rt/emul/compact/src/main/java/java/util/concurrent/ConcurrentHashMap.java
author Jaroslav Tulach <jtulach@netbeans.org>
Thu, 03 Oct 2013 15:40:35 +0200
branchjdk7-b147
changeset 1334 588d5bf7a560
child 1338 aa70afac4eca
permissions -rw-r--r--
Set of JDK classes needed to run javac
jtulach@1334
     1
/*
jtulach@1334
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jtulach@1334
     3
 *
jtulach@1334
     4
 * This code is free software; you can redistribute it and/or modify it
jtulach@1334
     5
 * under the terms of the GNU General Public License version 2 only, as
jtulach@1334
     6
 * published by the Free Software Foundation.  Oracle designates this
jtulach@1334
     7
 * particular file as subject to the "Classpath" exception as provided
jtulach@1334
     8
 * by Oracle in the LICENSE file that accompanied this code.
jtulach@1334
     9
 *
jtulach@1334
    10
 * This code is distributed in the hope that it will be useful, but WITHOUT
jtulach@1334
    11
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jtulach@1334
    12
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
jtulach@1334
    13
 * version 2 for more details (a copy is included in the LICENSE file that
jtulach@1334
    14
 * accompanied this code).
jtulach@1334
    15
 *
jtulach@1334
    16
 * You should have received a copy of the GNU General Public License version
jtulach@1334
    17
 * 2 along with this work; if not, write to the Free Software Foundation,
jtulach@1334
    18
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jtulach@1334
    19
 *
jtulach@1334
    20
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jtulach@1334
    21
 * or visit www.oracle.com if you need additional information or have any
jtulach@1334
    22
 * questions.
jtulach@1334
    23
 */
jtulach@1334
    24
jtulach@1334
    25
/*
jtulach@1334
    26
 * This file is available under and governed by the GNU General Public
jtulach@1334
    27
 * License version 2 only, as published by the Free Software Foundation.
jtulach@1334
    28
 * However, the following notice accompanied the original version of this
jtulach@1334
    29
 * file:
jtulach@1334
    30
 *
jtulach@1334
    31
 * Written by Doug Lea with assistance from members of JCP JSR-166
jtulach@1334
    32
 * Expert Group and released to the public domain, as explained at
jtulach@1334
    33
 * http://creativecommons.org/publicdomain/zero/1.0/
jtulach@1334
    34
 */
jtulach@1334
    35
jtulach@1334
    36
package java.util.concurrent;
jtulach@1334
    37
import java.util.concurrent.locks.*;
jtulach@1334
    38
import java.util.*;
jtulach@1334
    39
import java.io.Serializable;
jtulach@1334
    40
import java.io.IOException;
jtulach@1334
    41
import java.io.ObjectInputStream;
jtulach@1334
    42
import java.io.ObjectOutputStream;
jtulach@1334
    43
jtulach@1334
    44
/**
jtulach@1334
    45
 * A hash table supporting full concurrency of retrievals and
jtulach@1334
    46
 * adjustable expected concurrency for updates. This class obeys the
jtulach@1334
    47
 * same functional specification as {@link java.util.Hashtable}, and
jtulach@1334
    48
 * includes versions of methods corresponding to each method of
jtulach@1334
    49
 * <tt>Hashtable</tt>. However, even though all operations are
jtulach@1334
    50
 * thread-safe, retrieval operations do <em>not</em> entail locking,
jtulach@1334
    51
 * and there is <em>not</em> any support for locking the entire table
jtulach@1334
    52
 * in a way that prevents all access.  This class is fully
jtulach@1334
    53
 * interoperable with <tt>Hashtable</tt> in programs that rely on its
jtulach@1334
    54
 * thread safety but not on its synchronization details.
jtulach@1334
    55
 *
jtulach@1334
    56
 * <p> Retrieval operations (including <tt>get</tt>) generally do not
jtulach@1334
    57
 * block, so may overlap with update operations (including
jtulach@1334
    58
 * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
jtulach@1334
    59
 * of the most recently <em>completed</em> update operations holding
jtulach@1334
    60
 * upon their onset.  For aggregate operations such as <tt>putAll</tt>
jtulach@1334
    61
 * and <tt>clear</tt>, concurrent retrievals may reflect insertion or
jtulach@1334
    62
 * removal of only some entries.  Similarly, Iterators and
jtulach@1334
    63
 * Enumerations return elements reflecting the state of the hash table
jtulach@1334
    64
 * at some point at or since the creation of the iterator/enumeration.
jtulach@1334
    65
 * They do <em>not</em> throw {@link ConcurrentModificationException}.
jtulach@1334
    66
 * However, iterators are designed to be used by only one thread at a time.
jtulach@1334
    67
 *
jtulach@1334
    68
 * <p> The allowed concurrency among update operations is guided by
jtulach@1334
    69
 * the optional <tt>concurrencyLevel</tt> constructor argument
jtulach@1334
    70
 * (default <tt>16</tt>), which is used as a hint for internal sizing.  The
jtulach@1334
    71
 * table is internally partitioned to try to permit the indicated
jtulach@1334
    72
 * number of concurrent updates without contention. Because placement
jtulach@1334
    73
 * in hash tables is essentially random, the actual concurrency will
jtulach@1334
    74
 * vary.  Ideally, you should choose a value to accommodate as many
jtulach@1334
    75
 * threads as will ever concurrently modify the table. Using a
jtulach@1334
    76
 * significantly higher value than you need can waste space and time,
jtulach@1334
    77
 * and a significantly lower value can lead to thread contention. But
jtulach@1334
    78
 * overestimates and underestimates within an order of magnitude do
jtulach@1334
    79
 * not usually have much noticeable impact. A value of one is
jtulach@1334
    80
 * appropriate when it is known that only one thread will modify and
jtulach@1334
    81
 * all others will only read. Also, resizing this or any other kind of
jtulach@1334
    82
 * hash table is a relatively slow operation, so, when possible, it is
jtulach@1334
    83
 * a good idea to provide estimates of expected table sizes in
jtulach@1334
    84
 * constructors.
jtulach@1334
    85
 *
jtulach@1334
    86
 * <p>This class and its views and iterators implement all of the
jtulach@1334
    87
 * <em>optional</em> methods of the {@link Map} and {@link Iterator}
jtulach@1334
    88
 * interfaces.
jtulach@1334
    89
 *
jtulach@1334
    90
 * <p> Like {@link Hashtable} but unlike {@link HashMap}, this class
jtulach@1334
    91
 * does <em>not</em> allow <tt>null</tt> to be used as a key or value.
jtulach@1334
    92
 *
jtulach@1334
    93
 * <p>This class is a member of the
jtulach@1334
    94
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
jtulach@1334
    95
 * Java Collections Framework</a>.
jtulach@1334
    96
 *
jtulach@1334
    97
 * @since 1.5
jtulach@1334
    98
 * @author Doug Lea
jtulach@1334
    99
 * @param <K> the type of keys maintained by this map
jtulach@1334
   100
 * @param <V> the type of mapped values
jtulach@1334
   101
 */
jtulach@1334
   102
