~ubuntu-branches/ubuntu/trusty/ehcache/trusty

« back to all changes in this revision

Viewing changes to src/main/java/net/sf/ehcache/store/chm/ConcurrentHashMap.java

  • Committer: Package Import Robot
  • Author(s): Emmanuel Bourg
  • Date: 2013-05-06 14:53:07 UTC
  • mfrom: (1.1.7) (2.1.8 sid)
  • Revision ID: package-import@ubuntu.com-20130506145307-v5bhw5yu70re00l3
Tags: 2.6.7-1
* Team upload.
* New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Written by Doug Lea with assistance from members of JCP JSR-166
3
 
 * Expert Group and released to the public domain, as explained at
4
 
 * http://creativecommons.org/licenses/publicdomain
5
 
 */
6
 
 
7
 
/*
8
 
 * Repackaged for use in Ehcache by Chris Dennis. The only changes
9
 
 * to this version where to override the AbstractCollection toArray
10
 
 * implementation in KeySet.toArray(), Values.toArray(), and
11
 
 * EntrySet.toArray() to ensure correct operation when using the 1.5
12
 
 * version of AbstractCollection.
13
 
 */
14
 
 
15
 
package net.sf.ehcache.store.chm;
16
 
 
17
 
import java.io.IOException;
18
 
import java.io.Serializable;
19
 
import java.util.AbstractCollection;
20
 
import java.util.AbstractMap;
21
 
import java.util.AbstractSet;
22
 
import java.util.ArrayList;
23
 
import java.util.Collection;
24
 
import java.util.ConcurrentModificationException;
25
 
import java.util.Enumeration;
26
 
import java.util.HashMap;
27
 
import java.util.Hashtable;
28
 
import java.util.Iterator;
29
 
import java.util.Map;
30
 
import java.util.NoSuchElementException;
31
 
import java.util.Set;
32
 
import java.util.concurrent.ConcurrentMap;
33
 
import java.util.concurrent.locks.ReentrantReadWriteLock;
34
 
 
35
 
import net.sf.ehcache.util.FindBugsSuppressWarnings;
36
 
 
37
 
/**
38
 
 * A hash table supporting full concurrency of retrievals and
39
 
 * adjustable expected concurrency for updates. This class obeys the
40
 
 * same functional specification as {@link java.util.Hashtable}, and
41
 
 * includes versions of methods corresponding to each method of
42
 
 * <tt>Hashtable</tt>. However, even though all operations are
43
 
 * thread-safe, retrieval operations do <em>not</em> entail locking,
44
 
 * and there is <em>not</em> any support for locking the entire table
45
 
 * in a way that prevents all access.  This class is fully
46
 
 * interoperable with <tt>Hashtable</tt> in programs that rely on its
47
 
 * thread safety but not on its synchronization details.
48
 
 *
49
 
 * <p> Retrieval operations (including <tt>get</tt>) generally do not
50
 
 * block, so may overlap with update operations (including
51
 
 * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
52
 
 * of the most recently <em>completed</em> update operations holding
53
 
 * upon their onset.  For aggregate operations such as <tt>putAll</tt>
54
 
 * and <tt>clear</tt>, concurrent retrievals may reflect insertion or
55
 
 * removal of only some entries.  Similarly, Iterators and
56
 
 * Enumerations return elements reflecting the state of the hash table
57
 
 * at some point at or since the creation of the iterator/enumeration.
58
 
 * They do <em>not</em> throw {@link ConcurrentModificationException}.
59
 
 * However, iterators are designed to be used by only one thread at a time.
60
 
 *
61
 
 * <p> The allowed concurrency among update operations is guided by
62
 
 * the optional <tt>concurrencyLevel</tt> constructor argument
63
 
 * (default <tt>16</tt>), which is used as a hint for internal sizing.  The
64
 
 * table is internally partitioned to try to permit the indicated
65
 
 * number of concurrent updates without contention. Because placement
66
 
 * in hash tables is essentially random, the actual concurrency will
67
 
 * vary.  Ideally, you should choose a value to accommodate as many
68
 
 * threads as will ever concurrently modify the table. Using a
69
 
 * significantly higher value than you need can waste space and time,
70
 
 * and a significantly lower value can lead to thread contention. But
71
 
 * overestimates and underestimates within an order of magnitude do
72
 
 * not usually have much noticeable impact. A value of one is
73
 
 * appropriate when it is known that only one thread will modify and
74
 
 * all others will only read. Also, resizing this or any other kind of
75
 
 * hash table is a relatively slow operation, so, when possible, it is
76
 
 * a good idea to provide estimates of expected table sizes in
77
 
 * constructors.
78
 
 *
79
 
 * <p>This class and its views and iterators implement all of the
80
 
 * <em>optional</em> methods of the {@link Map} and {@link Iterator}
81
 
 * interfaces.
82
 
 *
83
 
 * <p> Like {@link Hashtable} but unlike {@link HashMap}, this class
84
 
 * does <em>not</em> allow <tt>null</tt> to be used as a key or value.
85
 
 *
86
 
 * <p>This class is a member of the
87
 
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
88
 
 * Java Collections Framework</a>.
89
 
 *
90
 
 * @since 1.5
91
 
 * @author Doug Lea
92
 
 * @param <K> the type of keys maintained by this map
93
 
 * @param <V> the type of mapped values
94
 
 */
95
 
