ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentHashMap.java
Revision: 1.45
Committed: Sat Apr 10 14:21:45 2004 UTC (20 years, 1 month ago) by dl
Branch: MAIN
Changes since 1.44: +194 -143 lines
Log Message:
Conform to JSR133:
Declare HashEntry.value field volatile to ensure ordering
Reread value to deal with cases of HashEntry initialization reorderings
Force ordering during rehash by making table field volatile
Eliminate possiblilty of infinite retry in size and containsValue
Minor changes to private method decls  to simplify the above
Make internal docuemntation match code.

File Contents

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