public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
jtulach@1334
   103
        implements ConcurrentMap<K, V>, Serializable {
jtulach@1334
   104
    private static final long serialVersionUID = 7249069246763182397L;
jtulach@1334
   105
jtulach@1334
   106
    /*
jtulach@1334
   107
     * The basic strategy is to subdivide the table among Segments,
jtulach@1334
   108
     * each of which itself is a concurrently readable hash table.  To
jtulach@1334
   109
     * reduce footprint, all but one segments are constructed only
jtulach@1334
   110
     * when first needed (see ensureSegment). To maintain visibility
jtulach@1334
   111
     * in the presence of lazy construction, accesses to segments as
jtulach@1334
   112
     * well as elements of segment's table must use volatile access,
jtulach@1334
   113
     * which is done via Unsafe within methods segmentAt etc
jtulach@1334
   114
     * below. These provide the functionality of AtomicReferenceArrays
jtulach@1334
   115
     * but reduce the levels of indirection. Additionally,
jtulach@1334
   116
     * volatile-writes of table elements and entry "next" fields
jtulach@1334
   117
     * within locked operations use the cheaper "lazySet" forms of
jtulach@1334
   118
     * writes (via putOrderedObject) because these writes are always
jtulach@1334
   119
     * followed by lock releases that maintain sequential consistency
jtulach@1334
   120
     * of table updates.
jtulach@1334
   121
     *
jtulach@1334
   122
     * Historical note: The previous version of this class relied
jtulach@1334
   123
     * heavily on "final" fields, which avoided some volatile reads at
jtulach@1334
   124
     * the expense of a large initial footprint.  Some remnants of
jtulach@1334
   125
     * that design (including forced construction of segment 0) exist
jtulach@1334
   126
     * to ensure serialization compatibility.
jtulach@1334
   127
     */
jtulach@1334
   128
jtulach@1334
   129
    /* ---------------- Constants -------------- */
jtulach@1334
   130
jtulach@1334
   131
    /**
jtulach@1334
   132
     * The default initial capacity for this table,
jtulach@1334
   133
     * used when not otherwise specified in a constructor.
jtulach@1334
   134
     */
jtulach@1334
   135
    static final int DEFAULT_INITIAL_CAPACITY = 16;
jtulach@1334
   136
jtulach@1334
   137
    /**
jtulach@1334
   138
     * The default load factor for this table, used when not
jtulach@1334
   139
     * otherwise specified in a constructor.
jtulach@1334
   140
     */
jtulach@1334
   141
    static final float DEFAULT_LOAD_FACTOR = 0.75f;
jtulach@1334
   142
jtulach@1334
   143
    /**
jtulach@1334
   144
     * The default concurrency level for this table, used when not
jtulach@1334
   145
     * otherwise specified in a constructor.
jtulach@1334
   146
     */
jtulach@1334
   147
    static final int DEFAULT_CONCURRENCY_LEVEL = 16;
jtulach@1334
   148
jtulach@1334
   149
    /**
jtulach@1334
   150
     * The maximum capacity, used if a higher value is implicitly
jtulach@1334
   151
     * specified by either of the constructors with arguments.  MUST
jtulach@1334
   152
     * be a power of two <= 1<<30 to ensure that entries are indexable
jtulach@1334
   153
     * using ints.
jtulach@1334
   154
     */
jtulach@1334
   155
    static final int MAXIMUM_CAPACITY = 1 << 30;
jtulach@1334
   156
jtulach@1334
   157
    /**
jtulach@1334
   158
     * The minimum capacity for per-segment tables.  Must be a power
jtulach@1334
   159
     * of two, at least two to avoid immediate resizing on next use
jtulach@1334
   160
     * after lazy construction.
jtulach@1334
   161
     */
jtulach@1334
   162
    static final int MIN_SEGMENT_TABLE_CAPACITY = 2;
jtulach@1334
   163
jtulach@1334
   164
    /**
jtulach@1334
   165
     * The maximum number of segments to allow; used to bound
jtulach@1334
   166
     * constructor arguments. Must be power of two less than 1 << 24.
jtulach@1334
   167
     */
jtulach@1334
   168
    static final int MAX_SEGMENTS = 1 << 16; // slightly conservative
jtulach@1334
   169
jtulach@1334
   170
    /**
jtulach@1334
   171
     * Number of unsynchronized retries in size and containsValue
jtulach@1334
   172
     * methods before resorting to locking. This is used to avoid
jtulach@1334
   173
     * unbounded retries if tables undergo continuous modification
jtulach@1334
   174
     * which would make it impossible to obtain an accurate result.
jtulach@1334
   175
     */
jtulach@1334
   176
    static final int RETRIES_BEFORE_LOCK = 2;
jtulach@1334
   177
jtulach@1334
   178
    /* ---------------- Fields -------------- */
jtulach@1334
   179
jtulach@1334
   180
    /**
jtulach@1334
   181
     * Mask value for indexing into segments. The upper bits of a
jtulach@1334
   182
     * key's hash code are used to choose the segment.
jtulach@1334
   183
     */
jtulach@1334
   184
    final int segmentMask;
jtulach@1334
   185
jtulach@1334
   186
    /**
jtulach@1334
   187
     * Shift value for indexing within segments.
jtulach@1334
   188
     */
jtulach@1334
   189
    final int segmentShift;
jtulach@1334
   190
jtulach@1334
   191
    /**
jtulach@1334
   192
     * The segments, each of which is a specialized hash table.
jtulach@1334
   193
     */
jtulach@1334
   194
    final Segment<K,V>[] segments;
jtulach@1334
   195
jtulach@1334
   196
    transient Set<K> keySet;
jtulach@1334
   197
    transient Set<Map.Entry<K,V>> entrySet;
jtulach@1334
   198
    transient Collection<V> values;
jtulach@1334
   199
jtulach@1334
   200
    /**
jtulach@1334
   201
     * ConcurrentHashMap list entry. Note that this is never exported
jtulach@1334
   202
     * out as a user-visible Map.Entry.
jtulach@1334
   203
     */
jtulach@1334
   204
    static final class HashEntry<K,V> {
jtulach@1334
   205
        final int hash;
jtulach@1334
   206
        final K key;
jtulach@1334
   207
        volatile V value;
jtulach@1334
   208
        volatile HashEntry<K,V> next;
jtulach@1334
   209
jtulach@1334
   210
        HashEntry(int hash, K key, V value, HashEntry<K,V> next) {
jtulach@1334
   211
            this.hash = hash;
jtulach@1334
   212
            this.key = key;
jtulach@1334
   213
            this.value = value;
jtulach@1334
   214
            this.next = next;
jtulach@1334
   215
        }
jtulach@1334
   216
jtulach@1334
   217
        /**
jtulach@1334
   218
         * Sets next field with volatile write semantics.  (See above
jtulach@1334
   219
         * about use of putOrderedObject.)
jtulach@1334
   220
         */
jtulach@1334
   221
        final void setNext(HashEntry<K,V> n) {
jtulach@1334
   222
            UNSAFE.putOrderedObject(this, nextOffset, n);
jtulach@1334
   223
        }
jtulach@1334
   224
jtulach@1334
   225
        // Unsafe mechanics
jtulach@1334
   226
        static final sun.misc.Unsafe UNSAFE;
jtulach@1334
   227
        static final long nextOffset;
jtulach@1334
   228
        static {
jtulach@1334
   229
            try {
jtulach@1334
   230
                UNSAFE = sun.misc.Unsafe.getUnsafe();
jtulach@1334
   231
                Class k = HashEntry.class;
jtulach@1334
   232
                nextOffset = UNSAFE.objectFieldOffset
jtulach@1334
   233
                    (k.getDeclaredField("next"));
jtulach@1334
   234
            } catch (Exception e) {
jtulach@1334
   235
                throw new Error(e);
jtulach@1334
   236
            }
jtulach@1334
   237
        }
jtulach@1334
   238
    }
jtulach@1334
   239
jtulach@1334
   240
    /**
jtulach@1334
   241
     * Gets the ith element of given table (if nonnull) with volatile
jtulach@1334
   242
     * read semantics. Note: This is manually integrated into a few
jtulach@1334
   243
     * performance-sensitive methods to reduce call overhead.
jtulach@1334
   244
     */
jtulach@1334
   245
    @SuppressWarnings("unchecked")
jtulach@1334
   246
    static final <K,V> HashEntry<K,V> entryAt(HashEntry<K,V>[] tab, int i) {
jtulach@1334
   247
        return (tab == null) ? null :
jtulach@1334
   248
            (HashEntry<K,V>) UNSAFE.getObjectVolatile
jtulach@1334
   249
            (tab, ((long)i << TSHIFT) + TBASE);
jtulach@1334
   250
    }
jtulach@1334
   251
jtulach@1334
   252
    /**
jtulach@1334
   253
     * Sets the ith element of given table, with volatile write
jtulach@1334
   254
     * semantics. (See above about use of putOrderedObject.)
jtulach@1334
   255
     */
jtulach@1334
   256
    static final <K,V> void setEntryAt(HashEntry<K,V>[] tab, int i,
jtulach@1334
   257
                                       HashEntry<K,V> e) {
jtulach@1334
   258
        UNSAFE.putOrderedObject(tab, ((long)i << TSHIFT) + TBASE, e);
jtulach@1334
   259
    }
jtulach@1334
   260
jtulach@1334
   261
    /**
jtulach@1334
   262
     * Applies a supplemental hash function to a given hashCode, which
jtulach@1334
   263
     * defends against poor quality hash functions.  This is critical
jtulach@1334
   264
     * because ConcurrentHashMap uses power-of-two length hash tables,
jtulach@1334
   265
     * that otherwise encounter collisions for hashCodes that do not
jtulach@1334
   266
     * differ in lower or upper bits.
jtulach@1334
   267
     */
jtulach@1334
   268
    private static int hash(int h) {
jtulach@1334
   269
        // Spread bits to regularize both segment and index locations,
jtulach@1334
   270
        // using variant of single-word Wang/Jenkins hash.
jtulach@1334
   271
        h += (h <<  15) ^ 0xffffcd7d;
jtulach@1334
   272
        h ^= (h >>> 10);
jtulach@1334
   273
        h += (h <<   3);
jtulach@1334
   274
        h ^= (h >>>  6);
jtulach@1334
   275
        h += (h <<   2) + (h << 14);
jtulach@1334
   276
        return h ^ (h >>> 16);
jtulach@1334
   277
    }
jtulach@1334
   278
jtulach@1334
   279
    /**
jtulach@1334
   280
     * Segments are specialized versions of hash tables.  This
jtulach@1334
   281
     * subclasses from ReentrantLock opportunistically, just to
jtulach@1334
   282
     * simplify some locking and avoid separate construction.
jtulach@1334
   283
     */
jtulach@1334
   284
    static final class Segment<K,V> extends ReentrantLock implements Serializable {
jtulach@1334
   285
        /*
jtulach@1334
   286
         * Segments maintain a table of entry lists that are always
jtulach@1334
   287
         * kept in a consistent state, so can be read (via volatile
jtulach@1334
   288
         * reads of segments and tables) without locking.  This
jtulach@1334
   289
         * requires replicating nodes when necessary during table
jtulach@1334
   290
         * resizing, so the old lists can be traversed by readers
jtulach@1334
   291
         * still using old version of table.
jtulach@1334
   292
         *
jtulach@1334
   293
         * This class defines only mutative methods requiring locking.
jtulach@1334
   294
         * Except as noted, the methods of this class perform the
jtulach@1334
   295
         * per-segment versions of ConcurrentHashMap methods.  (Other
jtulach@1334
   296
         * methods are integrated directly into ConcurrentHashMap
jtulach@1334
   297
         * methods.) These mutative methods use a form of controlled
jtulach@1334
   298
         * spinning on contention via methods scanAndLock and
jtulach@1334
   299
         * scanAndLockForPut. These intersperse tryLocks with
jtulach@1334
   300
         * traversals to locate nodes.  The main benefit is to absorb
jtulach@1334
   301
         * cache misses (which are very common for hash tables) while
jtulach@1334
   302
         * obtaining locks so that traversal is faster once
jtulach@1334
   303
         * acquired. We do not actually use the found nodes since they
jtulach@1334
   304
         * must be re-acquired under lock anyway to ensure sequential
jtulach@1334
   305
         * consistency of updates (and in any case may be undetectably
jtulach@1334
   306
         * stale), but they will normally be much faster to re-locate.
jtulach@1334
   307
         * Also, scanAndLockForPut speculatively creates a fresh node
jtulach@1334
   308
         * to use in put if no node is found.
jtulach@1334
   309
         */
jtulach@1334
   310
jtulach@1334
   311
        private static final long serialVersionUID = 2249069246763182397L;
jtulach@1334
   312
jtulach@1334
   313
        /**
jtulach@1334
   314
         * The maximum number of times to tryLock in a prescan before
jtulach@1334
   315
         * possibly blocking on acquire in preparation for a locked
jtulach@1334
   316
         * segment operation. On multiprocessors, using a bounded
jtulach@1334
   317
         * number of retries maintains cache acquired while locating
jtulach@1334
   318
         * nodes.
jtulach@1334
   319
         */
jtulach@1334
   320
        static final int MAX_SCAN_RETRIES =
jtulach@1334
   321
            Runtime.getRuntime().availableProcessors() > 1 ? 64 : 1;
jtulach@1334
   322
jtulach@1334
   323
        /**
jtulach@1334
   324
         * The per-segment table. Elements are accessed via
jtulach@1334
   325
         * entryAt/setEntryAt providing volatile semantics.
jtulach@1334
   326
         */
jtulach@1334
   327
        transient volatile HashEntry<K,V>[] table;
jtulach@1334
   328
jtulach@1334
   329
        /**
jtulach@1334
   330
         * The number of elements. Accessed only either within locks
jtulach@1334
   331
         * or among other volatile reads that maintain visibility.
jtulach@1334
   332
         */
jtulach@1334
   333
        transient int count;
jtulach@1334
   334
jtulach@1334
   335
        /**
jtulach@1334
   336
         * The total number of mutative operations in this segment.
jtulach@1334
   337
         * Even though this may overflows 32 bits, it provides
jtulach@1334
   338
         * sufficient accuracy for stability checks in CHM isEmpty()
jtulach@1334
   339
         * and size() methods.  Accessed only either within locks or
jtulach@1334
   340
         * among other volatile reads that maintain visibility.
jtulach@1334
   341
         */
jtulach@1334
   342
        transient int modCount;
jtulach@1334
   343
jtulach@1334
   344
        /**
jtulach@1334
   345
         * The table is rehashed when its size exceeds this threshold.
jtulach@1334
   346
         * (The value of this field is always <tt>(int)(capacity *
jtulach@1334
   347
         * loadFactor)</tt>.)
jtulach@1334
   348
         */
jtulach@1334
   349
        transient int threshold;
jtulach@1334
   350
jtulach@1334
   351
        /**
jtulach@1334
   352
         * The load factor for the hash table.  Even though this value
jtulach@1334
   353
         * is same for all segments, it is replicated to avoid needing
jtulach@1334
   354
         * links to outer object.
jtulach@1334
   355
         * @serial
jtulach@1334
   356
         */
jtulach@1334
   357
        final float loadFactor;
jtulach@1334
   358
jtulach@1334
   359
        Segment(float lf, int threshold, HashEntry<K,V>[] tab) {
jtulach@1334
   360
            this.loadFactor = lf;
jtulach@1334
   361
            this.threshold = threshold;
jtulach@1334
   362
            this.table = tab;
jtulach@1334
   363
        }
jtulach@1334
   364
jtulach@1334
   365
        final V put(K key, int hash, V value, boolean onlyIfAbsent) {
jtulach@1334
   366
            HashEntry<K,V> node = tryLock() ? null :
jtulach@1334
   367
                scanAndLockForPut(key, hash, value);
jtulach@1334
   368
            V oldValue;
jtulach@1334
   369
            try {
jtulach@1334
   370
                HashEntry<K,V>[] tab = table;
jtulach@1334
   371
                int index = (tab.length - 1) & hash;
jtulach@1334
   372
                HashEntry<K,V> first = entryAt(tab, index);
jtulach@1334
   373
                for (HashEntry<K,V> e = first;;) {
jtulach@1334
   374
                    if (e != null) {
jtulach@1334
   375
                        K k;
jtulach@1334
   376
                        if ((k = e.key) == key ||
jtulach@1334
   377
                            (e.hash == hash && key.equals(k))) {
jtulach@1334
   378
                            oldValue = e.value;
jtulach@1334
   379
                            if (!onlyIfAbsent) {
jtulach@1334
   380
                                e.value = value;
jtulach@1334
   381
                                ++modCount;
jtulach@1334
   382
                            }
jtulach@1334
   383
                            break;
jtulach@1334
   384
                        }
jtulach@1334
   385
                        e = e.next;
jtulach@1334
   386
                    }
jtulach@1334
   387
                    else {
jtulach@1334
   388
                        if (node != null)
jtulach@1334
   389
                            node.setNext(first);
jtulach@1334
   390
                        else
jtulach@1334
   391
                            node = new HashEntry<K,V>(hash, key, value, first);
jtulach@1334
   392
                        int c = count + 1;
jtulach@1334
   393
                        if (c > threshold && tab.length < MAXIMUM_CAPACITY)
jtulach@1334
   394
                            rehash(node);
jtulach@1334
   395
                        else
jtulach@1334
   396
                            setEntryAt(tab, index, node);
jtulach@1334
   397
                        ++modCount;
jtulach@1334
   398
                        count = c;
jtulach@1334
   399
                        oldValue = null;
jtulach@1334
   400
                        break;
jtulach@1334
   401
                    }
jtulach@1334
   402
                }
jtulach@1334
   403
            } finally {
jtulach@1334
   404
                unlock();
jtulach@1334
   405
            }
jtulach@1334
   406
            return oldValue;
jtulach@1334
   407
        }
jtulach@1334
   408
jtulach@1334
   409
        /**
jtulach@1334
   410
         * Doubles size of table and repacks entries, also adding the
jtulach@1334
   411
         * given node to new table
jtulach@1334
   412
         */
jtulach@1334
   413
        @SuppressWarnings("unchecked")
jtulach@1334
   414
        private void rehash(HashEntry<K,V> node) {
jtulach@1334
   415
            /*
jtulach@1334
   416
             * Reclassify nodes in each list to new table.  Because we
jtulach@1334
   417
             * are using power-of-two expansion, the elements from
jtulach@1334
   418
             * each bin must either stay at same index, or move with a
jtulach@1334
   419
             * power of two offset. We eliminate unnecessary node
jtulach@1334
   420
             * creation by catching cases where old nodes can be
jtulach@1334
   421
             * reused because their next fields won't change.
jtulach@1334
   422
             * Statistically, at the default threshold, only about
jtulach@1334
   423
             * one-sixth of them need cloning when a table
jtulach@1334
   424
             * doubles. The nodes they replace will be garbage
jtulach@1334
   425
             * collectable as soon as they are no longer referenced by
jtulach@1334
   426
             * any reader thread that may be in the midst of
jtulach@1334
   427
             * concurrently traversing table. Entry accesses use plain
jtulach@1334
   428
             * array indexing because they are followed by volatile
jtulach@1334
   429
             * table write.
jtulach@1334
   430
             */
jtulach@1334
   431
            HashEntry<K,V>[] oldTable = table;
jtulach@1334
   432
            int oldCapacity = oldTable.length;
jtulach@1334
   433
            int newCapacity = oldCapacity << 1;
jtulach@1334
   434
            threshold = (int)(newCapacity * loadFactor);
jtulach@1334
   435
            HashEntry<K,V>[] newTable =
jtulach@1334
   436
                (HashEntry<K,V>[]) new HashEntry[newCapacity];
jtulach@1334
   437
            int sizeMask = newCapacity - 1;
jtulach@1334
   438
            for (int i = 0; i < oldCapacity ; i++) {
jtulach@1334
   439
                HashEntry<K,V> e = oldTable[i];
jtulach@1334
   440
                if (e != null) {
jtulach@1334
   441
                    HashEntry<K,V> next = e.next;
jtulach@1334
   442
                    int idx = e.hash & sizeMask;
jtulach@1334
   443
                    if (next == null)   //  Single node on list
jtulach@1334
   444
                        newTable[idx] = e;
jtulach@1334
   445
                    else { // Reuse consecutive sequence at same slot
jtulach@1334
   446
                        HashEntry<K,V> lastRun = e;
jtulach@1334
   447
                        int lastIdx = idx;
jtulach@1334
   448
                        for (HashEntry<K,V> last = next;
jtulach@1334
   449
                             last != null;
jtulach@1334
   450
                             last = last.next) {
jtulach@1334
   451
                            int k = last.hash & sizeMask;
jtulach@1334
   452
                            if (k != lastIdx) {
jtulach@1334
   453
                                lastIdx = k;
jtulach@1334
   454
                                lastRun = last;
jtulach@1334
   455
                            }
jtulach@1334
   456
                        }
jtulach@1334
   457
                        newTable[lastIdx] = lastRun;
jtulach@1334
   458
                        // Clone remaining nodes
jtulach@1334
   459
                        for (HashEntry<K,V> p = e; p != lastRun; p = p.next) {
jtulach@1334
   460
                            V v = p.value;
jtulach@1334
   461
                            int h = p.hash;
jtulach@1334
   462
                            int k = h & sizeMask;
jtulach@1334
   463
                            HashEntry<K,V> n = newTable[k];
jtulach@1334
   464
                            newTable[k] = new HashEntry<K,V>(h, p.key, v, n);
jtulach@1334
   465
                        }
jtulach@1334
   466
                    }
jtulach@1334
   467
                }
jtulach@1334
   468
            }
jtulach@1334
   469
            int nodeIndex = node.hash & sizeMask; // add the new node
jtulach@1334
   470
            node.setNext(newTable[nodeIndex]);
jtulach@1334
   471
            newTable[nodeIndex] = node;
jtulach@1334
   472
            table = newTable;
jtulach@1334
   473
        }
jtulach@1334
   474
jtulach@1334
   475
        /**
jtulach@1334
   476
         * Scans for a node containing given key while trying to
jtulach@1334
   477
         * acquire lock, creating and returning one if not found. Upon
jtulach@1334
   478
         * return, guarantees that lock is held. UNlike in most
jtulach@1334
   479
         * methods, calls to method equals are not screened: Since
jtulach@1334
   480
         * traversal speed doesn't matter, we might as well help warm
jtulach@1334
   481
         * up the associated code and accesses as well.
jtulach@1334
   482
         *
jtulach@1334
   483
         * @return a new node if key not found, else null
jtulach@1334
   484
         */
jtulach@1334
   485
        private HashEntry<K,V> scanAndLockForPut(K key, int hash, V value) {
jtulach@1334
   486
            HashEntry<K,V> first = entryForHash(this, hash);
jtulach@1334
   487
            HashEntry<K,V> e = first;
jtulach@1334
   488
            HashEntry<K,V> node = null;
jtulach@1334
   489
            int retries = -1; // negative while locating node
jtulach@1334
   490
            while (!tryLock()) {
jtulach@1334
   491
                HashEntry<K,V> f; // to recheck first below
jtulach@1334
   492
                if (retries < 0) {
jtulach@1334
   493
                    if (e == null) {
jtulach@1334
   494
                        if (node == null) // speculatively create node
jtulach@1334
   495
                            node = new HashEntry<K,V>(hash, key, value, null);
jtulach@1334
   496
                        retries = 0;
jtulach@1334
   497
                    }
jtulach@1334
   498
                    else if (key.equals(e.key))
jtulach@1334
   499
                        retries = 0;
jtulach@1334
   500
                    else
jtulach@1334
   501
                        e = e.next;
jtulach@1334
   502
                }
jtulach@1334
   503
                else if (++retries > MAX_SCAN_RETRIES) {
jtulach@1334
   504
                    lock();
jtulach@1334
   505
                    break;
jtulach@1334
   506
                }
jtulach@1334
   507
                else if ((retries & 1) == 0 &&
jtulach@1334
   508
                         (f = entryForHash(this, hash)) != first) {
jtulach@1334
   509
                    e = first = f; // re-traverse if entry changed
jtulach@1334
   510
                    retries = -1;
jtulach@1334
   511
                }
jtulach@1334
   512
            }
jtulach@1334
   513
            return node;
jtulach@1334
   514
        }
jtulach@1334
   515
jtulach@1334
   516
        /**
jtulach@1334
   517
         * Scans for a node containing the given key while trying to
jtulach@1334
   518
         * acquire lock for a remove or replace operation. Upon
jtulach@1334
   519
         * return, guarantees that lock is held.  Note that we must
jtulach@1334
   520
         * lock even if the key is not found, to ensure sequential
jtulach@1334
   521
         * consistency of updates.
jtulach@1334
   522
         */
jtulach@1334
   523
        private void scanAndLock(Object key, int hash) {
jtulach@1334
   524
            // similar to but simpler than scanAndLockForPut
jtulach@1334
   525
            HashEntry<K,V> first = entryForHash(this, hash);
jtulach@1334
   526
            HashEntry<K,V> e = first;
jtulach@1334
   527
            int retries = -1;
jtulach@1334
   528
            while (!tryLock()) {
jtulach@1334
   529
                HashEntry<K,V> f;
jtulach@1334
   530
                if (retries < 0) {
jtulach@1334
   531
                    if (e == null || key.equals(e.key))
jtulach@1334
   532
                        retries = 0;
jtulach@1334
   533
                    else
jtulach@1334
   534
                        e = e.next;
jtulach@1334
   535
                }
jtulach@1334
   536
                else if (++retries > MAX_SCAN_RETRIES) {
jtulach@1334
   537
                    lock();
jtulach@1334
   538
                    break;
jtulach@1334
   539
                }
jtulach@1334
   540
                else if ((retries & 1) == 0 &&
jtulach@1334
   541
                         (f = entryForHash(this, hash)) != first) {
jtulach@1334
   542
                    e = first = f;
jtulach@1334
   543
                    retries = -1;
jtulach@1334
   544
                }
jtulach@1334
   545
            }
jtulach@1334
   546
        }
jtulach@1334
   547
jtulach@1334
   548
        /**
jtulach@1334
   549
         * Remove; match on key only if value null, else match both.
jtulach@1334
   550
         */
jtulach@1334
   551
        final V remove(Object key, int hash, Object value) {
jtulach@1334
   552
            if (!tryLock())
jtulach@1334
   553
                scanAndLock(key, hash);
jtulach@1334
   554
            V oldValue = null;
jtulach@1334
   555
            try {
jtulach@1334
   556
                HashEntry<K,V>[] tab = table;
jtulach@1334
   557
                int index = (tab.length - 1) & hash;
jtulach@1334
   558
                HashEntry<K,V> e = entryAt(tab, index);
jtulach@1334
   559
                HashEntry<K,V> pred = null;
jtulach@1334
   560
                while (e != null) {
jtulach@1334
   561
                    K k;
jtulach@1334
   562
                    HashEntry<K,V> next = e.next;
jtulach@1334
   563
                    if ((k = e.key) == key ||
jtulach@1334
   564
                        (e.hash == hash && key.equals(k))) {
jtulach@1334
   565
                        V v = e.value;
jtulach@1334
   566
                        if (value == null || value == v || value.equals(v)) {
jtulach@1334
   567
                            if (pred == null)
jtulach@1334
   568
                                setEntryAt(tab, index, next);
jtulach@1334
   569
                            else
jtulach@1334
   570
                                pred.setNext(next);
jtulach@1334
   571
                            ++modCount;
jtulach@1334
   572
                            --count;
jtulach@1334
   573
                            oldValue = v;
jtulach@1334
   574
                        }
jtulach@1334
   575
                        break;
jtulach@1334
   576
                    }
jtulach@1334
   577
                    pred = e;
jtulach@1334
   578
                    e = next;
jtulach@1334
   579
                }
jtulach@1334
   580
            } finally {
jtulach@1334
   581
                unlock();
jtulach@1334
   582
            }
jtulach@1334
   583
            return oldValue;
jtulach@1334
   584
        }
jtulach@1334
   585
jtulach@1334
   586
        final boolean replace(K key, int hash, V oldValue, V newValue) {
jtulach@1334
   587
            if (!tryLock())
jtulach@1334
   588
                scanAndLock(key, hash);
jtulach@1334
   589
            boolean replaced = false;
jtulach@1334
   590
            try {
jtulach@1334
   591
                HashEntry<K,V> e;
jtulach@1334
   592
                for (e = entryForHash(this, hash); e != null; e = e.next) {
jtulach@1334
   593
                    K k;
jtulach@1334
   594
                    if ((k = e.key) == key ||
jtulach@1334
   595
                        (e.hash == hash && key.equals(k))) {
jtulach@1334
   596
                        if (oldValue.equals(e.value)) {
jtulach@1334
   597
                            e.value = newValue;
jtulach@1334
   598
                            ++modCount;
jtulach@1334
   599
                            replaced = true;
jtulach@1334
   600
                        }
jtulach@1334
   601
                        break;
jtulach@1334
   602
                    }
jtulach@1334
   603
                }
jtulach@1334
   604
            } finally {
jtulach@1334
   605
                unlock();
jtulach@1334
   606
            }
jtulach@1334
   607
            return replaced;
jtulach@1334
   608
        }
jtulach@1334
   609
jtulach@1334
   610
        final V replace(K key, int hash, V value) {
jtulach@1334
   611
            if (!tryLock())
jtulach@1334
   612
                scanAndLock(key, hash);
jtulach@1334
   613
            V oldValue = null;
jtulach@1334
   614
            try {
jtulach@1334
   615
                HashEntry<K,V> e;
jtulach@1334
   616
                for (e = entryForHash(this, hash); e != null; e = e.next) {
jtulach@1334
   617
                    K k;
jtulach@1334
   618
                    if ((k = e.key) == key ||
jtulach@1334
   619
                        (e.hash == hash && key.equals(k))) {
jtulach@1334
   620
                        oldValue = e.value;
jtulach@1334
   621
                        e.value = value;
jtulach@1334
   622
                        ++modCount;
jtulach@1334
   623
                        break;
jtulach@1334
   624
                    }
jtulach@1334
   625
                }
jtulach@1334
   626
            } finally {
jtulach@1334
   627
                unlock();
jtulach@1334
   628
            }
jtulach@1334
   629
            return oldValue;
jtulach@1334
   630
        }
jtulach@1334
   631
jtulach@1334
   632
        final void clear() {
jtulach@1334
   633
            lock();
jtulach@1334
   634
            try {
jtulach@1334
   635
                HashEntry<K,V>[] tab = table;
jtulach@1334
   636
                for (int i = 0; i < tab.length ; i++)
jtulach@1334
   637
                    setEntryAt(tab, i, null);
jtulach@1334
   638
                ++modCount;
jtulach@1334
   639
                count = 0;
jtulach@1334
   640
            } finally {
jtulach@1334
   641
                unlock();
jtulach@1334
   642
            }
jtulach@1334
   643
        }
jtulach@1334
   644
    }
jtulach@1334
   645
jtulach@1334
   646
    // Accessing segments
jtulach@1334
   647
jtulach@1334
   648
    /**
jtulach@1334
   649
     * Gets the jth element of given segment array (if nonnull) with
jtulach@1334
   650
     * volatile element access semantics via Unsafe. (The null check
jtulach@1334
   651
     * can trigger harmlessly only during deserialization.) Note:
jtulach@1334
   652
     * because each element of segments array is set only once (using
jtulach@1334
   653
     * fully ordered writes), some performance-sensitive methods rely
jtulach@1334
   654
     * on this method only as a recheck upon null reads.
jtulach@1334
   655
     */
jtulach@1334
   656
    @SuppressWarnings("unchecked")
jtulach@1334
   657
    static final <K,V> Segment<K,V> segmentAt(Segment<K,V>[] ss, int j) {
jtulach@1334
   658
        long u = (j << SSHIFT) + SBASE;
jtulach@1334
   659
        return ss == null ? null :
jtulach@1334
   660
            (Segment<K,V>) UNSAFE.getObjectVolatile(ss, u);
jtulach@1334
   661
    }
jtulach@1334
   662
jtulach@1334
   663
    /**
jtulach@1334
   664
     * Returns the segment for the given index, creating it and
jtulach@1334
   665
     * recording in segment table (via CAS) if not already present.
jtulach@1334
   666
     *
jtulach@1334
   667
     * @param k the index
jtulach@1334
   668
     * @return the segment
jtulach@1334
   669
     */
jtulach@1334
   670
    @SuppressWarnings("unchecked")
jtulach@1334
   671
    private Segment<K,V> ensureSegment(int k) {
jtulach@1334
   672
        final Segment<K,V>[] ss = this.segments;
jtulach@1334
   673
        long u = (k << SSHIFT) + SBASE; // raw offset
jtulach@1334
   674
        Segment<K,V> seg;
jtulach@1334
   675
        if ((seg = (Segment<K,V>)UNSAFE.getObjectVolatile(ss, u)) == null) {
jtulach@1334
   676
            Segment<K,V> proto = ss[0]; // use segment 0 as prototype
jtulach@1334
   677
            int cap = proto.table.length;
jtulach@1334
   678
            float lf = proto.loadFactor;
jtulach@1334
   679
            int threshold = (int)(cap * lf);
jtulach@1334
   680
            HashEntry<K,V>[] tab = (HashEntry<K,V>[])new HashEntry[cap];
jtulach@1334
   681
            if ((seg = (Segment<K,V>)UNSAFE.getObjectVolatile(ss, u))
jtulach@1334
   682
                == null) { // recheck
jtulach@1334
   683
                Segment<K,V> s = new Segment<K,V>(lf, threshold, tab);
jtulach@1334
   684
                while ((seg = (Segment<K,V>)UNSAFE.getObjectVolatile(ss, u))
jtulach@1334
   685
                       == null) {
jtulach@1334
   686
                    if (UNSAFE.compareAndSwapObject(ss, u, null, seg = s))
jtulach@1334
   687
                        break;
jtulach@1334
   688
                }
jtulach@1334
   689
            }
jtulach@1334
   690
        }
jtulach@1334
   691
        return seg;
jtulach@1334
   692
    }
jtulach@1334
   693
jtulach@1334
   694
    // Hash-based segment and entry accesses
jtulach@1334
   695
jtulach@1334
   696
    /**
jtulach@1334
   697
     * Get the segment for the given hash
jtulach@1334
   698
     */
jtulach@1334
   699
    @SuppressWarnings("unchecked")
jtulach@1334
   700
    private Segment<K,V> segmentForHash(int h) {
jtulach@1334
   701
        long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE;
jtulach@1334
   702
        return (Segment<K,V>) UNSAFE.getObjectVolatile(segments, u);
jtulach@1334
   703
    }
jtulach@1334
   704
jtulach@1334
   705
    /**
jtulach@1334
   706
     * Gets the table entry for the given segment and hash
jtulach@1334
   707
     */
jtulach@1334
   708
    @SuppressWarnings("unchecked")
jtulach@1334
   709
    static final <K,V> HashEntry<K,V> entryForHash(Segment<K,V> seg, int h) {
jtulach@1334
   710
        HashEntry<K,V>[] tab;
jtulach@1334
   711
        return (seg == null || (tab = seg.table) == null) ? null :
jtulach@1334
   712
            (HashEntry<K,V>) UNSAFE.getObjectVolatile
jtulach@1334
   713
            (tab, ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE);
jtulach@1334
   714
    }
jtulach@1334
   715
jtulach@1334
   716
    /* ---------------- Public operations -------------- */
jtulach@1334
   717
jtulach@1334
   718
    /**
jtulach@1334
   719
     * Creates a new, empty map with the specified initial
jtulach@1334
   720
     * capacity, load factor and concurrency level.
jtulach@1334
   721
     *
jtulach@1334
   722
     * @param initialCapacity the initial capacity. The implementation
jtulach@1334
   723
     * performs internal sizing to accommodate this many elements.
jtulach@1334
   724
     * @param loadFactor  the load factor threshold, used to control resizing.
jtulach@1334
   725
     * Resizing may be performed when the average number of elements per
jtulach@1334
   726
     * bin exceeds this threshold.
jtulach@1334
   727
     * @param concurrencyLevel the estimated number of concurrently
jtulach@1334
   728
     * updating threads. The implementation performs internal sizing
jtulach@1334
   729
     * to try to accommodate this many threads.
jtulach@1334
   730
     * @throws IllegalArgumentException if the initial capacity is
jtulach@1334
   731
     * negative or the load factor or concurrencyLevel are
jtulach@1334
   732
     * nonpositive.
jtulach@1334
   733
     */
jtulach@1334
   734
    @SuppressWarnings("unchecked")
jtulach@1334
   735
    public ConcurrentHashMap(int initialCapacity,
jtulach@1334
   736
                             float loadFactor, int concurrencyLevel) {
jtulach@1334
   737
        if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
jtulach@1334
   738
            throw new IllegalArgumentException();
jtulach@1334
   739
        if (concurrencyLevel > MAX_SEGMENTS)
jtulach@1334
   740
            concurrencyLevel = MAX_SEGMENTS;
jtulach@1334
   741
        // Find power-of-two sizes best matching arguments
jtulach@1334
   742
        int sshift = 0;
jtulach@1334
   743
        int ssize = 1;
jtulach@1334
   744
        while (ssize < concurrencyLevel) {
jtulach@1334
   745
            ++sshift;
jtulach@1334
   746
            ssize <<= 1;
jtulach@1334
   747
        }
jtulach@1334
   748
        this.segmentShift = 32 - sshift;
jtulach@1334
   749
        this.segmentMask = ssize - 1;
jtulach@1334
   750
        if (initialCapacity > MAXIMUM_CAPACITY)
jtulach@1334
   751
            initialCapacity = MAXIMUM_CAPACITY;
jtulach@1334
   752
        int c = initialCapacity / ssize;
jtulach@1334
   753
        if (c * ssize < initialCapacity)
jtulach@1334
   754
            ++c;
jtulach@1334
   755
        int cap = MIN_SEGMENT_TABLE_CAPACITY;
jtulach@1334
   756
        while (cap < c)
jtulach@1334
   757
            cap <<= 1;
jtulach@1334
   758
        // create segments and segments[0]
jtulach@1334
   759
        Segment<K,V> s0 =
jtulach@1334
   760
            new Segment<K,V>(loadFactor, (int)(cap * loadFactor),
jtulach@1334
   761
                             (HashEntry<K,V>[])new HashEntry[cap]);
jtulach@1334
   762
        Segment<K,V>[] ss = (Segment<K,V>[])new Segment[ssize];
jtulach@1334
   763
        UNSAFE.putOrderedObject(ss, SBASE, s0); // ordered write of segments[0]
jtulach@1334
   764
        this.segments = ss;
jtulach@1334
   765
    }
jtulach@1334
   766
jtulach@1334
   767
    /**
jtulach@1334
   768
     * Creates a new, empty map with the specified initial capacity
jtulach@1334
   769
     * and load factor and with the default concurrencyLevel (16).
jtulach@1334
   770
     *
jtulach@1334
   771
     * @param initialCapacity The implementation performs internal
jtulach@1334
   772
     * sizing to accommodate this many elements.
jtulach@1334
   773
     * @param loadFactor  the load factor threshold, used to control resizing.
jtulach@1334
   774
     * Resizing may be performed when the average number of elements per
jtulach@1334
   775
     * bin exceeds this threshold.
jtulach@1334
   776
     * @throws IllegalArgumentException if the initial capacity of
jtulach@1334
   777
     * elements is negative or the load factor is nonpositive
jtulach@1334
   778
     *
jtulach@1334
   779
     * @since 1.6
jtulach@1334
   780
     */
jtulach@1334
   781
    public ConcurrentHashMap(int initialCapacity, float loadFactor) {
jtulach@1334
   782
        this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL);
jtulach@1334
   783
    }