class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
96
 
        implements ConcurrentMap<K, V>, Serializable {
97
 
    private static final long serialVersionUID = 7249069246763182397L;
98
 
 
99
 
    /*
100
 
     * The basic strategy is to subdivide the table among Segments,
101
 
     * each of which itself is a concurrently readable hash table.
102
 
     */
103
 
 
104
 
    /* ---------------- Constants -------------- */
105
 
 
106
 
    /**
107
 
     * The default initial capacity for this table,
108
 
     * used when not otherwise specified in a constructor.
109
 
     */
110
 
    static final int DEFAULT_INITIAL_CAPACITY = 16;
111
 
 
112
 
    /**
113
 
     * The default load factor for this table, used when not
114
 
     * otherwise specified in a constructor.
115
 
     */
116
 
    static final float DEFAULT_LOAD_FACTOR = 0.75f;
117
 
 
118
 
    /**
119
 
     * The default concurrency level for this table, used when not
120
 
     * otherwise specified in a constructor.
121
 
     */
122
 
    static final int DEFAULT_CONCURRENCY_LEVEL = 16;
123
 
 
124
 
    /**
125
 
     * The maximum capacity, used if a higher value is implicitly
126
 
     * specified by either of the constructors with arguments.  MUST
127
 
     * be a power of two <= 1<<30 to ensure that entries are indexable
128
 
     * using ints.
129
 
     */
130
 
    static final int MAXIMUM_CAPACITY = 1 << 30;
131
 
 
132
 
    /**
133
 
     * The maximum number of segments to allow; used to bound
134
 
     * constructor arguments.
135
 
     */
136
 
    static final int MAX_SEGMENTS = 1 << 16; // slightly conservative
137
 
 
138
 
    /**
139
 
     * Number of unsynchronized retries in size and containsValue
140
 
     * methods before resorting to locking. This is used to avoid
141
 
     * unbounded retries if tables undergo continuous modification
142
 
     * which would make it impossible to obtain an accurate result.
143
 
     */
144
 
    static final int RETRIES_BEFORE_LOCK = 2;
145
 
 
146
 
    /* ---------------- Fields -------------- */
147
 
 
148
 
    /**
149
 
     * Mask value for indexing into segments. The upper bits of a
150
 
     * key's hash code are used to choose the segment.
151
 
     */
152
 
    final int segmentMask;
153
 
 
154
 
    /**
155
 
     * Shift value for indexing within segments.
156
 
     */
157
 
    final int segmentShift;
158
 
 
159
 
    /**
160
 
     * The segments, each of which is a specialized hash table
161
 
     */
162
 
    final Segment<K,V>[] segments;
163
 
 
164
 
    transient Set<K> keySet;
165
 
    transient Set<Map.Entry<K,V>> entrySet;
166
 
    transient Collection<V> values;
167
 
 
168
 
    /* ---------------- Small Utilities -------------- */
169
 
 
170
 
    /**
171
 
     * Applies a supplemental hash function to a given hashCode, which
172
 
     * defends against poor quality hash functions.  This is critical
173
 
     * because ConcurrentHashMap uses power-of-two length hash tables,
174
 
     * that otherwise encounter collisions for hashCodes that do not
175
 
     * differ in lower or upper bits.
176
 
     */
177
 
    protected static int hash(int h) {
178
 
        // Spread bits to regularize both segment and index locations,
179
 
        // using variant of single-word Wang/Jenkins hash.
180
 
        h += (h <<  15) ^ 0xffffcd7d;
181
 
        h ^= (h >>> 10);
182
 
        h += (h <<   3);
183
 
        h ^= (h >>>  6);
184
 
        h += (h <<   2) + (h << 14);
185
 
        return h ^ (h >>> 16);
186
 
    }
187
 
 
188
 
    /**
189
 
     * Returns the segment that should be used for key with given hash
190
 
     * @param hash the hash code for the key
191
 
     * @return the segment
192
 
     */
193
 
    final Segment<K,V> segmentFor(int hash) {
194
 
        return segments[(hash >>> segmentShift) & segmentMask];
195
 
    }
196
 
 
197
 
    /* ---------------- Inner Classes -------------- */
198
 
 
199
 
    /**
200
 
     * ConcurrentHashMap list entry. Note that this is never exported
201
 
     * out as a user-visible Map.Entry.
202
 
     *
203
 
     * Because the value field is volatile, not final, it is legal wrt
204
 
     * the Java Memory Model for an unsynchronized reader to see null
205
 
     * instead of initial value when read via a data race.  Although a
206
 
     * reordering leading to this is not likely to ever actually
207
 
     * occur, the Segment.readValueUnderLock method is used as a
208
 
     * backup in case a null (pre-initialized) value is ever seen in
209
 
     * an unsynchronized access method.
210
 
     */
211
 
    static class HashEntry<K,V> {
212
 
        final K key;
213
 
        final int hash;
214
 
        volatile V value;
215
 
        final HashEntry<K,V> next;
216
 
 
217
 
        HashEntry(K key, int hash, HashEntry<K,V> next, V value) {
218
 
            this.key = key;
219
 
            this.hash = hash;
220
 
            this.next = next;
221
 
            this.value = value;
222
 
        }
223
 
 
224
 
        @SuppressWarnings("unchecked")
225
 
        static final <K,V> HashEntry<K,V>[] newArray(int i) {
226
 
            return new HashEntry[i];
227
 
        }
228
 
    }
229
 
 
230
 
    protected Segment<K, V> createSegment(int initialCapacity, float lf) {
231
 
        return new Segment<K, V>(initialCapacity, lf);
232
 
    }
233
 
    
234
 
    /**
235
 
     * Segments are specialized versions of hash tables.  This
236
 
     * subclasses from ReentrantLock opportunistically, just to
237
 
     * simplify some locking and avoid separate construction.
238
 
     */
239
 
    static class Segment<K,V> extends ReentrantReadWriteLock implements Serializable {
240
 
        /*
241
 
         * Segments maintain a table of entry lists that are ALWAYS
242
 
         * kept in a consistent state, so can be read without locking.
243
 
         * Next fields of nodes are immutable (final).  All list
244
 
         * additions are performed at the front of each bin. This
245
 
         * makes it easy to check changes, and also fast to traverse.
246
 
         * When nodes would otherwise be changed, new nodes are
247
 
         * created to replace them. This works well for hash tables
248
 
         * since the bin lists tend to be short. (The average length
249
 
         * is less than two for the default load factor threshold.)
250
 
         *
251
 
         * Read operations can thus proceed without locking, but rely
252
 
         * on selected uses of volatiles to ensure that completed
253
 
         * write operations performed by other threads are
254
 
         * noticed. For most purposes, the "count" field, tracking the
255
 
         * number of elements, serves as that volatile variable
256
 
         * ensuring visibility.  This is convenient because this field
257
 
         * needs to be read in many read operations anyway:
258
 
         *
259
 
         *   - All (unsynchronized) read operations must first read the
260
 
         *     "count" field, and should not look at table entries if
261
 
         *     it is 0.
262
 
         *
263
 
         *   - All (synchronized) write operations should write to
264
 
         *     the "count" field after structurally changing any bin.
265
 
         *     The operations must not take any action that could even
266
 
         *     momentarily cause a concurrent read operation to see
267
 
         *     inconsistent data. This is made easier by the nature of
268
 
         *     the read operations in Map. For example, no operation
269
 
         *     can reveal that the table has grown but the threshold
270
 
         *     has not yet been updated, so there are no atomicity
271
 
         *     requirements for this with respect to reads.
272
 
         *
273
 
         * As a guide, all critical volatile reads and writes to the
274
 
         * count field are marked in code comments.
275
 
         */
276
 
 
277
 
        private static final long serialVersionUID = 2249069246763182397L;
278
 
 
279
 
        /**
280
 
         * The number of elements in this segment's region.
281
 
         */
282
 
        transient volatile int count;
283
 
 
284
 
        /**
285
 
         * Number of updates that alter the size of the table. This is
286
 
         * used during bulk-read methods to make sure they see a
287
 
         * consistent snapshot: If modCounts change during a traversal
288
 
         * of segments computing size or checking containsValue, then
289
 
         * we might have an inconsistent view of state so (usually)
290
 
         * must retry.
291
 
         */
292
 
        transient int modCount;
293
 
 
294
 
        /**
295
 
         * The table is rehashed when its size exceeds this threshold.
296
 
         * (The value of this field is always <tt>(int)(capacity *
297
 
         * loadFactor)</tt>.)
298
 
         */
299
 
        transient int threshold;
300
 
 
301
 
        /**
302
 
         * The per-segment table.
303
 
         */
304
 
        transient volatile HashEntry<K,V>[] table;
305
 
 
306
 
        /**
307
 
         * The load factor for the hash table.  Even though this value
308
 
         * is same for all segments, it is replicated to avoid needing
309
 
         * links to outer object.
310
 
         * @serial
311
 
         */
312
 
        final float loadFactor;
313
 
 
314
 
        Segment(int initialCapacity, float lf) {
315
 
            loadFactor = lf;
316
 
            setTable(HashEntry.<K,V>newArray(initialCapacity));
317
 
        }
318
 
 
319
 
        @SuppressWarnings("unchecked")
320
 
        static final <K,V> Segment<K,V>[] newArray(int i) {
321
 
            return new Segment[i];
322
 
        }
323
 
 
324
 
        /**
325
 
         * Sets table to new HashEntry array.
326
 
         * Call only while holding lock or in constructor.
327
 
         */
328
 
        void setTable(HashEntry<K,V>[] newTable) {
329
 
            threshold = (int)(newTable.length * loadFactor);
330
 
            table = newTable;
331
 
        }
332
 
 
333
 
        /**
334
 
         * Returns properly casted first entry of bin for given hash.
335
 
         */
336
 
        HashEntry<K,V> getFirst(int hash) {
337
 
            HashEntry<K,V>[] tab = table;
338
 
            return tab[hash & (tab.length - 1)];
339
 
        }
340
 
 
341
 
        /* Specialized implementations of map methods */
342
 
 
343
 
        V get(Object key, int hash) {
344
 
            readLock().lock();
345
 
            try {
346
 
                if (count != 0) { // read-volatile
347
 
                    HashEntry<K,V> e = getFirst(hash);
348
 
                    while (e != null) {
349
 
                        if (e.hash == hash && key.equals(e.key)) {
350
 
                            return e.value;
351
 
                        }
352
 
                        e = e.next;
353
 
                    }
354
 
                }
355
 
                return null;
356
 
            } finally {
357
 
                readLock().unlock();
358
 
            }
359
 
        }
360
 
 
361
 
        boolean containsKey(Object key, int hash) {
362
 
            readLock().lock();
363
 
            try {
364
 
                if (count != 0) { // read-volatile
365
 
                    HashEntry<K,V> e = getFirst(hash);
366
 
                    while (e != null) {
367
 
                        if (e.hash == hash && key.equals(e.key))
368
 
                            return true;
369
 
                        e = e.next;
370
 
                    }
371
 
                }
372
 
                return false;
373
 
            } finally {
374
 
                readLock().unlock();
375
 
            }
376
 
        }
377
 
 
378
 
        boolean containsValue(Object value) {
379
 
            readLock().lock();
380
 
            try {
381
 
                if (count != 0) { // read-volatile
382
 
                    HashEntry<K,V>[] tab = table;
383
 
                    int len = tab.length;
384
 
                    for (int i = 0 ; i < len; i++) {
385
 
                        for (HashEntry<K,V> e = tab[i]; e != null; e = e.next) {
386
 
                            V v = e.value;
387
 
                            if (value.equals(v))
388
 
                                return true;
389
 
                        }
390
 
                    }
391
 
                }
392
 
                return false;
393
 
            } finally {
394
 
                readLock().unlock();
395
 
            }
396
 
        }
397
 
 
398
 
        boolean replace(K key, int hash, V oldValue, V newValue) {
399
 
            writeLock().lock();
400
 
            try {
401
 
                HashEntry<K,V> e = getFirst(hash);
402
 
                while (e != null && (e.hash != hash || !key.equals(e.key)))
403
 
                    e = e.next;
404
 
 
405
 
                boolean replaced = false;
406
 
                if (e != null && oldValue.equals(e.value)) {
407
 
                    replaced = true;
408
 
                    e.value = newValue;
409
 
                }
410
 
                return replaced;
411
 
            } finally {
412
 
                writeLock().unlock();
413
 
            }
414
 
        }
415
 
 
416
 
        V replace(K key, int hash, V newValue) {
417
 
            writeLock().lock();
418
 
            try {
419
 
                HashEntry<K,V> e = getFirst(hash);
420
 
                while (e != null && (e.hash != hash || !key.equals(e.key)))
421
 
                    e = e.next;
422
 
 
423
 
                V oldValue = null;
424
 
                if (e != null) {
425
 
                    oldValue = e.value;
426
 
                    e.value = newValue;
427
 
                }
428
 
                return oldValue;
429
 
            } finally {
430
 
                writeLock().unlock();
431
 
            }
432
 
        }
433
 
 
434
 
 
435
 
        V put(K key, int hash, V value, boolean onlyIfAbsent) {
436
 
            writeLock().lock();
437
 
            try {
438
 
                int c = count;
439
 
                if (c++ > threshold) // ensure capacity
440
 
                    rehash();
441
 
                HashEntry<K,V>[] tab = table;
442
 
                int index = hash & (tab.length - 1);
443
 
                HashEntry<K,V> first = tab[index];
444
 
                HashEntry<K,V> e = first;
445
 
                while (e != null && (e.hash != hash || !key.equals(e.key)))
446
 
                    e = e.next;
447
 
 
448
 
                V oldValue;
449
 
                if (e != null) {
450
 
                    oldValue = e.value;
451
 
                    if (!onlyIfAbsent)
452
 
                        e.value = value;
453
 
                }
454
 
                else {
455
 
                    oldValue = null;
456
 
                    ++modCount;
457
 
                    tab[index] = new HashEntry<K,V>(key, hash, first, value);
458
 
                    count = c; // write-volatile
459
 
                }
460
 
                return oldValue;
461
 
            } finally {
462
 
                writeLock().unlock();
463
 
            }
464
 
        }
465
 
 
466
 
        void rehash() {
467
 
            HashEntry<K,V>[] oldTable = table;
468
 
            int oldCapacity = oldTable.length;
469
 
            if (oldCapacity >= MAXIMUM_CAPACITY)
470
 
                return;
471
 
 
472
 
            /*
473
 
             * Reclassify nodes in each list to new Map.  Because we are
474
 
             * using power-of-two expansion, the elements from each bin
475
 
             * must either stay at same index, or move with a power of two
476
 
             * offset. We eliminate unnecessary node creation by catching
477
 
             * cases where old nodes can be reused because their next
478
 
             * fields won't change. Statistically, at the default
479
 
             * threshold, only about one-sixth of them need cloning when
480
 
             * a table doubles. The nodes they replace will be garbage
481
 
             * collectable as soon as they are no longer referenced by any
482
 
             * reader thread that may be in the midst of traversing table
483
 
             * right now.
484
 
             */
485
 
 
486
 
            HashEntry<K,V>[] newTable = HashEntry.newArray(oldCapacity<<1);
487
 
            threshold = (int)(newTable.length * loadFactor);
488
 
            int sizeMask = newTable.length - 1;
489
 
            for (int i = 0; i < oldCapacity ; i++) {
490
 
                // We need to guarantee that any existing reads of old Map can
491
 
                //  proceed. So we cannot yet null out each bin.
492
 
                HashEntry<K,V> e = oldTable[i];
493
 
 
494
 
                if (e != null) {
495
 
                    HashEntry<K,V> next = e.next;
496
 
                    int idx = e.hash & sizeMask;
497
 
 
498
 
                    //  Single node on list
499
 
                    if (next == null)
500
 
                        newTable[idx] = e;
501
 
 
502
 
                    else {
503
 
                        // Reuse trailing consecutive sequence at same slot
504
 
                        HashEntry<K,V> lastRun = e;
505
 
                        int lastIdx = idx;
506
 
                        for (HashEntry<K,V> last = next;
507
 
                             last != null;
508
 
                             last = last.next) {
509
 
                            int k = last.hash & sizeMask;
510
 
                            if (k != lastIdx) {
511
 
                                lastIdx = k;
512
 
                                lastRun = last;
513
 
                            }
514
 
                        }
515
 
                        newTable[lastIdx] = lastRun;
516
 
 
517
 
                        // Clone all remaining nodes
518
 
                        for (HashEntry<K,V> p = e; p != lastRun; p = p.next) {
519
 
                            int k = p.hash & sizeMask;
520
 
                            HashEntry<K,V> n = newTable[k];
521
 
                            newTable[k] = relinkHashEntry(p, n);
522
 
                        }
523
 
                    }
524
 
                }
525
 
            }
526
 
            table = newTable;
527
 
        }
528
 
 
529
 
        /**
530
 
         * Remove; match on key only if value null, else match both.
531
 
         */
532
 
        V remove(Object key, int hash, Object value) {
533
 
            writeLock().lock();
534
 
            try {
535
 
                int c = count - 1;
536
 
                HashEntry<K,V>[] tab = table;
537
 
                int index = hash & (tab.length - 1);
538
 
                HashEntry<K,V> first = tab[index];
539
 
                HashEntry<K,V> e = first;
540
 
                while (e != null && (e.hash != hash || !key.equals(e.key)))
541
 
                    e = e.next;
542
 
 
543
 
                V oldValue = null;
544
 
                if (e != null) {
545
 
                    V v = e.value;
546
 
                    if (value == null || value.equals(v)) {
547
 
                        oldValue = v;
548
 
                        // All entries following removed node can stay
549
 
                        // in list, but all preceding ones need to be
550
 
                        // cloned.
551
 
                        ++modCount;
552
 
                        HashEntry<K,V> newFirst = e.next;
553
 
                        for (HashEntry<K,V> p = first; p != e; p = p.next)
554
 
                            newFirst = relinkHashEntry(p, newFirst);
555
 
                        tab[index] = newFirst;
556
 
                        count = c; // write-volatile
557
 
                    }
558
 
                }
559
 
                return oldValue;
560
 
            } finally {
561
 
                writeLock().unlock();
562
 
            }
563
 
        }
564
 
 
565
 
        void clear() {
566
 
            writeLock().lock();
567
 
            try {
568
 
                if (count != 0) {
569
 
                    HashEntry<K,V>[] tab = table;
570
 
                    for (int i = 0; i < tab.length ; i++)
571
 
                        tab[i] = null;
572
 
                    ++modCount;
573
 
                    count = 0; // write-volatile
574
 
                }
575
 
            } finally {
576
 
                writeLock().unlock();
577
 
            }
578
 
        }
579
 
 
580
 
        protected HashEntry<K, V> relinkHashEntry(HashEntry<K,V> e, HashEntry<K,V> next) {
581
 
            return new HashEntry<K,V>(e.key, e.hash, next, e.value);
582
 
        }
583
 
    }
584
 
 
585
 
 
586
 
 
587
 
    /* ---------------- Public operations -------------- */
588
 
 
589
 
    /**
590
 
     * Creates a new, empty map with the specified initial
591
 
     * capacity, load factor and concurrency level.
592
 
     *
593
 
     * @param initialCapacity the initial capacity. The implementation
594
 
     * performs internal sizing to accommodate this many elements.
595
 
     * @param loadFactor  the load factor threshold, used to control resizing.
596
 
     * Resizing may be performed when the average number of elements per
597
 
     * bin exceeds this threshold.
598
 
     * @param concurrencyLevel the estimated number of concurrently
599
 
     * updating threads. The implementation performs internal sizing
600
 
     * to try to accommodate this many threads.
601
 
     * @throws IllegalArgumentException if the initial capacity is
602
 
     * negative or the load factor or concurrencyLevel are
603
 
     * nonpositive.
604
 
     */
605
 
    public ConcurrentHashMap(int initialCapacity,
606
 
                             float loadFactor, int concurrencyLevel) {
607
 
        if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
608
 
            throw new IllegalArgumentException();
609
 
 
610
 
        if (concurrencyLevel > MAX_SEGMENTS)
611
 
            concurrencyLevel = MAX_SEGMENTS;
612
 
 
613
 
        // Find power-of-two sizes best matching arguments
614
 
        int sshift = 0;
615
 
        int ssize = 1;
616
 
        while (ssize < concurrencyLevel) {
617
 
            ++sshift;
618
 
            ssize <<= 1;
619
 
        }
620
 
        segmentShift = 32 - sshift;
621
 
        segmentMask = ssize - 1;
622
 
        this.segments = Segment.newArray(ssize);
623
 
 
624
 
        if (initialCapacity > MAXIMUM_CAPACITY)
625
 
            initialCapacity = MAXIMUM_CAPACITY;
626
 
        int c = initialCapacity / ssize;
627
 
        if (c * ssize < initialCapacity)
628
 
            ++c;
629
 
        int cap = 1;
630
 
        while (cap < c)
631
 
            cap <<= 1;
632
 
 
633
 
        for (int i = 0; i < this.segments.length; ++i)
634
 
            this.segments[i] = createSegment(cap, loadFactor);
635
 
    }
636
 
 
637
 
    /**
638
 
     * Creates a new, empty map with the specified initial capacity,
639
 
     * and with default load factor (0.75) and concurrencyLevel (16).
640
 
     *
641
 
     * @param initialCapacity the initial capacity. The implementation
642
 
     * performs internal sizing to accommodate this many elements.
643
 
     * @throws IllegalArgumentException if the initial capacity of
644
 
     * elements is negative.
645
 
     */
646
 
    public ConcurrentHashMap(int initialCapacity) {
647
 
        this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
648
 
    }
649
 
 
650
 
    /**
651
 
     * Creates a new, empty map with a default initial capacity (16),
652
 
     * load factor (0.75) and concurrencyLevel (16).
653
 
     */
654
 
    public ConcurrentHashMap() {
655
 
        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
656
 
    }
657
 
 
658
 
    /**
659
 
     * Creates a new map with the same mappings as the given map.
660
 
     * The map is created with a capacity of 1.5 times the number
661
 
     * of mappings in the given map or 16 (whichever is greater),
662
 
     * and a default load factor (0.75) and concurrencyLevel (16).
663
 
     *
664
 
     * @param m the map
665
 
     */
666
 
    public ConcurrentHashMap(Map<? extends K, ? extends V> m) {
667
 
        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
668
 
                      DEFAULT_INITIAL_CAPACITY),
669
 
             DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
670
 
        putAll(m);
671
 
    }
672
 
 
673
 
    /**
674
 
     * Returns <tt>true</tt> if this map contains no key-value mappings.
675
 
     *
676
 
     * @return <tt>true</tt> if this map contains no key-value mappings
677
 
     */
678
 
    public boolean isEmpty() {
679
 
        final Segment<K,V>[] segments = this.segments;
680
 
        /*
681
 
         * We keep track of per-segment modCounts to avoid ABA
682
 
         * problems in which an element in one segment was added and
683
 
         * in another removed during traversal, in which case the
684
 
         * table was never actually empty at any point. Note the
685
 
         * similar use of modCounts in the size() and containsValue()
686
 
         * methods, which are the only other methods also susceptible
687
 
         * to ABA problems.
688
 
         */
689
 
        int[] mc = new int[segments.length];
690
 
        int mcsum = 0;
691
 
        for (int i = 0; i < segments.length; ++i) {
692
 
            if (segments[i].count != 0)
693
 
                return false;
694
 
            else
695
 
                mcsum += mc[i] = segments[i].modCount;
696
 
        }
697
 
        // If mcsum happens to be zero, then we know we got a snapshot
698
 
        // before any modifications at all were made.  This is
699
 
        // probably common enough to bother tracking.
700
 
        if (mcsum != 0) {
701
 
            for (int i = 0; i < segments.length; ++i) {
702
 
                if (segments[i].count != 0 ||
703
 
                    mc[i] != segments[i].modCount)
704
 
                    return false;
705
 
            }
706
 
        }
707
 
        return true;
708
 
    }