jtulach@1334
   784
jtulach@1334
   785
    /**
jtulach@1334
   786
     * Creates a new, empty map with the specified initial capacity,
jtulach@1334
   787
     * and with default load factor (0.75) and concurrencyLevel (16).
jtulach@1334
   788
     *
jtulach@1334
   789
     * @param initialCapacity the initial capacity. The implementation
jtulach@1334
   790
     * performs internal sizing to accommodate this many elements.
jtulach@1334
   791
     * @throws IllegalArgumentException if the initial capacity of
jtulach@1334
   792
     * elements is negative.
jtulach@1334
   793
     */
jtulach@1334
   794
    public ConcurrentHashMap(int initialCapacity) {
jtulach@1334
   795
        this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
jtulach@1334
   796
    }
jtulach@1334
   797
jtulach@1334
   798
    /**
jtulach@1334
   799
     * Creates a new, empty map with a default initial capacity (16),
jtulach@1334
   800
     * load factor (0.75) and concurrencyLevel (16).
jtulach@1334
   801
     */
jtulach@1334
   802
    public ConcurrentHashMap() {
jtulach@1334
   803
        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
jtulach@1334
   804
    }
jtulach@1334
   805
jtulach@1334
   806
    /**
jtulach@1334
   807
     * Creates a new map with the same mappings as the given map.
jtulach@1334
   808
     * The map is created with a capacity of 1.5 times the number
jtulach@1334
   809
     * of mappings in the given map or 16 (whichever is greater),
jtulach@1334
   810
     * and a default load factor (0.75) and concurrencyLevel (16).
jtulach@1334
   811
     *
jtulach@1334
   812
     * @param m the map
jtulach@1334
   813
     */