709
 
 
710
 
    /**
711
 
     * Returns the number of key-value mappings in this map.  If the
712
 
     * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
713
 
     * <tt>Integer.MAX_VALUE</tt>.
714
 
     *
715
 
     * @return the number of key-value mappings in this map
716
 
     */
717
 
    @FindBugsSuppressWarnings("UL_UNRELEASED_LOCK")
718
 
    public int size() {
719
 
        final Segment<K,V>[] segments = this.segments;
720
 
        long sum = 0;
721
 
        long check = 0;
722
 
        int[] mc = new int[segments.length];
723
 
        // Try a few times to get accurate count. On failure due to
724
 
        // continuous async changes in table, resort to locking.
725
 
        for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
726
 
            check = 0;
727
 
            sum = 0;
728
 
            int mcsum = 0;
729
 
            for (int i = 0; i < segments.length; ++i) {
730
 
                sum += segments[i].count;
731
 
                mcsum += mc[i] = segments[i].modCount;
732
 
            }
733
 
            if (mcsum != 0) {
734
 
                for (int i = 0; i < segments.length; ++i) {
735
 
                    check += segments[i].count;
736
 
                    if (mc[i] != segments[i].modCount) {
737
 
                        check = -1; // force retry
738
 
                        break;
739
 
                    }
740
 
                }
741
 
            }
742
 
            if (check == sum)
743
 
                break;
744
 
        }
745
 
        if (check != sum) { // Resort to locking all segments
746
 
            sum = 0;
747
 
            for (int i = 0; i < segments.length; ++i)
748
 
                segments[i].readLock().lock();
749
 
            try {
750
 
              for (int i = 0; i < segments.length; ++i)
751
 
                  sum += segments[i].count;
752
 
            } finally {
753
 
              for (int i = 0; i < segments.length; ++i)
754
 
                  segments[i].readLock().unlock();
755
 
            }
756
 
        }
757
 
        if (sum > Integer.MAX_VALUE)
758
 
            return Integer.MAX_VALUE;
759
 
        else
760
 
            return (int)sum;
761
 
    }
762
 
 
763
 
    /**
764
 
     * Returns the value to which the specified key is mapped,
765
 
     * or {@code null} if this map contains no mapping for the key.
766
 
     *
767
 
     * <p>More formally, if this map contains a mapping from a key
768
 
     * {@code k} to a value {@code v} such that {@code key.equals(k)},
769
 
     * then this method returns {@code v}; otherwise it returns
770
 
     * {@code null}.  (There can be at most one such mapping.)
771
 
     *
772
 
     * @throws NullPointerException if the specified key is null
773
 
     */
774
 
    public V get(Object key) {
775
 
        int hash = hash(key.hashCode());
776
 
        return segmentFor(hash).get(key, hash);
777
 
    }
778
 
 
779
 
    /**
780
 
     * Tests if the specified object is a key in this table.
781
 
     *
782
 
     * @param  key   possible key
783
 
     * @return <tt>true</tt> if and only if the specified object
784
 
     *         is a key in this table, as determined by the
785
 
     *         <tt>equals</tt> method; <tt>false</tt> otherwise.
786
 
     * @throws NullPointerException if the specified key is null
787
 
     */
788
 
    public boolean containsKey(Object key) {
789
 
        int hash = hash(key.hashCode());
790
 
        return segmentFor(hash).containsKey(key, hash);
791
 
    }
792
 
 
793
 
    /**
794
 
     * Returns <tt>true</tt> if this map maps one or more keys to the
795
 
     * specified value. Note: This method requires a full internal
796
 
     * traversal of the hash table, and so is much slower than
797
 
     * method <tt>containsKey</tt>.
798
 
     *
799
 
     * @param value value whose presence in this map is to be tested
800
 
     * @return <tt>true</tt> if this map maps one or more keys to the
801
 
     *         specified value
802
 
     * @throws NullPointerException if the specified value is null
803
 
     */
804
 
    @FindBugsSuppressWarnings("UL_UNRELEASED_LOCK")
805
 
    public boolean containsValue(Object value) {
806
 
        if (value == null)
807
 
            throw new NullPointerException();
808
 
 
809
 
        // See explanation of modCount use above
810
 
 
811
 
        final Segment<K,V>[] segments = this.segments;
812
 
        int[] mc = new int[segments.length];
813
 
 
814
 
        // Try a few times without locking
815
 
        for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
816
 
            int sum = 0;
817
 
            int mcsum = 0;
818
 
            for (int i = 0; i < segments.length; ++i) {
819
 
                int c = segments[i].count;
820
 
                mcsum += mc[i] = segments[i].modCount;
821
 
                if (segments[i].containsValue(value))
822
 
                    return true;
823
 
            }
824
 
            boolean cleanSweep = true;
825
 
            if (mcsum != 0) {
826
 
                for (int i = 0; i < segments.length; ++i) {
827
 
                    int c = segments[i].count;
828
 
                    if (mc[i] != segments[i].modCount) {
829
 
                        cleanSweep = false;
830
 
                        break;
831
 
                    }
832
 
                }
833
 
            }
834
 
            if (cleanSweep)
835
 
                return false;
836
 
        }
837
 
 
838
 
        // Resort to locking all segments
839
 
        for (int i = 0; i < segments.length; ++i)
840
 
            segments[i].readLock().lock();
841
 
        try {
842
 
            for (int i = 0; i < segments.length; ++i) {
843
 
                if (segments[i].containsValue(value)) {
844
 
                    return true;
845
 
                }
846
 
            }
847
 
        } finally {
848
 
            for (int i = 0; i < segments.length; ++i)
849
 
                segments[i].readLock().unlock();
850
 
        }
851
 
        return false;
852
 
    }