jtulach@1334
   814
    public ConcurrentHashMap(Map<? extends K, ? extends V> m) {
jtulach@1334
   815
        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
jtulach@1334
   816
                      DEFAULT_INITIAL_CAPACITY),
jtulach@1334
   817
             DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
jtulach@1334
   818
        putAll(m);
jtulach@1334
   819
    }
jtulach@1334
   820
jtulach@1334
   821
    /**
jtulach@1334
   822
     * Returns <tt>true</tt> if this map contains no key-value mappings.
jtulach@1334
   823
     *
jtulach@1334
   824
     * @return <tt>true</tt> if this map contains no key-value mappings
jtulach@1334
   825
     */
jtulach@1334
   826
    public boolean isEmpty() {
jtulach@1334
   827
        /*
jtulach@1334
   828
         * Sum per-segment modCounts to avoid mis-reporting when
jtulach@1334
   829
         * elements are concurrently added and removed in one segment
jtulach@1334
   830
         * while checking another, in which case the table was never
jtulach@1334
   831
         * actually empty at any point. (The sum ensures accuracy up
jtulach@1334
   832
         * through at least 1<<31 per-segment modifications before
jtulach@1334
   833
         * recheck.)  Methods size() and containsValue() use similar
jtulach@1334
   834
         * constructions for stability checks.
jtulach@1334
   835
         */
jtulach@1334
   836
        long sum = 0L;
jtulach@1334
   837
        final Segment<K,V>[] segments = this.segments;
jtulach@1334
   838
        for (int j = 0; j < segments.length; ++j) {
jtulach@1334
   839
            Segment<K,V> seg = segmentAt(segments, j);
jtulach@1334
   840
            if (seg != null) {
jtulach@1334
   841
                if (seg.count != 0)
jtulach@1334
   842
                    return false;
jtulach@1334
   843
                sum += seg.modCount;
jtulach@1334
   844
            }
jtulach@1334
   845
        }
jtulach@1334
   846
        if (sum != 0L) { // recheck unless no modifications
jtulach@1334
   847
            for (int j = 0; j < segments.length; ++j) {
jtulach@1334
   848
                Segment<K,V> seg = segmentAt(segments, j);
jtulach@1334
   849
                if (seg != null) {
jtulach@1334
   850
                    if (seg.count != 0)
jtulach@1334
   851
                        return false;
jtulach@1334
   852
                    sum -= seg.modCount;
jtulach@1334
   853
                }
jtulach@1334
   854
            }
jtulach@1334
   855
            if (sum != 0L)
jtulach@1334
   856
                return false;
jtulach@1334
   857
        }
jtulach@1334
   858
        return true;
jtulach@1334
   859
    }