853
 
 
854
 
    /**
855
 
     * Legacy method testing if some key maps into the specified value
856
 
     * in this table.  This method is identical in functionality to
857
 
     * {@link #containsValue}, and exists solely to ensure
858
 
     * full compatibility with class {@link java.util.Hashtable},
859
 
     * which supported this method prior to introduction of the
860
 
     * Java Collections framework.
861
 
 
862
 
     * @param  value a value to search for
863
 
     * @return <tt>true</tt> if and only if some key maps to the
864
 
     *         <tt>value</tt> argument in this table as
865
 
     *         determined by the <tt>equals</tt> method;
866
 
     *         <tt>false</tt> otherwise
867
 
     * @throws NullPointerException if the specified value is null
868
 
     */
869
 
    public boolean contains(Object value) {
870
 
        return containsValue(value);
871
 
    }
872
 
 
873
 
    /**
874
 
     * Maps the specified key to the specified value in this table.
875
 
     * Neither the key nor the value can be null.
876
 
     *
877
 
     * <p> The value can be retrieved by calling the <tt>get</tt> method
878
 
     * with a key that is equal to the original key.
879
 
     *
880
 
     * @param key key with which the specified value is to be associated
881
 
     * @param value value to be associated with the specified key
882
 
     * @return the previous value associated with <tt>key</tt>, or
883
 
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>
884
 
     * @throws NullPointerException if the specified key or value is null
885
 
     */
886
 
    public V put(K key, V value) {
887
 
        if (value == null)
888
 
            throw new NullPointerException();
889
 
        int hash = hash(key.hashCode());
890
 
        return segmentFor(hash).put(key, hash, value, false);
891
 
    }
892
 
 
893
 
    /**
894
 
     * {@inheritDoc}
895
 
     *
896
 
     * @return the previous value associated with the specified key,
897
 
     *         or <tt>null</tt> if there was no mapping for the key
898
 
     * @throws NullPointerException if the specified key or value is null
899
 
     */
900
 
    public V putIfAbsent(K key, V value) {
901
 
        if (value == null)
902
 
            throw new NullPointerException();
903
 
        int hash = hash(key.hashCode());
904
 
        return segmentFor(hash).put(key, hash, value, true);
905
 
    }
906
 
 
907
 
    /**
908
 
     * Copies all of the mappings from the specified map to this one.
909
 
     * These mappings replace any mappings that this map had for any of the
910
 
     * keys currently in the specified map.
911
 
     *
912
 
     * @param m mappings to be stored in this map
913
 
     */
914
 
    public void putAll(Map<? extends K, ? extends V> m) {
915
 
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
916
 
            put(e.getKey(), e.getValue());
917
 
    }
918
 
 
919
 
    /**
920
 
     * Removes the key (and its corresponding value) from this map.
921
 
     * This method does nothing if the key is not in the map.
922
 
     *
923
 
     * @param  key the key that needs to be removed
924
 
     * @return the previous value associated with <tt>key</tt>, or
925
 
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>
926
 
     * @throws NullPointerException if the specified key is null
927
 
     */
928
 
    public V remove(Object key) {
929
 
        int hash = hash(key.hashCode());
930
 
        return segmentFor(hash).remove(key, hash, null);
931
 
    }
932
 
 
933
 
    /**
934
 
     * {@inheritDoc}
935
 
     *
936
 
     * @throws NullPointerException if the specified key is null
937
 
     */
938
 
    public boolean remove(Object key, Object value) {
939
 
        int hash = hash(key.hashCode());
940
 
        if (value == null)
941
 
            return false;
942
 
        return segmentFor(hash).remove(key, hash, value) != null;
943
 
    }
944
 
 
945
 
    /**
946
 
     * {@inheritDoc}
947
 
     *
948
 
     * @throws NullPointerException if any of the arguments are null
949
 
     */
950
 
    public boolean replace(K key, V oldValue, V newValue) {
951
 
        if (oldValue == null || newValue == null)
952
 
            throw new NullPointerException();
953
 
        int hash = hash(key.hashCode());
954
 
        return segmentFor(hash).replace(key, hash, oldValue, newValue);
955
 
    }
956
 
 
957
 
    /**
958
 
     * {@inheritDoc}
959
 
     *
960
 
     * @return the previous value associated with the specified key,
961
 
     *         or <tt>null</tt> if there was no mapping for the key
962
 
     * @throws NullPointerException if the specified key or value is null
963
 
     */
964
 
    public V replace(K key, V value) {
965
 
        if (value == null)
966
 
            throw new NullPointerException();
967
 
        int hash = hash(key.hashCode());
968
 
        return segmentFor(hash).replace(key, hash, value);
969
 
    }
970
 
 
971
 
    /**
972
 
     * Removes all of the mappings from this map.
973
 
     */
974
 
    public void clear() {
975
 
        for (int i = 0; i < segments.length; ++i)
976
 
            segments[i].clear();
977
 
    }
978
 
 
979
 
    /**
980
 
     * Returns a {@link Set} view of the keys contained in this map.
981
 
     * The set is backed by the map, so changes to the map are
982
 
     * reflected in the set, and vice-versa.  The set supports element
983
 
     * removal, which removes the corresponding mapping from this map,
984
 
     * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
985
 
     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
986
 
     * operations.  It does not support the <tt>add</tt> or
987
 
     * <tt>addAll</tt> operations.
988
 
     *
989
 
     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
990
 
     * that will never throw {@link ConcurrentModificationException},
991
 
     * and guarantees to traverse elements as they existed upon
992
 
     * construction of the iterator, and may (but is not guaranteed to)
993
 
     * reflect any modifications subsequent to construction.
994
 
     */
995
 
    public Set<K> keySet() {
996
 
        Set<K> ks = keySet;
997
 
        return (ks != null) ? ks : (keySet = new KeySet());
998
 
    }
999
 
 
1000
 
    /**
1001
 
     * Returns a {@link Collection} view of the values contained in this map.
1002
 
     * The collection is backed by the map, so changes to the map are
1003
 
     * reflected in the collection, and vice-versa.  The collection
1004
 
     * supports element removal, which removes the corresponding
1005
 
     * mapping from this map, via the <tt>Iterator.remove</tt>,
1006
 
     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
1007
 
     * <tt>retainAll</tt>, and <tt>clear</tt> operations.  It does not
1008
 
     * support the <tt>add</tt> or <tt>addAll</tt> operations.
1009
 
     *
1010
 
     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
1011
 
     * that will never throw {@link ConcurrentModificationException},
1012
 
     * and guarantees to traverse elements as they existed upon
1013
 
     * construction of the iterator, and may (but is not guaranteed to)
1014
 
     * reflect any modifications subsequent to construction.
1015
 
     */
1016
 
    public Collection<V> values() {
1017
 
        Collection<V> vs = values;
1018
 
        return (vs != null) ? vs : (values = new Values());
1019
 
    }
1020
 
 
1021
 
    /**
1022
 
     * Returns a {@link Set} view of the mappings contained in this map.
1023
 
     * The set is backed by the map, so changes to the map are
1024
 
     * reflected in the set, and vice-versa.  The set supports element
1025
 
     * removal, which removes the corresponding mapping from the map,
1026
 
     * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
1027
 
     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
1028
 
     * operations.  It does not support the <tt>add</tt> or
1029
 
     * <tt>addAll</tt> operations.
1030
 
     *
1031
 
     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
1032
 
     * that will never throw {@link ConcurrentModificationException},
1033
 
     * and guarantees to traverse elements as they existed upon
1034
 
     * construction of the iterator, and may (but is not guaranteed to)
1035
 
     * reflect any modifications subsequent to construction.
1036
 
     */