jtulach@1334
   860
jtulach@1334
   861
    /**
jtulach@1334
   862
     * Returns the number of key-value mappings in this map.  If the
jtulach@1334
   863
     * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
jtulach@1334
   864
     * <tt>Integer.MAX_VALUE</tt>.
jtulach@1334
   865
     *
jtulach@1334
   866
     * @return the number of key-value mappings in this map
jtulach@1334
   867
     */
jtulach@1334
   868
    public int size() {
jtulach@1334
   869
        // Try a few times to get accurate count. On failure due to
jtulach@1334
   870
        // continuous async changes in table, resort to locking.
jtulach@1334
   871
        final Segment<K,V>[] segments = this.segments;
jtulach@1334
   872
        int size;
jtulach@1334
   873
        boolean overflow; // true if size overflows 32 bits
jtulach@1334
   874
        long sum;         // sum of modCounts
jtulach@1334
   875
        long last = 0L;   // previous sum
jtulach@1334
   876
        int retries = -1; // first iteration isn't retry
jtulach@1334
   877
        try {
jtulach@1334
   878
            for (;;) {
jtulach@1334
   879
                if (retries++ == RETRIES_BEFORE_LOCK) {
jtulach@1334
   880
                    for (int j = 0; j < segments.length; ++j)
jtulach@1334
   881
                        ensureSegment(j).lock(); // force creation
jtulach@1334
   882
                }
jtulach@1334
   883
                sum = 0L;
jtulach@1334
   884
                size = 0;
jtulach@1334
   885
                overflow = false;
jtulach@1334
   886
                for (int j = 0; j < segments.length; ++j) {
jtulach@1334
   887
                    Segment<K,V> seg = segmentAt(segments, j);
jtulach@1334
   888
                    if (seg != null) {
jtulach@1334
   889
                        sum += seg.modCount;
jtulach@1334
   890
                        int c = seg.count;
jtulach@1334
   891
                        if (c < 0 || (size += c) < 0)
jtulach@1334
   892
                            overflow = true;
jtulach@1334
   893
                    }
jtulach@1334
   894
                }
jtulach@1334
   895
                if (sum == last)
jtulach@1334
   896
                    break;
jtulach@1334
   897
                last = sum;
jtulach@1334
   898
            }
jtulach@1334
   899
        } finally {
jtulach@1334
   900
            if (retries > RETRIES_BEFORE_LOCK) {
jtulach@1334
   901
                for (int j = 0; j < segments.length; ++j)
jtulach@1334
   902
                    segmentAt(segments, j).unlock();
jtulach@1334
   903
            }
jtulach@1334
   904
        }
jtulach@1334
   905
        return overflow ? Integer.MAX_VALUE : size;
jtulach@1334
   906
    }
jtulach@1334
   907
jtulach@1334
   908
    /**
jtulach@1334
   909
     * Returns the value to which the specified key is mapped,
jtulach@1334
   910
     * or {@code null} if this map contains no mapping for the key.
jtulach@1334
   911
     *
jtulach@1334
   912
     * <p>More formally, if this map contains a mapping from a key
jtulach@1334
   913
     * {@code k} to a value {@code v} such that {@code key.equals(k)},
jtulach@1334
   914
     * then this method returns {@code v}; otherwise it returns
jtulach@1334
   915
     * {@code null}.  (There can be at most one such mapping.)
jtulach@1334
   916
     *
jtulach@1334
   917
     * @throws NullPointerException if the specified key is null
jtulach@1334
   918
     */
jtulach@1334
   919
    public V get(Object key) {
jtulach@1334
   920
        Segment<K,V> s; // manually integrate access methods to reduce overhead
jtulach@1334
   921
        HashEntry<K,V>[] tab;
jtulach@1334
   922
        int h = hash(key.hashCode());
jtulach@1334
   923
        long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE;
jtulach@1334
   924
        if ((s = (Segment<K,V>)UNSAFE.getObjectVolatile(segments, u)) != null &&
jtulach@1334
   925
            (tab = s.table) != null) {
jtulach@1334
   926
            for (HashEntry<K,V> e = (HashEntry<K,V>) UNSAFE.getObjectVolatile
jtulach@1334
   927
                     (tab, ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE);
jtulach@1334
   928
                 e != null; e = e.next) {
jtulach@1334
   929
                K k;
jtulach@1334
   930
                if ((k = e.key) == key || (e.hash == h && key.equals(k)))
jtulach@1334
   931
                    return e.value;
jtulach@1334
   932
            }
jtulach@1334
   933
        }
jtulach@1334
   934
        return null;
jtulach@1334
   935
    }
jtulach@1334
   936
jtulach@1334
   937
    /**
jtulach@1334
   938
     * Tests if the specified object is a key in this table.
jtulach@1334
   939
     *
jtulach@1334
   940
     * @param  key   possible key
jtulach@1334
   941
     * @return <tt>true</tt> if and only if the specified object
jtulach@1334
   942
     *         is a key in this table, as determined by the
jtulach@1334
   943
     *         <tt>equals</tt> method; <tt>false</tt> otherwise.
jtulach@1334
   944
     * @throws NullPointerException if the specified key is null
jtulach@1334
   945
     */
jtulach@1334
   946
    @SuppressWarnings("unchecked")