1037
 
    public Set<Map.Entry<K,V>> entrySet() {
1038
 
        Set<Map.Entry<K,V>> es = entrySet;
1039
 
        return (es != null) ? es : (entrySet = new EntrySet());
1040
 
    }
1041
 
 
1042
 
    /**
1043
 
     * Returns an enumeration of the keys in this table.
1044
 
     *
1045
 
     * @return an enumeration of the keys in this table
1046
 
     * @see #keySet()
1047
 
     */
1048
 
    public Enumeration<K> keys() {
1049
 
        return new KeyIterator();
1050
 
    }
1051
 
 
1052
 
    /**
1053
 
     * Returns an enumeration of the values in this table.
1054
 
     *
1055
 
     * @return an enumeration of the values in this table
1056
 
     * @see #values()
1057
 
     */
1058
 
    public Enumeration<V> elements() {
1059
 
        return new ValueIterator();
1060
 
    }
1061
 
 
1062
 
    /* ---------------- Iterator Support -------------- */
1063
 
 
1064
 
    abstract class HashIterator {
1065
 
        int nextSegmentIndex;
1066
 
        int nextTableIndex;
1067
 
        HashEntry<K,V>[] currentTable;
1068
 
        HashEntry<K, V> nextEntry;
1069
 
        HashEntry<K, V> lastReturned;
1070
 
 
1071
 
        HashIterator() {
1072
 
            nextSegmentIndex = segments.length - 1;
1073
 
            nextTableIndex = -1;
1074
 
            advance();
1075
 
        }
1076
 
 
1077
 
        public boolean hasMoreElements() { return hasNext(); }
1078
 
 
1079
 
        final void advance() {
1080
 
            if (nextEntry != null && (nextEntry = nextEntry.next) != null)
1081
 
                return;
1082
 
 
1083
 
            while (nextTableIndex >= 0) {
1084
 
                if ( (nextEntry = currentTable[nextTableIndex--]) != null)
1085
 
                    return;
1086
 
            }
1087
 
 
1088
 
            while (nextSegmentIndex >= 0) {
1089
 
                Segment<K,V> seg = segments[nextSegmentIndex--];
1090
 
                if (seg.count != 0) {
1091
 
                    currentTable = seg.table;
1092
 
                    for (int j = currentTable.length - 1; j >= 0; --j) {
1093
 
                        if ( (nextEntry = currentTable[j]) != null) {
1094
 
                            nextTableIndex = j - 1;
1095
 
                            return;
1096
 
                        }
1097
 
                    }
1098
 
                }
1099
 
            }
1100
 
        }
1101
 
 
1102
 
        public boolean hasNext() { return nextEntry != null; }
1103
 
 
1104
 
        HashEntry<K,V> nextEntry() {
1105
 
            if (nextEntry == null)
1106
 
                throw new NoSuchElementException();
1107
 
            lastReturned = nextEntry;
1108
 
            advance();
1109
 
            return lastReturned;
1110
 
        }
1111
 
 
1112
 
        public void remove() {
1113
 
            if (lastReturned == null)
1114
 
                throw new IllegalStateException();
1115
 
            ConcurrentHashMap.this.remove(lastReturned.key);
1116
 
            lastReturned = null;
1117
 
        }
1118
 
    }
1119
 
 
1120
 
    final class KeyIterator
1121
 
        extends HashIterator
1122
 
        implements Iterator<K>, Enumeration<K>
1123
 
    {
1124
 
        public K next()        { return super.nextEntry().key; }
1125
 
        public K nextElement() { return super.nextEntry().key; }
1126
 
    }
1127
 
 
1128
 
    final class ValueIterator
1129
 
        extends HashIterator
1130
 
        implements Iterator<V>, Enumeration<V>
1131
 
    {
1132
 
        public V next()        { return super.nextEntry().value; }
1133
 
        public V nextElement() { return super.nextEntry().value; }
1134
 
    }
1135
 
 
1136
 
    /**
1137
 
     * Custom Entry class used by EntryIterator.next(), that relays
1138
 
     * setValue changes to the underlying map.
1139
 
     */
1140
 
    final class WriteThroughEntry
1141
 
        extends SimpleEntry<K,V>
1142
 
    {
1143
 
        WriteThroughEntry(K k, V v) {
1144
 
            super(k,v);
1145
 
        }
1146
 
 
1147
 
        /**
1148
 
         * Set our entry's value and write through to the map. The
1149
 
         * value to return is somewhat arbitrary here. Since a
1150
 
         * WriteThroughEntry does not necessarily track asynchronous
1151
 
         * changes, the most recent "previous" value could be
1152
 
         * different from what we return (or could even have been
1153
 
         * removed in which case the put will re-establish). We do not
1154
 
         * and cannot guarantee more.
1155
 
         */
1156
 
        public V setValue(V value) {
1157
 
            if (value == null) throw new NullPointerException();
1158
 
            V v = super.setValue(value);
1159
 
            ConcurrentHashMap.this.put(getKey(), value);
1160
 
            return v;
1161
 
        }
1162
 
    }
1163
 
 
1164
 
    final class EntryIterator
1165
 
        extends HashIterator
1166
 
        implements Iterator<Entry<K,V>>
1167
 
    {
1168
 
        public Map.Entry<K,V> next() {
1169
 
            HashEntry<K,V> e = super.nextEntry();
1170
 
            return new WriteThroughEntry(e.key, e.value);
1171
 
        }
1172
 
    }
1173
 
 
1174
 
    final class KeySet extends AbstractSet<K> {
1175
 
        public Iterator<K> iterator() {
1176
 
            return new KeyIterator();
1177
 
        }
1178
 
        public int size() {
1179
 
            return ConcurrentHashMap.this.size();
1180
 
        }
1181
 
        public boolean isEmpty() {
1182
 
            return ConcurrentHashMap.this.isEmpty();
1183
 
        }
1184
 
        public boolean contains(Object o) {
1185
 
            return ConcurrentHashMap.this.containsKey(o);
1186
 
        }
1187
 
        public boolean remove(Object o) {
1188
 
            return ConcurrentHashMap.this.remove(o) != null;
1189
 
        }
1190
 
        public void clear() {
1191
 
            ConcurrentHashMap.this.clear();
1192
 
        }
1193
 
        public Object[] toArray() {
1194
 
            Collection<K> c = new ArrayList<K>();
1195
 
            for (Iterator<K> i = iterator(); i.hasNext(); )
1196
 
                c.add(i.next());
1197
 
            return c.toArray();
1198
 
        }
1199
 
        public <T> T[] toArray(T[] a) {
1200
 
            Collection<K> c = new ArrayList<K>();
1201
 
            for (Iterator<K> i = iterator(); i.hasNext(); )
1202
 
                c.add(i.next());
1203
 
            return c.toArray(a);
1204
 
        }
1205
 
    }
1206
 
 
1207
 
    final class Values extends AbstractCollection<V> {
1208
 
        public Iterator<V> iterator() {
1209
 
            return new ValueIterator();
1210
 
        }
1211
 
        public int size() {
1212
 
            return ConcurrentHashMap.this.size();
1213
 
        }
1214
 
        public boolean isEmpty() {
1215
 
            return ConcurrentHashMap.this.isEmpty();
1216
 
        }
1217
 
        public boolean contains(Object o) {
1218
 
            return ConcurrentHashMap.this.containsValue(o);
1219
 
        }
1220
 
        public void clear() {
1221
 
            ConcurrentHashMap.this.clear();
1222
 
        }
1223
 
        public Object[] toArray() {
1224
 
            Collection<V> c = new ArrayList<V>();
1225
 
            for (Iterator<V> i = iterator(); i.hasNext(); )
1226
 
                c.add(i.next());
1227
 
            return c.toArray();
1228
 
        }
1229
 
        public <T> T[] toArray(T[] a) {
1230
 
            Collection<V> c = new ArrayList<V>();
1231
 
            for (Iterator<V> i = iterator(); i.hasNext(); )
1232
 
                c.add(i.next());
1233
 
            return c.toArray(a);
1234
 
        }
1235
 
    }
1236
 
 
1237
 
    final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
1238
 
        public Iterator<Map.Entry<K,V>> iterator() {
1239
 
            return new EntryIterator();
1240
 
        }
1241
 
        public boolean contains(Object o) {
1242
 
            if (!(o instanceof Map.Entry))
1243
 
                return false;
1244
 
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
1245
 
            V v = ConcurrentHashMap.this.get(e.getKey());
1246
 
            return v != null && v.equals(e.getValue());
1247
 
        }
1248
 
        public boolean remove(Object o) {
1249
 
            if (!(o instanceof Map.Entry))
1250
 
                return false;
1251
 
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
1252
 
            return ConcurrentHashMap.this.remove(e.getKey(), e.getValue());
1253
 
        }
1254
 
        public int size() {
1255
 
            return ConcurrentHashMap.this.size();
1256
 
        }
1257
 
        public boolean isEmpty() {
1258
 
            return ConcurrentHashMap.this.isEmpty();
1259
 
        }
1260
 
        public void clear() {
1261
 
            ConcurrentHashMap.this.clear();
1262
 
        }
1263
 
        public Object[] toArray() {
1264
 
            Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>();
1265
 
            for (Iterator<Map.Entry<K,V>> i = iterator(); i.hasNext(); )
1266
 
                c.add(i.next());
1267
 
            return c.toArray();
1268
 
        }
1269
 
        public <T> T[] toArray(T[] a) {
1270
 
            Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>();
1271
 
            for (Iterator<Map.Entry<K,V>> i = iterator(); i.hasNext(); )
1272
 
                c.add(i.next());
1273
 
            return c.toArray(a);
1274
 
        }
1275
 
    }
1276
 
 
1277
 
    /**
1278
 
     * This duplicates java.util.AbstractMap.SimpleEntry until this class
1279
 
     * is made accessible.
1280
 
     */
1281
 
    static class SimpleEntry<K,V> implements Entry<K,V> {
1282
 
        K key;
1283
 
        V value;
1284
 
 
1285
 
        public SimpleEntry(K key, V value) {
1286
 
            this.key   = key;
1287
 
            this.value = value;
1288
 
        }
1289
 
 
1290
 
        public SimpleEntry(Entry<K,V> e) {
1291
 
            this.key   = e.getKey();
1292
 
            this.value = e.getValue();
1293
 
        }
1294
 
 
1295
 
        public K getKey() {
1296
 
            return key;
1297
 
        }
1298
 
 
1299
 
        public V getValue() {
1300
 
            return value;
1301
 
        }
1302
 
 
1303
 
        public V setValue(V value) {
1304
 
            V oldValue = this.value;
1305
 
            this.value = value;
1306
 
            return oldValue;
1307
 
        }
1308
 
 
1309
 
        public boolean equals(Object o) {
1310
 
            if (!(o instanceof Map.Entry))
1311
 
                return false;
1312
 
            Map.Entry e = (Map.Entry)o;
1313
 
            return eq(key, e.getKey()) && eq(value, e.getValue());
1314
 
        }
1315
 
 
1316
 
        public int hashCode() {
1317
 
            return ((key   == null)   ? 0 :   key.hashCode()) ^
1318
 
                    ((value == null)   ? 0 : value.hashCode());
1319
 
        }
1320
 
 
1321
 
        public String toString() {
1322
 
            return key + "=" + value;
1323
 
        }
1324
 
 
1325
 
        static boolean eq(Object o1, Object o2) {
1326
 
            return (o1 == null ? o2 == null : o1.equals(o2));
1327
 
        }
1328
 
    }
1329
 
 
1330
 
   /* ---------------- Serialization Support -------------- */
1331
 
 
1332
 
    /**
1333
 
     * Save the state of the <tt>ConcurrentHashMap</tt> instance to a
1334
 
     * stream (i.e., serialize it).
1335
 
     * @param s the stream
1336
 
     * @serialData
1337
 
     * the key (Object) and value (Object)
1338
 
     * for each key-value mapping, followed by a null pair.
1339
 
     * The key-value mappings are emitted in no particular order.
1340
 
     */
1341
 
    private void writeObject(java.io.ObjectOutputStream s) throws IOException  {
1342
 
        s.defaultWriteObject();
1343
 
 
1344
 
        for (int k = 0; k < segments.length; ++k) {
1345
 
            Segment<K,V> seg = segments[k];
1346
 
            seg.readLock().lock();
1347
 
            try {
1348
 
                HashEntry<K,V>[] tab = seg.table;
1349
 
                for (int i = 0; i < tab.length; ++i) {
1350
 
                    for (HashEntry<K,V> e = tab[i]; e != null; e = e.next) {
1351
 
                        s.writeObject(e.key);
1352
 
                        s.writeObject(e.value);
1353
 
                    }
1354
 
                }
1355
 
            } finally {
1356
 
                seg.readLock().unlock();
1357
 
            }
1358
 
        }
1359
 
        s.writeObject(null);
1360
 
        s.writeObject(null);
1361
 
    }
1362
 
 
1363
 
    /**
1364
 
     * Reconstitute the <tt>ConcurrentHashMap</tt> instance from a
1365
 
     * stream (i.e., deserialize it).
1366
 
     * @param s the stream
1367
 
     */
1368
 
    private void readObject(java.io.ObjectInputStream s)
1369
 
        throws IOException, ClassNotFoundException  {
1370
 
        s.defaultReadObject();
1371
 
 
1372
 
        // Initialize each segment to be minimally sized, and let grow.
1373
 
        for (int i = 0; i < segments.length; ++i) {
1374
 
            segments[i].setTable(new HashEntry[1]);
1375
 
        }
1376
 
 
1377
 
        // Read the keys and values, and put the mappings in the table
1378
 
        for (;;) {
1379
 
            K key = (K) s.readObject();
1380
 
            V value = (V) s.readObject();
1381
 
            if (key == null)
1382
 
                break;
1383
 
            put(key, value);
1384
 
        }
1385
 
    }
1386
 
}