jtulach@1334
   947
    public boolean containsKey(Object key) {
jtulach@1334
   948
        Segment<K,V> s; // same as get() except no need for volatile value read
jtulach@1334
   949
        HashEntry<K,V>[] tab;
jtulach@1334
   950
        int h = hash(key.hashCode());
jtulach@1334
   951
        long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE;
jtulach@1334
   952
        if ((s = (Segment<K,V>)UNSAFE.getObjectVolatile(segments, u)) != null &&
jtulach@1334
   953
            (tab = s.table) != null) {
jtulach@1334
   954
            for (HashEntry<K,V> e = (HashEntry<K,V>) UNSAFE.getObjectVolatile
jtulach@1334
   955
                     (tab, ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE);
jtulach@1334
   956
                 e != null; e = e.next) {
jtulach@1334
   957
                K k;
jtulach@1334
   958
                if ((k = e.key) == key || (e.hash == h && key.equals(k)))
jtulach@1334
   959
                    return true;
jtulach@1334
   960
            }
jtulach@1334
   961
        }
jtulach@1334
   962
        return false;
jtulach@1334
   963
    }
jtulach@1334
   964
jtulach@1334
   965
    /**
jtulach@1334
   966
     * Returns <tt>true</tt> if this map maps one or more keys to the
jtulach@1334
   967
     * specified value. Note: This method requires a full internal
jtulach@1334
   968
     * traversal of the hash table, and so is much slower than
jtulach@1334
   969
     * method <tt>containsKey</tt>.
jtulach@1334
   970
     *
jtulach@1334
   971
     * @param value value whose presence in this map is to be tested
jtulach@1334
   972
     * @return <tt>true</tt> if this map maps one or more keys to the
jtulach@1334
   973
     *         specified value
jtulach@1334
   974
     * @throws NullPointerException if the specified value is null
jtulach@1334
   975
     */
jtulach@1334
   976
    public boolean containsValue(Object value) {
jtulach@1334
   977
        // Same idea as size()
jtulach@1334
   978
        if (value == null)
jtulach@1334
   979
            throw new NullPointerException();
jtulach@1334
   980
        final Segment<K,V>[] segments = this.segments;
jtulach@1334
   981
        boolean found = false;
jtulach@1334
   982
        long last = 0;
jtulach@1334
   983
        int retries = -1;
jtulach@1334
   984
        try {
jtulach@1334
   985
            outer: for (;;) {
jtulach@1334
   986
                if (retries++ == RETRIES_BEFORE_LOCK) {
jtulach@1334
   987
                    for (int j = 0; j < segments.length; ++j)
jtulach@1334
   988
                        ensureSegment(j).lock(); // force creation
jtulach@1334
   989
                }
jtulach@1334
   990
                long hashSum = 0L;
jtulach@1334
   991
                int sum = 0;
jtulach@1334
   992
                for (int j = 0; j < segments.length; ++j) {
jtulach@1334
   993
                    HashEntry<K,V>[] tab;
jtulach@1334
   994
                    Segment<K,V> seg = segmentAt(segments, j);
jtulach@1334
   995
                    if (seg != null && (tab = seg.table) != null) {
jtulach@1334
   996
                        for (int i = 0 ; i < tab.length; i++) {
jtulach@1334
   997
                            HashEntry<K,V> e;
jtulach@1334
   998
                            for (e = entryAt(tab, i); e != null; e = e.next) {
jtulach@1334
   999
                                V v = e.value;
jtulach@1334
  1000
                                if (v != null && value.equals(v)) {
jtulach@1334
  1001
                                    found = true;
jtulach@1334
  1002
                                    break outer;
jtulach@1334
  1003
                                }
jtulach@1334
  1004
                            }
jtulach@1334
  1005
                        }
jtulach@1334
  1006
                        sum += seg.modCount;
jtulach@1334
  1007
                    }
jtulach@1334
  1008
                }
jtulach@1334
  1009
                if (retries > 0 && sum == last)
jtulach@1334
  1010
                    break;
jtulach@1334
  1011
                last = sum;
jtulach@1334
  1012
            }
jtulach@1334
  1013
        } finally {
jtulach@1334
  1014
            if (retries > RETRIES_BEFORE_LOCK) {
jtulach@1334
  1015
                for (int j = 0; j < segments.length; ++j)
jtulach@1334
  1016
                    segmentAt(segments, j).unlock();
jtulach@1334
  1017
            }
jtulach@1334
  1018
        }
jtulach@1334
  1019
        return found;
jtulach@1334
  1020
    }
jtulach@1334
  1021
jtulach@1334
  1022
    /**
jtulach@1334
  1023
     * Legacy method testing if some key maps into the specified value
jtulach@1334
  1024
     * in this table.  This method is identical in functionality to
jtulach@1334
  1025
     * {@link #containsValue}, and exists solely to ensure
jtulach@1334
  1026
     * full compatibility with class {@link java.util.Hashtable},
jtulach@1334
  1027
     * which supported this method prior to introduction of the
jtulach@1334
  1028
     * Java Collections framework.
jtulach@1334
  1029
jtulach@1334
  1030
     * @param  value a value to search for
jtulach@1334
  1031
     * @return <tt>true</tt> if and only if some key maps to the
jtulach@1334
  1032
     *         <tt>value</tt> argument in this table as
jtulach@1334
  1033
     *         determined by the <tt>equals</tt> method;
jtulach@1334
  1034
     *         <tt>false</tt> otherwise
jtulach@1334
  1035
     * @throws NullPointerException if the specified value is null
jtulach@1334
  1036
     */
jtulach@1334
  1037
    public boolean contains(Object value) {
jtulach@1334
  1038
        return containsValue(value);
jtulach@1334
  1039
    }
jtulach@1334
  1040
jtulach@1334
  1041
    /**
jtulach@1334
  1042
     * Maps the specified key to the specified value in this table.
jtulach@1334
  1043
     * Neither the key nor the value can be null.
jtulach@1334
  1044
     *
jtulach@1334
  1045
     * <p> The value can be retrieved by calling the <tt>get</tt> method
jtulach@1334
  1046
     * with a key that is equal to the original key.
jtulach@1334
  1047
     *
jtulach@1334
  1048
     * @param key key with which the specified value is to be associated
jtulach@1334
  1049
     * @param value value to be associated with the specified key
jtulach@1334
  1050
     * @return the previous value associated with <tt>key</tt>, or
jtulach@1334
  1051
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>
jtulach@1334
  1052
     * @throws NullPointerException if the specified key or value is null
jtulach@1334
  1053
     */
jtulach@1334
  1054
    @SuppressWarnings("unchecked")
jtulach@1334
  1055
    public V put(K key, V value) {
jtulach@1334
  1056
        Segment<K,V> s;
jtulach@1334
  1057
        if (value == null)
jtulach@1334
  1058
            throw new NullPointerException();
jtulach@1334
  1059
        int hash = hash(key.hashCode());
jtulach@1334
  1060
        int j = (hash >>> segmentShift) & segmentMask;
jtulach@1334
  1061
        if ((s = (Segment<K,V>)UNSAFE.getObject          // nonvolatile; recheck
jtulach@1334
  1062
             (segments, (j << SSHIFT) + SBASE)) == null) //  in ensureSegment
jtulach@1334
  1063
            s = ensureSegment(j);
jtulach@1334
  1064
        return s.put(key, hash, value, false);
jtulach@1334
  1065
    }
jtulach@1334
  1066
jtulach@1334
  1067
    /**
jtulach@1334
  1068
     * {@inheritDoc}
jtulach@1334
  1069
     *
jtulach@1334
  1070
     * @return the previous value associated with the specified key,
jtulach@1334
  1071
     *         or <tt>null</tt> if there was no mapping for the key
jtulach@1334
  1072
     * @throws NullPointerException if the specified key or value is null
jtulach@1334
  1073
     */
jtulach@1334
  1074
    @SuppressWarnings("unchecked")
jtulach@1334
  1075
    public V putIfAbsent(K key, V value) {
jtulach@1334
  1076
        Segment<K,V> s;
jtulach@1334
  1077
        if (value == null)
jtulach@1334
  1078
            throw new NullPointerException();
jtulach@1334
  1079
        int hash = hash(key.hashCode());
jtulach@1334
  1080
        int j = (hash >>> segmentShift) & segmentMask;
jtulach@1334
  1081
        if ((s = (Segment<K,V>)UNSAFE.getObject
jtulach@1334
  1082
             (segments, (j << SSHIFT) + SBASE)) == null)
jtulach@1334
  1083
            s = ensureSegment(j);
jtulach@1334
  1084
        return s.put(key, hash, value, true);
jtulach@1334
  1085
    }
jtulach@1334
  1086
jtulach@1334
  1087
    /**
jtulach@1334
  1088
     * Copies all of the mappings from the specified map to this one.
jtulach@1334
  1089
     * These mappings replace any mappings that this map had for any of the
jtulach@1334
  1090
     * keys currently in the specified map.
jtulach@1334
  1091
     *
jtulach@1334
  1092
     * @param m mappings to be stored in this map
jtulach@1334
  1093
     */
jtulach@1334
  1094
    public void putAll(Map<? extends K, ? extends V> m) {
jtulach@1334
  1095
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
jtulach@1334
  1096
            put(e.getKey(), e.getValue());
jtulach@1334
  1097
    }
jtulach@1334
  1098
jtulach@1334
  1099
    /**
jtulach@1334
  1100
     * Removes the key (and its corresponding value) from this map.
jtulach@1334
  1101
     * This method does nothing if the key is not in the map.
jtulach@1334
  1102
     *
jtulach@1334
  1103
     * @param  key the key that needs to be removed
jtulach@1334
  1104
     * @return the previous value associated with <tt>key</tt>, or
jtulach@1334
  1105
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>
jtulach@1334
  1106
     * @throws NullPointerException if the specified key is null
jtulach@1334
  1107
     */
jtulach@1334
  1108
    public V remove(Object key) {
jtulach@1334
  1109
        int hash = hash(key.hashCode());
jtulach@1334
  1110
        Segment<K,V> s = segmentForHash(hash);
jtulach@1334
  1111
        return s == null ? null : s.remove(key, hash, null);
jtulach@1334
  1112
    }
jtulach@1334
  1113
jtulach@1334
  1114
    /**
jtulach@1334
  1115
     * {@inheritDoc}
jtulach@1334
  1116
     *
jtulach@1334
  1117
     * @throws NullPointerException if the specified key is null
jtulach@1334
  1118
     */
jtulach@1334
  1119
    public boolean remove(Object key, Object value) {
jtulach@1334
  1120
        int hash = hash(key.hashCode());
jtulach@1334
  1121
        Segment<K,V> s;
jtulach@1334
  1122
        return value != null && (s = segmentForHash(hash)) != null &&
jtulach@1334
  1123
            s.remove(key, hash, value) != null;
jtulach@1334
  1124
    }
jtulach@1334
  1125
jtulach@1334
  1126
    /**
jtulach@1334
  1127
     * {@inheritDoc}
jtulach@1334
  1128
     *
jtulach@1334
  1129
     * @throws NullPointerException if any of the arguments are null
jtulach@1334
  1130
     */
jtulach@1334
  1131
    public boolean replace(K key, V oldValue, V newValue) {
jtulach@1334
  1132
        int hash = hash(key.hashCode());
jtulach@1334
  1133
        if (oldValue == null || newValue == null)
jtulach@1334
  1134
            throw new NullPointerException();
jtulach@1334
  1135
        Segment<K,V> s = segmentForHash(hash);
jtulach@1334
  1136
        return s != null && s.replace(key, hash, oldValue, newValue);
jtulach@1334
  1137
    }
jtulach@1334
  1138
jtulach@1334
  1139
    /**
jtulach@1334
  1140
     * {@inheritDoc}
jtulach@1334
  1141
     *
jtulach@1334
  1142
     * @return the previous value associated with the specified key,
jtulach@1334
  1143
     *         or <tt>null</tt> if there was no mapping for the key
jtulach@1334
  1144
     * @throws NullPointerException if the specified key or value is null
jtulach@1334
  1145
     */
jtulach@1334
  1146
    public V replace(K key, V value) {
jtulach@1334
  1147
        int hash = hash(key.hashCode());
jtulach@1334
  1148
        if (value == null)
jtulach@1334
  1149
            throw new NullPointerException();
jtulach@1334
  1150
        Segment<K,V> s = segmentForHash(hash);
jtulach@1334
  1151
        return s == null ? null : s.replace(key, hash, value);
jtulach@1334
  1152
    }
jtulach@1334
  1153
jtulach@1334
  1154
    /**
jtulach@1334
  1155
     * Removes all of the mappings from this map.
jtulach@1334
  1156
     */
jtulach@1334
  1157
    public void clear() {
jtulach@1334
  1158
        final Segment<K,V>[] segments = this.segments;
jtulach@1334
  1159
        for (int j = 0; j < segments.length; ++j) {
jtulach@1334
  1160
            Segment<K,V> s = segmentAt(segments, j);
jtulach@1334
  1161
            if (s != null)
jtulach@1334
  1162
                s.clear();
jtulach@1334
  1163
        }
jtulach@1334
  1164
    }
jtulach@1334
  1165
jtulach@1334
  1166
    /**
jtulach@1334
  1167
     * Returns a {@link Set} view of the keys contained in this map.
jtulach@1334
  1168
     * The set is backed by the map, so changes to the map are
jtulach@1334
  1169
     * reflected in the set, and vice-versa.  The set supports element
jtulach@1334
  1170
     * removal, which removes the corresponding mapping from this map,
jtulach@1334
  1171
     * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
jtulach@1334
  1172
     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
jtulach@1334
  1173
     * operations.  It does not support the <tt>add</tt> or
jtulach@1334
  1174
     * <tt>addAll</tt> operations.
jtulach@1334
  1175
     *
jtulach@1334
  1176
     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
jtulach@1334
  1177
     * that will never throw {@link ConcurrentModificationException},
jtulach@1334
  1178
     * and guarantees to traverse elements as they existed upon
jtulach@1334
  1179
     * construction of the iterator, and may (but is not guaranteed to)
jtulach@1334
  1180
     * reflect any modifications subsequent to construction.
jtulach@1334
  1181
     */
jtulach@1334
  1182
    public Set<K> keySet() {
jtulach@1334
  1183
        Set<K> ks = keySet;
jtulach@1334
  1184
        return (ks != null) ? ks : (keySet = new KeySet());
jtulach@1334
  1185
    }
jtulach@1334
  1186
jtulach@1334
  1187
    /**
jtulach@1334
  1188
     * Returns a {@link Collection} view of the values contained in this map.
jtulach@1334
  1189
     * The collection is backed by the map, so changes to the map are
jtulach@1334
  1190
     * reflected in the collection, and vice-versa.  The collection
jtulach@1334
  1191
     * supports element removal, which removes the corresponding
jtulach@1334
  1192
     * mapping from this map, via the <tt>Iterator.remove</tt>,
jtulach@1334
  1193
     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
jtulach@1334
  1194
     * <tt>retainAll</tt>, and <tt>clear</tt> operations.  It does not
jtulach@1334
  1195
     * support the <tt>add</tt> or <tt>addAll</tt> operations.
jtulach@1334
  1196
     *
jtulach@1334
  1197
     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
jtulach@1334
  1198
     * that will never throw {@link ConcurrentModificationException},
jtulach@1334
  1199
     * and guarantees to traverse elements as they existed upon
jtulach@1334
  1200
     * construction of the iterator, and may (but is not guaranteed to)
jtulach@1334
  1201
     * reflect any modifications subsequent to construction.
jtulach@1334
  1202
     */
jtulach@1334
  1203
    public Collection<V> values() {
jtulach@1334
  1204
        Collection<V> vs = values;
jtulach@1334
  1205
        return (vs != null) ? vs : (values = new Values());
jtulach@1334
  1206
    }
jtulach@1334
  1207
jtulach@1334
  1208
    /**
jtulach@1334
  1209
     * Returns a {@link Set} view of the mappings contained in this map.
jtulach@1334
  1210
     * The set is backed by the map, so changes to the map are
jtulach@1334
  1211
     * reflected in the set, and vice-versa.  The set supports element
jtulach@1334
  1212
     * removal, which removes the corresponding mapping from the map,
jtulach@1334
  1213
     * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
jtulach@1334
  1214
     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
jtulach@1334
  1215
     * operations.  It does not support the <tt>add</tt> or
jtulach@1334
  1216
     * <tt>addAll</tt> operations.
jtulach@1334
  1217
     *
jtulach@1334
  1218
     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
jtulach@1334
  1219
     * that will never throw {@link ConcurrentModificationException},
jtulach@1334
  1220
     * and guarantees to traverse elements as they existed upon
jtulach@1334
  1221
     * construction of the iterator, and may (but is not guaranteed to)
jtulach@1334
  1222
     * reflect any modifications subsequent to construction.
jtulach@1334
  1223
     */
jtulach@1334
  1224
    public Set<Map.Entry<K,V>> entrySet() {
jtulach@1334
  1225
        Set<Map.Entry<K,V>> es = entrySet;
jtulach@1334
  1226
        return (es != null) ? es : (entrySet = new EntrySet());
jtulach@1334
  1227
    }
jtulach@1334
  1228
jtulach@1334
  1229
    /**
jtulach@1334
  1230
     * Returns an enumeration of the keys in this table.
jtulach@1334
  1231
     *
jtulach@1334
  1232
     * @return an enumeration of the keys in this table
jtulach@1334
  1233
     * @see #keySet()
jtulach@1334
  1234
     */
jtulach@1334
  1235
    public Enumeration<K> keys() {
jtulach@1334
  1236
        return new KeyIterator();
jtulach@1334
  1237
    }
jtulach@1334
  1238
jtulach@1334
  1239
    /**
jtulach@1334
  1240
     * Returns an enumeration of the values in this table.
jtulach@1334
  1241
     *
jtulach@1334
  1242
     * @return an enumeration of the values in this table
jtulach@1334
  1243
     * @see #values()
jtulach@1334
  1244
     */
jtulach@1334
  1245
    public Enumeration<V> elements() {
jtulach@1334
  1246
        return new ValueIterator();
jtulach@1334
  1247
    }
jtulach@1334
  1248
jtulach@1334
  1249
    /* ---------------- Iterator Support -------------- */
jtulach@1334
  1250
jtulach@1334
  1251
    abstract class HashIterator {
jtulach@1334
  1252
        int nextSegmentIndex;
jtulach@1334
  1253
        int nextTableIndex;
jtulach@1334
  1254
        HashEntry<K,V>[] currentTable;
jtulach@1334
  1255
        HashEntry<K, V> nextEntry;
jtulach@1334
  1256
        HashEntry<K, V> lastReturned;
jtulach@1334
  1257
jtulach@1334
  1258
        HashIterator() {
jtulach@1334
  1259
            nextSegmentIndex = segments.length - 1;
jtulach@1334
  1260
            nextTableIndex = -1;
jtulach@1334
  1261
            advance();
jtulach@1334
  1262
        }
jtulach@1334
  1263
jtulach@1334
  1264
        /**
jtulach@1334
  1265
         * Set nextEntry to first node of next non-empty table
jtulach@1334
  1266
         * (in backwards order, to simplify checks).
jtulach@1334
  1267
         */
jtulach@1334
  1268
        final void advance() {
jtulach@1334
  1269
            for (;;) {
jtulach@1334
  1270
                if (nextTableIndex >= 0) {
jtulach@1334
  1271
                    if ((nextEntry = entryAt(currentTable,
jtulach@1334
  1272
                                             nextTableIndex--)) != null)
jtulach@1334
  1273
                        break;
jtulach@1334
  1274
                }
jtulach@1334
  1275
                else if (nextSegmentIndex >= 0) {
jtulach@1334
  1276
                    Segment<K,V> seg = segmentAt(segments, nextSegmentIndex--);
jtulach@1334
  1277
                    if (seg != null && (currentTable = seg.table) != null)
jtulach@1334
  1278
                        nextTableIndex = currentTable.length - 1;
jtulach@1334
  1279
                }
jtulach@1334
  1280
                else
jtulach@1334
  1281
                    break;
jtulach@1334
  1282
            }
jtulach@1334
  1283
        }
jtulach@1334
  1284
jtulach@1334
  1285
        final HashEntry<K,V> nextEntry() {
jtulach@1334
  1286
            HashEntry<K,V> e = nextEntry;
jtulach@1334
  1287
            if (e == null)
jtulach@1334
  1288
                throw new NoSuchElementException();
jtulach@1334
  1289
            lastReturned = e; // cannot assign until after null check
jtulach@1334
  1290
            if ((nextEntry = e.next) == null)
jtulach@1334
  1291
                advance();
jtulach@1334
  1292
            return e;
jtulach@1334
  1293
        }
jtulach@1334
  1294
jtulach@1334
  1295
        public final boolean hasNext() { return nextEntry != null; }
jtulach@1334
  1296
        public final boolean hasMoreElements() { return nextEntry != null; }
jtulach@1334
  1297
jtulach@1334
  1298
        public final void remove() {
jtulach@1334
  1299
            if (lastReturned == null)
jtulach@1334
  1300
                throw new IllegalStateException();
jtulach@1334
  1301
            ConcurrentHashMap.this.remove(lastReturned.key);
jtulach@1334
  1302
            lastReturned = null;
jtulach@1334
  1303
        }
jtulach@1334
  1304
    }
jtulach@1334
  1305
jtulach@1334
  1306
    final class KeyIterator
jtulach@1334
  1307
        extends HashIterator
jtulach@1334
  1308
        implements Iterator<K>, Enumeration<K>
jtulach@1334
  1309
    {
jtulach@1334
  1310
        public final K next()        { return super.nextEntry().key; }
jtulach@1334
  1311
        public final K nextElement() { return super.nextEntry().key; }
jtulach@1334
  1312
    }
jtulach@1334
  1313
jtulach@1334
  1314
    final class ValueIterator
jtulach@1334
  1315
        extends HashIterator
jtulach@1334
  1316
        implements Iterator<V>, Enumeration<V>
jtulach@1334
  1317
    {
jtulach@1334
  1318
        public final V next()        { return super.nextEntry().value; }
jtulach@1334
  1319
        public final V nextElement() { return super.nextEntry().value; }
jtulach@1334
  1320
    }
jtulach@1334
  1321
jtulach@1334
  1322
    /**
jtulach@1334
  1323
     * Custom Entry class used by EntryIterator.next(), that relays
jtulach@1334
  1324
     * setValue changes to the underlying map.
jtulach@1334
  1325
     */
jtulach@1334
  1326
    final class WriteThroughEntry
jtulach@1334
  1327
        extends AbstractMap.SimpleEntry<K,V>
jtulach@1334
  1328
    {
jtulach@1334
  1329
        WriteThroughEntry(K k, V v) {
jtulach@1334
  1330
            super(k,v);
jtulach@1334
  1331
        }
jtulach@1334
  1332
jtulach@1334
  1333
        /**
jtulach@1334
  1334
         * Set our entry's value and write through to the map. The
jtulach@1334
  1335
         * value to return is somewhat arbitrary here. Since a
jtulach@1334
  1336
         * WriteThroughEntry does not necessarily track asynchronous
jtulach@1334
  1337
         * changes, the most recent "previous" value could be
jtulach@1334
  1338
         * different from what we return (or could even have been
jtulach@1334
  1339
         * removed in which case the put will re-establish). We do not
jtulach@1334
  1340
         * and cannot guarantee more.
jtulach@1334
  1341
         */
jtulach@1334
  1342
        public V setValue(V value) {
jtulach@1334
  1343
            if (value == null) throw new NullPointerException();
jtulach@1334
  1344
            V v = super.setValue(value);
jtulach@1334
  1345
            ConcurrentHashMap.this.put(getKey(), value);
jtulach@1334
  1346
            return v;
jtulach@1334
  1347
        }
jtulach@1334
  1348
    }
jtulach@1334
  1349
jtulach@1334
  1350
    final class EntryIterator
jtulach@1334
  1351
        extends HashIterator
jtulach@1334
  1352
        implements Iterator<Entry<K,V>>
jtulach@1334
  1353
    {
jtulach@1334
  1354
        public Map.Entry<K,V> next() {
jtulach@1334
  1355
            HashEntry<K,V> e = super.nextEntry();
jtulach@1334
  1356
            return new WriteThroughEntry(e.key, e.value);
jtulach@1334
  1357
        }
jtulach@1334
  1358
    }
jtulach@1334
  1359
jtulach@1334
  1360
    final class KeySet extends AbstractSet<K> {
jtulach@1334
  1361
        public Iterator<K> iterator() {
jtulach@1334
  1362
            return new KeyIterator();
jtulach@1334
  1363
        }
jtulach@1334
  1364
        public int size() {
jtulach@1334
  1365
            return ConcurrentHashMap.this.size();
jtulach@1334
  1366
        }
jtulach@1334
  1367
        public boolean isEmpty() {
jtulach@1334
  1368
            return ConcurrentHashMap.this.isEmpty();
jtulach@1334
  1369
        }
jtulach@1334
  1370
        public boolean contains(Object o) {
jtulach@1334
  1371
            return ConcurrentHashMap.this.containsKey(o);
jtulach@1334
  1372
        }
jtulach@1334
  1373
        public boolean remove(Object o) {
jtulach@1334
  1374
            return ConcurrentHashMap.this.remove(o) != null;
jtulach@1334
  1375
        }
jtulach@1334
  1376
        public void clear() {
jtulach@1334
  1377
            ConcurrentHashMap.this.clear();
jtulach@1334
  1378
        }
jtulach@1334
  1379
    }
jtulach@1334
  1380
jtulach@1334
  1381
    final class Values extends AbstractCollection<V> {
jtulach@1334
  1382
        public Iterator<V> iterator() {
jtulach@1334
  1383
            return new ValueIterator();
jtulach@1334
  1384
        }
jtulach@1334
  1385
        public int size() {
jtulach@1334
  1386
            return ConcurrentHashMap.this.size();
jtulach@1334
  1387
        }
jtulach@1334
  1388
        public boolean isEmpty() {
jtulach@1334
  1389
            return ConcurrentHashMap.this.isEmpty();
jtulach@1334
  1390
        }
jtulach@1334
  1391
        public boolean contains(Object o) {
jtulach@1334
  1392
            return ConcurrentHashMap.this.containsValue(o);
jtulach@1334
  1393
        }
jtulach@1334
  1394
        public void clear() {
jtulach@1334
  1395
            ConcurrentHashMap.this.clear();
jtulach@1334
  1396
        }
jtulach@1334
  1397
    }
jtulach@1334
  1398
jtulach@1334
  1399
    final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
jtulach@1334
  1400
        public Iterator<Map.Entry<K,V>> iterator() {
jtulach@1334
  1401
            return new EntryIterator();
jtulach@1334
  1402
        }
jtulach@1334
  1403
        public boolean contains(Object o) {
jtulach@1334
  1404
            if (!(o instanceof Map.Entry))
jtulach@1334
  1405
                return false;
jtulach@1334
  1406
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
jtulach@1334
  1407
            V v = ConcurrentHashMap.this.get(e.getKey());
jtulach@1334
  1408
            return v != null && v.equals(e.getValue());
jtulach@1334
  1409
        }
jtulach@1334
  1410
        public boolean remove(Object o) {
jtulach@1334
  1411
            if (!(o instanceof Map.Entry))
jtulach@1334
  1412
                return false;
jtulach@1334
  1413
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
jtulach@1334
  1414
            return ConcurrentHashMap.this.remove(e.getKey(), e.getValue());
jtulach@1334
  1415
        }
jtulach@1334
  1416
        public int size() {
jtulach@1334
  1417
            return ConcurrentHashMap.this.size();
jtulach@1334
  1418
        }
jtulach@1334
  1419
        public boolean isEmpty() {
jtulach@1334
  1420
            return ConcurrentHashMap.this.isEmpty();
jtulach@1334
  1421
        }
jtulach@1334
  1422
        public void clear() {
jtulach@1334
  1423
            ConcurrentHashMap.this.clear();
jtulach@1334
  1424
        }
jtulach@1334
  1425
    }
jtulach@1334
  1426
jtulach@1334
  1427
    /* ---------------- Serialization Support -------------- */
jtulach@1334
  1428
jtulach@1334
  1429
    /**
jtulach@1334
  1430
     * Save the state of the <tt>ConcurrentHashMap</tt> instance to a
jtulach@1334
  1431
     * stream (i.e., serialize it).
jtulach@1334
  1432
     * @param s the stream
jtulach@1334
  1433
     * @serialData
jtulach@1334
  1434
     * the key (Object) and value (Object)
jtulach@1334
  1435
     * for each key-value mapping, followed by a null pair.
jtulach@1334
  1436
     * The key-value mappings are emitted in no particular order.
jtulach@1334
  1437
     */
jtulach@1334
  1438
    private void writeObject(java.io.ObjectOutputStream s) throws IOException {
jtulach@1334
  1439
        // force all segments for serialization compatibility
jtulach@1334
  1440
        for (int k = 0; k < segments.length; ++k)
jtulach@1334
  1441
            ensureSegment(k);
jtulach@1334
  1442
        s.defaultWriteObject();
jtulach@1334
  1443
jtulach@1334
  1444
        final Segment<K,V>[] segments = this.segments;
jtulach@1334
  1445
        for (int k = 0; k < segments.length; ++k) {
jtulach@1334
  1446
            Segment<K,V> seg = segmentAt(segments, k);
jtulach@1334
  1447
            seg.lock();
jtulach@1334
  1448
            try {
jtulach@1334
  1449
                HashEntry<K,V>[] tab = seg.table;
jtulach@1334
  1450
                for (int i = 0; i < tab.length; ++i) {
jtulach@1334
  1451
                    HashEntry<K,V> e;
jtulach@1334
  1452
                    for (e = entryAt(tab, i); e != null; e = e.next) {
jtulach@1334
  1453
                        s.writeObject(e.key);
jtulach@1334
  1454
                        s.writeObject(e.value);
jtulach@1334
  1455
                    }
jtulach@1334
  1456
                }
jtulach@1334
  1457
            } finally {
jtulach@1334
  1458
                seg.unlock();
jtulach@1334
  1459
            }
jtulach@1334
  1460
        }
jtulach@1334
  1461
        s.writeObject(null);
jtulach@1334
  1462
        s.writeObject(null);
jtulach@1334
  1463
    }
jtulach@1334
  1464
jtulach@1334
  1465
    /**
jtulach@1334
  1466
     * Reconstitute the <tt>ConcurrentHashMap</tt> instance from a
jtulach@1334
  1467
     * stream (i.e., deserialize it).
jtulach@1334
  1468
     * @param s the stream
jtulach@1334
  1469
     */
jtulach@1334
  1470
    @SuppressWarnings("unchecked")
jtulach@1334
  1471
    private void readObject(java.io.ObjectInputStream s)
jtulach@1334
  1472
        throws IOException, ClassNotFoundException {
jtulach@1334
  1473
        s.defaultReadObject();
jtulach@1334
  1474
jtulach@1334
  1475
        // Re-initialize segments to be minimally sized, and let grow.
jtulach@1334
  1476
        int cap = MIN_SEGMENT_TABLE_CAPACITY;
jtulach@1334
  1477
        final Segment<K,V>[] segments = this.segments;
jtulach@1334
  1478
        for (int k = 0; k < segments.length; ++k) {
jtulach@1334
  1479
            Segment<K,V> seg = segments[k];
jtulach@1334
  1480
            if (seg != null) {
jtulach@1334
  1481
                seg.threshold = (int)(cap * seg.loadFactor);
jtulach@1334
  1482
                seg.table = (HashEntry<K,V>[]) new HashEntry[cap];
jtulach@1334
  1483
            }
jtulach@1334
  1484
        }
jtulach@1334
  1485
jtulach@1334
  1486
        // Read the keys and values, and put the mappings in the table
jtulach@1334
  1487
        for (;;) {
jtulach@1334
  1488
            K key = (K) s.readObject();
jtulach@1334
  1489
            V value = (V) s.readObject();
jtulach@1334
  1490
            if (key == null)
jtulach@1334
  1491
                break;
jtulach@1334
  1492
            put(key, value);
jtulach@1334
  1493
        }
jtulach@1334
  1494
    }
jtulach@1334
  1495
jtulach@1334
  1496
    // Unsafe mechanics
jtulach@1334
  1497
    private static final sun.misc.Unsafe UNSAFE;
jtulach@1334
  1498
    private static final long SBASE;
jtulach@1334
  1499
    private static final int SSHIFT;
jtulach@1334
  1500
    private static final long TBASE;
jtulach@1334
  1501
    private static final int TSHIFT;
jtulach@1334
  1502
jtulach@1334
  1503
    static {
jtulach@1334
  1504
        int ss, ts;
jtulach@1334
  1505
        try {
jtulach@1334
  1506
            UNSAFE = sun.misc.Unsafe.getUnsafe();
jtulach@1334
  1507
            Class tc = HashEntry[].class;
jtulach@1334
  1508
            Class sc = Segment[].class;
jtulach@1334
  1509
            TBASE = UNSAFE.arrayBaseOffset(tc);
jtulach@1334
  1510
            SBASE = UNSAFE.arrayBaseOffset(sc);
jtulach@1334
  1511
            ts = UNSAFE.arrayIndexScale(tc);
jtulach@1334
  1512
            ss = UNSAFE.arrayIndexScale(sc);
jtulach@1334
  1513
        } catch (Exception e) {
jtulach@1334
  1514
            throw new Error(e);
jtulach@1334
  1515
        }
jtulach@1334
  1516
        if ((ss & (ss-1)) != 0 || (ts & (ts-1)) != 0)
jtulach@1334
  1517
            throw new Error("data type scale not a power of two");
jtulach@1334
  1518
        SSHIFT = 31 - Integer.numberOfLeadingZeros(ss);
jtulach@1334
  1519
        TSHIFT = 31 - Integer.numberOfLeadingZeros(ts);
jtulach@1334
  1520
    }
jtulach@1334
  1521
jtulach@1334
  1522
}