View Javadoc

1   /*
2    File: ConcurrentReaderHashMap
3   
4    Written by Doug Lea. Adapted and released, under explicit
5    permission, from JDK1.2 HashMap.java and Hashtable.java which
6    carries the following copyright:
7   
8    * Copyright 1997 by Sun Microsystems, Inc.,
9    * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
10   * All rights reserved.
11   *
12   * This software is the confidential and proprietary information
13   * of Sun Microsystems, Inc. ("Confidential Information").  You
14   * shall not disclose such Confidential Information and shall use
15   * it only in accordance with the terms of the license agreement
16   * you entered into with Sun.
17  
18   History:
19   Date       Who                What
20   28oct1999  dl               Created
21   14dec1999  dl               jmm snapshot
22   19apr2000  dl               use barrierLock
23   12jan2001  dl               public release
24   17nov2001  dl               Minor tunings
25   20may2002  dl               BarrierLock can now be serialized.
26   09dec2002  dl               Fix interference checks.
27   */
28  
29  package org.dom4j.tree;
30  
31  import java.io.IOException;
32  import java.io.Serializable;
33  import java.util.AbstractCollection;
34  import java.util.AbstractMap;
35  import java.util.AbstractSet;
36  import java.util.Collection;
37  import java.util.Enumeration;
38  import java.util.Iterator;
39  import java.util.Map;
40  import java.util.NoSuchElementException;
41  import java.util.Set;
42  
43  /***
44   * A version of Hashtable that supports mostly-concurrent reading, but exclusive
45   * writing. Because reads are not limited to periods without writes, a
46   * concurrent reader policy is weaker than a classic reader/writer policy, but
47   * is generally faster and allows more concurrency. This class is a good choice
48   * especially for tables that are mainly created by one thread during the
49   * start-up phase of a program, and from then on, are mainly read (with perhaps
50   * occasional additions or removals) in many threads. If you also need
51   * concurrency among writes, consider instead using ConcurrentHashMap.
52   * <p>
53   * 
54   * Successful retrievals using get(key) and containsKey(key) usually run without
55   * locking. Unsuccessful ones (i.e., when the key is not present) do involve
56   * brief synchronization (locking). Also, the size and isEmpty methods are
57   * always synchronized.
58   * 
59   * <p>
60   * Because retrieval operations can ordinarily overlap with writing operations
61   * (i.e., put, remove, and their derivatives), retrievals can only be guaranteed
62   * to return the results of the most recently <em>completed</em> operations
63   * holding upon their onset. Retrieval operations may or may not return results
64   * reflecting in-progress writing operations. However, the retrieval operations
65   * do always return consistent results -- either those holding before any single
66   * modification or after it, but never a nonsense result. For aggregate
67   * operations such as putAll and clear, concurrent reads may reflect insertion
68   * or removal of only some entries. In those rare contexts in which you use a
69   * hash table to synchronize operations across threads (for example, to prevent
70   * reads until after clears), you should either encase operations in
71   * synchronized blocks, or instead use java.util.Hashtable.
72   * 
73   * <p>
74   * 
75   * This class also supports optional guaranteed exclusive reads, simply by
76   * surrounding a call within a synchronized block, as in <br>
77   * <code>ConcurrentReaderHashMap t; ... Object v; <br>
78   * synchronized(t) { v = t.get(k); } </code><br>
79   * 
80   * But this is not usually necessary in practice. For example, it is generally
81   * inefficient to write:
82   * 
83   * <pre>
84   * 
85   *  
86   *     ConcurrentReaderHashMap t; ...            // Inefficient version
87   *     Object key; ...
88   *     Object value; ...
89   *     synchronized(t) { 
90   *       if (!t.containsKey(key))
91   *         t.put(key, value);
92   *         // other code if not previously present
93   *       }
94   *       else {
95   *         // other code if it was previously present
96   *       }
97   *     }
98   *  
99   *  
100  * </pre>
101  * 
102  * Instead, if the values are intended to be the same in each case, just take
103  * advantage of the fact that put returns null if the key was not previously
104  * present:
105  * 
106  * <pre>
107  * 
108  *  
109  *     ConcurrentReaderHashMap t; ...                // Use this instead
110  *     Object key; ...
111  *     Object value; ...
112  *     Object oldValue = t.put(key, value);
113  *     if (oldValue == null) {
114  *       // other code if not previously present
115  *     }
116  *     else {
117  *       // other code if it was previously present
118  *     }
119  *  
120  *  
121  * </pre>
122  * 
123  * <p>
124  * 
125  * Iterators and Enumerations (i.e., those returned by keySet().iterator(),
126  * entrySet().iterator(), values().iterator(), keys(), and elements()) return
127  * elements reflecting the state of the hash table at some point at or since the
128  * creation of the iterator/enumeration. They will return at most one instance
129  * of each element (via next()/nextElement()), but might or might not reflect
130  * puts and removes that have been processed since they were created. They do
131  * <em>not</em> throw ConcurrentModificationException. However, these
132  * iterators are designed to be used by only one thread at a time. Sharing an
133  * iterator across multiple threads may lead to unpredictable results if the
134  * table is being concurrently modified. Again, you can ensure interference-free
135  * iteration by enclosing the iteration in a synchronized block.
136  * <p>
137  * 
138  * This class may be used as a direct replacement for any use of
139  * java.util.Hashtable that does not depend on readers being blocked during
140  * updates. Like Hashtable but unlike java.util.HashMap, this class does NOT
141  * allow <tt>null</tt> to be used as a key or value. This class is also
142  * typically faster than ConcurrentHashMap when there is usually only one thread
143  * updating the table, but possibly many retrieving values from it.
144  * <p>
145  * 
146  * Implementation note: A slightly faster implementation of this class will be
147  * possible once planned Java Memory Model revisions are in place.
148  * 
149  * <p>[ <a
150  * href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html">
151  * Introduction to this package. </a>]
152  * 
153  */
154 
155 class ConcurrentReaderHashMap extends AbstractMap implements Map, Cloneable,
156         Serializable {
157 
158     /*
159      * The basic strategy is an optimistic-style scheme based on the guarantee
160      * that the hash table and its lists are always kept in a consistent enough
161      * state to be read without locking:
162      * 
163      * Read operations first proceed without locking, by traversing the
164      * apparently correct list of the apparently correct bin. If an entry is
165      * found, but not invalidated (value field null), it is returned. If not
166      * found, operations must recheck (after a memory barrier) to make sure they
167      * are using both the right list and the right table (which can change under
168      * resizes). If invalidated, reads must acquire main update lock to wait out
169      * the update, and then re-traverse.
170      * 
171      * All list additions are at the front of each bin, making it easy to check
172      * changes, and also fast to traverse. Entry next pointers are never
173      * assigned. Remove() builds new nodes when necessary to preserve this.
174      * 
175      * Remove() (also clear()) invalidates removed nodes to alert read
176      * operations that they must wait out the full modifications.
177      * 
178      */
179 
180     /*** A Serializable class for barrier lock * */
181     protected static class BarrierLock implements java.io.Serializable {
182     }
183 
184     /***
185      * Lock used only for its memory effects.
186      */
187     protected final BarrierLock barrierLock = new BarrierLock();
188 
189     /***
190      * field written to only to guarantee lock ordering.
191      */
192 
193     protected transient Object lastWrite;
194 
195     /***
196      * Force a memory synchronization that will cause all readers to see table.
197      * Call only when already holding main synch lock.
198      */
199     protected final void recordModification(Object x) {
200         synchronized (barrierLock) {
201             lastWrite = x;
202         }
203     }
204 
205     /***
206      * Get ref to table; the reference and the cells it accesses will be at
207      * least as fresh as from last use of barrierLock
208      */
209     protected final Entry[] getTableForReading() {
210         synchronized (barrierLock) {
211             return table;
212         }
213     }
214 
215     /***
216      * The default initial number of table slots for this table (32). Used when
217      * not otherwise specified in constructor.
218      */
219     public static int DEFAULT_INITIAL_CAPACITY = 32;
220 
221     /***
222      * The minimum capacity, used if a lower value is implicitly specified by
223      * either of the constructors with arguments. MUST be a power of two.
224      */
225     private static final int MINIMUM_CAPACITY = 4;
226 
227     /***
228      * The maximum capacity, used if a higher value is implicitly specified by
229      * either of the constructors with arguments. MUST be a power of two <= 1 <
230      * <30.
231      */
232     private static final int MAXIMUM_CAPACITY = 1 << 30;
233 
234     /***
235      * The default load factor for this table (1.0). Used when not otherwise
236      * specified in constructor.
237      */
238 
239     public static final float DEFAULT_LOAD_FACTOR = 0.75f;
240 
241     /***
242      * The hash table data.
243      */
244     protected transient Entry[] table;
245 
246     /***
247      * The total number of mappings in the hash table.
248      */
249     protected transient int count;
250 
251     /***
252      * The table is rehashed when its size exceeds this threshold. (The value of
253      * this field is always (int)(capacity * loadFactor).)
254      * 
255      * @serial
256      */
257     protected int threshold;
258 
259     /***
260      * The load factor for the hash table.
261      * 
262      * @serial
263      */
264     protected float loadFactor;
265 
266     /***
267      * Returns the appropriate capacity (power of two) for the specified initial
268      * capacity argument.
269      */
270     private int p2capacity(int initialCapacity) {
271         int cap = initialCapacity;
272 
273         // Compute the appropriate capacity
274         int result;
275         if (cap > MAXIMUM_CAPACITY || cap < 0) {
276             result = MAXIMUM_CAPACITY;
277         } else {
278             result = MINIMUM_CAPACITY;
279             while (result < cap)
280                 result <<= 1;
281         }
282         return result;
283     }
284 
285     /***
286      * Return hash code for Object x. Since we are using power-of-two tables, it
287      * is worth the effort to improve hashcode via the same multiplicative
288      * scheme as used in IdentityHashMap.
289      */
290     private static int hash(Object x) {
291         int h = x.hashCode();
292         // Multiply by 127 (quickly, via shifts), and mix in some high
293         // bits to help guard against bunching of codes that are
294         // consecutive or equally spaced.
295         return ((h << 7) - h + (h >>> 9) + (h >>> 17));
296     }
297 
298     /***
299      * Check for equality of non-null references x and y.
300      */
301     protected boolean eq(Object x, Object y) {
302         return x == y || x.equals(y);
303     }
304 
305     /***
306      * Constructs a new, empty map with the specified initial capacity and the
307      * specified load factor.
308      * 
309      * @param initialCapacity
310      *            the initial capacity The actual initial capacity is rounded to
311      *            the nearest power of two.
312      * @param loadFactor
313      *            the load factor of the ConcurrentReaderHashMap
314      * @throws IllegalArgumentException
315      *             if the initial maximum number of elements is less than zero,
316      *             or if the load factor is nonpositive.
317      */
318 
319     public ConcurrentReaderHashMap(int initialCapacity, float loadFactor) {
320         if (loadFactor <= 0)
321             throw new IllegalArgumentException("Illegal Load factor: "
322                     + loadFactor);
323         this.loadFactor = loadFactor;
324 
325         int cap = p2capacity(initialCapacity);
326 
327         table = new Entry[cap];
328         threshold = (int) (cap * loadFactor);
329     }
330 
331     /***
332      * Constructs a new, empty map with the specified initial capacity and
333      * default load factor.
334      * 
335      * @param initialCapacity
336      *            the initial capacity of the ConcurrentReaderHashMap.
337      * @throws IllegalArgumentException
338      *             if the initial maximum number of elements is less than zero.
339      */
340 
341     public ConcurrentReaderHashMap(int initialCapacity) {
342         this(initialCapacity, DEFAULT_LOAD_FACTOR);
343     }
344 
345     /***
346      * Constructs a new, empty map with a default initial capacity and load
347      * factor.
348      */
349 
350     public ConcurrentReaderHashMap() {
351         this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
352     }
353 
354     /***
355      * Constructs a new map with the same mappings as the given map. The map is
356      * created with a capacity of twice the number of mappings in the given map
357      * or 16 (whichever is greater), and a default load factor.
358      */
359 
360     public ConcurrentReaderHashMap(Map t) {
361         this(Math.max((int) (t.size() / DEFAULT_LOAD_FACTOR) + 1, 16),
362                 DEFAULT_LOAD_FACTOR);
363         putAll(t);
364     }
365 
366     /***
367      * Returns the number of key-value mappings in this map.
368      * 
369      * @return the number of key-value mappings in this map.
370      */
371 
372     public synchronized int size() {
373         return count;
374     }
375 
376     /***
377      * Returns <tt>true</tt> if this map contains no key-value mappings.
378      * 
379      * @return <tt>true</tt> if this map contains no key-value mappings.
380      */
381 
382     public synchronized boolean isEmpty() {
383         return count == 0;
384     }
385 
386     /***
387      * Returns the value to which the specified key is mapped in this table.
388      * 
389      * @param key
390      *            a key in the table.
391      * @return the value to which the key is mapped in this table;
392      *         <code>null</code> if the key is not mapped to any value in this
393      *         table.
394      * @exception NullPointerException
395      *                if the key is <code>null</code>.
396      * @see #put(Object, Object)
397      */
398 
399     public Object get(Object key) {
400 
401         // throw null pointer exception if key null
402         int hash = hash(key);
403 
404         /*
405          * Start off at the apparently correct bin. If entry is found, we need
406          * to check after a barrier anyway. If not found, we need a barrier to
407          * check if we are actually in right bin. So either way, we encounter
408          * only one barrier unless we need to retry. And we only need to fully
409          * synchronize if there have been concurrent modifications.
410          */
411 
412         Entry[] tab = table;
413         int index = hash & (tab.length - 1);
414         Entry first = tab[index];
415         Entry e = first;
416 
417         for (;;) {
418             if (e == null) {
419 
420                 // If key apparently not there, check to
421                 // make sure this was a valid read
422 
423                 Entry[] reread = getTableForReading();
424                 if (tab == reread && first == tab[index])
425                     return null;
426                 else {
427                     // Wrong list -- must restart traversal at new first
428                     tab = reread;
429                     e = first = tab[index = hash & (tab.length - 1)];
430                 }
431 
432             }
433 
434             else if (e.hash == hash && eq(key, e.key)) {
435                 Object value = e.value;
436                 if (value != null)
437                     return value;
438 
439                 // Entry was invalidated during deletion. But it could
440                 // have been re-inserted, so we must retraverse.
441                 // To avoid useless contention, get lock to wait out
442                 // modifications
443                 // before retraversing.
444 
445                 synchronized (this) {
446                     tab = table;
447                 }
448                 e = first = tab[index = hash & (tab.length - 1)];
449 
450             } else
451                 e = e.next;
452         }
453     }
454 
455     /***
456      * Tests if the specified object is a key in this table.
457      * 
458      * @param key
459      *            possible key.
460      * @return <code>true</code> if and only if the specified object is a key
461      *         in this table, as determined by the <tt>equals</tt> method;
462      *         <code>false</code> otherwise.
463      * @exception NullPointerException
464      *                if the key is <code>null</code>.
465      * @see #contains(Object)
466      */
467 
468     public boolean containsKey(Object key) {
469         return get(key) != null;
470     }
471 
472     /***
473      * Maps the specified <code>key</code> to the specified <code>value</code>
474      * in this table. Neither the key nor the value can be <code>null</code>.
475      * <p>
476      * 
477      * The value can be retrieved by calling the <code>get</code> method with
478      * a key that is equal to the original key.
479      * 
480      * @param key
481      *            the table key.
482      * @param value
483      *            the value.
484      * @return the previous value of the specified key in this table, or
485      *         <code>null</code> if it did not have one.
486      * @exception NullPointerException
487      *                if the key or value is <code>null</code>.
488      * @see Object#equals(Object)
489      * @see #get(Object)
490      */
491 
492     public Object put(Object key, Object value) {
493         if (value == null)
494             throw new NullPointerException();
495 
496         int hash = hash(key);
497         Entry[] tab = table;
498         int index = hash & (tab.length - 1);
499         Entry first = tab[index];
500         Entry e;
501 
502         for (e = first; e != null; e = e.next)
503             if (e.hash == hash && eq(key, e.key))
504                 break;
505 
506         synchronized (this) {
507             if (tab == table) {
508                 if (e == null) {
509                     // make sure we are adding to correct list
510                     if (first == tab[index]) {
511                         // Add to front of list
512                         Entry newEntry = new Entry(hash, key, value, first);
513                         tab[index] = newEntry;
514                         if (++count >= threshold)
515                             rehash();
516                         else
517                             recordModification(newEntry);
518                         return null;
519                     }
520                 } else {
521                     Object oldValue = e.value;
522                     if (first == tab[index] && oldValue != null) {
523                         e.value = value;
524                         return oldValue;
525                     }
526                 }
527             }
528 
529             // retry if wrong list or lost race against concurrent remove
530             return sput(key, value, hash);
531         }
532     }
533 
534     /***
535      * Continuation of put(), called only when synch lock is held and
536      * interference has been detected.
537      */
538     protected Object sput(Object key, Object value, int hash) {
539 
540         Entry[] tab = table;
541         int index = hash & (tab.length - 1);
542         Entry first = tab[index];
543         Entry e = first;
544 
545         for (;;) {
546             if (e == null) {
547                 Entry newEntry = new Entry(hash, key, value, first);
548                 tab[index] = newEntry;
549                 if (++count >= threshold)
550                     rehash();
551                 else
552                     recordModification(newEntry);
553                 return null;
554             } else if (e.hash == hash && eq(key, e.key)) {
555                 Object oldValue = e.value;
556                 e.value = value;
557                 return oldValue;
558             } else
559                 e = e.next;
560         }
561     }
562 
563     /***
564      * Rehashes the contents of this map into a new table with a larger
565      * capacity. This method is called automatically when the number of keys in
566      * this map exceeds its capacity and load factor.
567      */
568     protected void rehash() {
569         Entry[] oldTable = table;
570         int oldCapacity = oldTable.length;
571         if (oldCapacity >= MAXIMUM_CAPACITY) {
572             threshold = Integer.MAX_VALUE; // avoid retriggering
573             return;
574         }
575 
576         int newCapacity = oldCapacity << 1;
577         int mask = newCapacity - 1;
578         threshold = (int) (newCapacity * loadFactor);
579 
580         Entry[] newTable = new Entry[newCapacity];
581         /*
582          * Reclassify nodes in each list to new Map. Because we are using
583          * power-of-two expansion, the elements from each bin must either stay
584          * at same index, or move to oldCapacity+index. We also eliminate
585          * unnecessary node creation by catching cases where old nodes can be
586          * reused because their next fields won't change. Statistically, at the
587          * default threshhold, only about one-sixth of them need cloning. (The
588          * nodes they replace will be garbage collectable as soon as they are no
589          * longer referenced by any reader thread that may be in the midst of
590          * traversing table right now.)
591          */
592 
593         for (int i = 0; i < oldCapacity; i++) {
594             // We need to guarantee that any existing reads of old Map can
595             // proceed. So we cannot yet null out each bin.
596             Entry e = oldTable[i];
597 
598             if (e != null) {
599                 int idx = e.hash & mask;
600                 Entry next = e.next;
601 
602                 // Single node on list
603                 if (next == null)
604                     newTable[idx] = e;
605 
606                 else {
607                     // Reuse trailing consecutive sequence of all same bit
608                     Entry lastRun = e;
609                     int lastIdx = idx;
610                     for (Entry last = next; last != null; last = last.next) {
611                         int k = last.hash & mask;
612                         if (k != lastIdx) {
613                             lastIdx = k;
614                             lastRun = last;
615                         }
616                     }
617                     newTable[lastIdx] = lastRun;
618 
619                     // Clone all remaining nodes
620                     for (Entry p = e; p != lastRun; p = p.next) {
621                         int k = p.hash & mask;
622                         newTable[k] = new Entry(p.hash, p.key, p.value,
623                                 newTable[k]);
624                     }
625                 }
626             }
627         }
628 
629         table = newTable;
630         recordModification(newTable);
631     }
632 
633     /***
634      * Removes the key (and its corresponding value) from this table. This
635      * method does nothing if the key is not in the table.
636      * 
637      * @param key
638      *            the key that needs to be removed.
639      * @return the value to which the key had been mapped in this table, or
640      *         <code>null</code> if the key did not have a mapping.
641      * @exception NullPointerException
642      *                if the key is <code>null</code>.
643      */
644 
645     public Object remove(Object key) {
646         /*
647          * Find the entry, then 1. Set value field to null, to force get() to
648          * retry 2. Rebuild the list without this entry. All entries following
649          * removed node can stay in list, but all preceeding ones need to be
650          * cloned. Traversals rely on this strategy to ensure that elements will
651          * not be repeated during iteration.
652          */
653 
654         int hash = hash(key);
655         Entry[] tab = table;
656         int index = hash & (tab.length - 1);
657         Entry first = tab[index];
658         Entry e = first;
659 
660         for (e = first; e != null; e = e.next)
661             if (e.hash == hash && eq(key, e.key))
662                 break;
663 
664         synchronized (this) {
665             if (tab == table) {
666                 if (e == null) {
667                     if (first == tab[index])
668                         return null;
669                 } else {
670                     Object oldValue = e.value;
671                     if (first == tab[index] && oldValue != null) {
672                         e.value = null;
673                         count--;
674 
675                         Entry head = e.next;
676                         for (Entry p = first; p != e; p = p.next)
677                             head = new Entry(p.hash, p.key, p.value, head);
678 
679                         tab[index] = head;
680                         recordModification(head);
681                         return oldValue;
682                     }
683                 }
684             }
685 
686             // Wrong list or interference
687             return sremove(key, hash);
688         }
689     }
690 
691     /***
692      * Continuation of remove(), called only when synch lock is held and
693      * interference has been detected.
694      */
695 
696     protected Object sremove(Object key, int hash) {
697         Entry[] tab = table;
698         int index = hash & (tab.length - 1);
699         Entry first = tab[index];
700 
701         for (Entry e = first; e != null; e = e.next) {
702             if (e.hash == hash && eq(key, e.key)) {
703                 Object oldValue = e.value;
704                 e.value = null;
705                 count--;
706                 Entry head = e.next;
707                 for (Entry p = first; p != e; p = p.next)
708                     head = new Entry(p.hash, p.key, p.value, head);
709 
710                 tab[index] = head;
711                 recordModification(head);
712                 return oldValue;
713             }
714         }
715         return null;
716     }
717 
718     /***
719      * Returns <tt>true</tt> if this map maps one or more keys to the
720      * specified value. Note: This method requires a full internal traversal of
721      * the hash table, and so is much slower than method <tt>containsKey</tt>.
722      * 
723      * @param value
724      *            value whose presence in this map is to be tested.
725      * @return <tt>true</tt> if this map maps one or more keys to the
726      *         specified value.
727      * @exception NullPointerException
728      *                if the value is <code>null</code>.
729      */
730 
731     public boolean containsValue(Object value) {
732         if (value == null)
733             throw new NullPointerException();
734 
735         Entry tab[] = getTableForReading();
736 
737         for (int i = 0; i < tab.length; ++i) {
738             for (Entry e = tab[i]; e != null; e = e.next)
739                 if (value.equals(e.value))
740                     return true;
741         }
742 
743         return false;
744     }
745 
746     /***
747      * Tests if some key maps into the specified value in this table. This
748      * operation is more expensive than the <code>containsKey</code> method.
749      * <p>
750      * 
751      * Note that this method is identical in functionality to containsValue,
752      * (which is part of the Map interface in the collections framework).
753      * 
754      * @param value
755      *            a value to search for.
756      * @return <code>true</code> if and only if some key maps to the
757      *         <code>value</code> argument in this table as determined by the
758      *         <tt>equals</tt> method; <code>false</code> otherwise.
759      * @exception NullPointerException
760      *                if the value is <code>null</code>.
761      * @see #containsKey(Object)
762      * @see #containsValue(Object)
763      * @see Map
764      */
765 
766     public boolean contains(Object value) {
767         return containsValue(value);
768     }
769 
770     /***
771      * Copies all of the mappings from the specified map to this one.
772      * 
773      * These mappings replace any mappings that this map had for any of the keys
774      * currently in the specified Map.
775      * 
776      * @param t
777      *            Mappings to be stored in this map.
778      */
779 
780     public synchronized void putAll(Map t) {
781         int n = t.size();
782         if (n == 0)
783             return;
784 
785         // Expand enough to hold at least n elements without resizing.
786         // We can only resize table by factor of two at a time.
787         // It is faster to rehash with fewer elements, so do it now.
788         while (n >= threshold)
789             rehash();
790 
791         for (Iterator it = t.entrySet().iterator(); it.hasNext();) {
792             Map.Entry entry = (Map.Entry) it.next();
793             Object key = entry.getKey();
794             Object value = entry.getValue();
795             put(key, value);
796         }
797     }
798 
799     /***
800      * Removes all mappings from this map.
801      */
802     public synchronized void clear() {
803         Entry tab[] = table;
804         for (int i = 0; i < tab.length; ++i) {
805 
806             // must invalidate all to force concurrent get's to wait and then
807             // retry
808             for (Entry e = tab[i]; e != null; e = e.next)
809                 e.value = null;
810 
811             tab[i] = null;
812         }
813         count = 0;
814         recordModification(tab);
815     }
816 
817     /***
818      * Returns a shallow copy of this <tt>ConcurrentReaderHashMap</tt>
819      * instance: the keys and values themselves are not cloned.
820      * 
821      * @return a shallow copy of this map.
822      */
823 
824     public synchronized Object clone() {
825         try {
826             ConcurrentReaderHashMap t = (ConcurrentReaderHashMap) super.clone();
827 
828             t.keySet = null;
829             t.entrySet = null;
830             t.values = null;
831 
832             Entry[] tab = table;
833             t.table = new Entry[tab.length];
834             Entry[] ttab = t.table;
835 
836             for (int i = 0; i < tab.length; ++i) {
837                 Entry first = null;
838                 for (Entry e = tab[i]; e != null; e = e.next)
839                     first = new Entry(e.hash, e.key, e.value, first);
840                 ttab[i] = first;
841             }
842 
843             return t;
844         } catch (CloneNotSupportedException e) {
845             // this shouldn't happen, since we are Cloneable
846             throw new InternalError();
847         }
848     }
849 
850     // Views
851 
852     protected transient Set keySet = null;
853 
854     protected transient Set entrySet = null;
855 
856     protected transient Collection values = null;
857 
858     /***
859      * Returns a set view of the keys contained in this map. The set is backed
860      * by the map, so changes to the map are reflected in the set, and
861      * vice-versa. The set supports element removal, which removes the
862      * corresponding mapping from this map, via the <tt>Iterator.remove</tt>,
863      * <tt>Set.remove</tt>,<tt>removeAll</tt>,<tt>retainAll</tt>, and
864      * <tt>clear</tt> operations. It does not support the <tt>add</tt> or
865      * <tt>addAll</tt> operations.
866      * 
867      * @return a set view of the keys contained in this map.
868      */
869 
870     public Set keySet() {
871         Set ks = keySet;
872         return (ks != null) ? ks : (keySet = new KeySet());
873     }
874 
875     private class KeySet extends AbstractSet {
876         public Iterator iterator() {
877             return new KeyIterator();
878         }
879 
880         public int size() {
881             return ConcurrentReaderHashMap.this.size();
882         }
883 
884         public boolean contains(Object o) {
885             return ConcurrentReaderHashMap.this.containsKey(o);
886         }
887 
888         public boolean remove(Object o) {
889             return ConcurrentReaderHashMap.this.remove(o) != null;
890         }
891 
892         public void clear() {
893             ConcurrentReaderHashMap.this.clear();
894         }
895     }
896 
897     /***
898      * Returns a collection view of the values contained in this map. The
899      * collection is backed by the map, so changes to the map are reflected in
900      * the collection, and vice-versa. The collection supports element removal,
901      * which removes the corresponding mapping from this map, via the
902      * <tt>Iterator.remove</tt>,<tt>Collection.remove</tt>,
903      * <tt>removeAll</tt>,<tt>retainAll</tt>, and <tt>clear</tt>
904      * operations. It does not support the <tt>add</tt> or <tt>addAll</tt>
905      * operations.
906      * 
907      * @return a collection view of the values contained in this map.
908      */
909 
910     public Collection values() {
911         Collection vs = values;
912         return (vs != null) ? vs : (values = new Values());
913     }
914 
915     private class Values extends AbstractCollection {
916         public Iterator iterator() {
917             return new ValueIterator();
918         }
919 
920         public int size() {
921             return ConcurrentReaderHashMap.this.size();
922         }
923 
924         public boolean contains(Object o) {
925             return ConcurrentReaderHashMap.this.containsValue(o);
926         }
927 
928         public void clear() {
929             ConcurrentReaderHashMap.this.clear();
930         }
931     }
932 
933     /***
934      * Returns a collection view of the mappings contained in this map. Each
935      * element in the returned collection is a <tt>Map.Entry</tt>. The
936      * collection is backed by the map, so changes to the map are reflected in
937      * the collection, and vice-versa. The collection supports element removal,
938      * which removes the corresponding mapping from the map, via the
939      * <tt>Iterator.remove</tt>,<tt>Collection.remove</tt>,
940      * <tt>removeAll</tt>,<tt>retainAll</tt>, and <tt>clear</tt>
941      * operations. It does not support the <tt>add</tt> or <tt>addAll</tt>
942      * operations.
943      * 
944      * @return a collection view of the mappings contained in this map.
945      */
946 
947     public Set entrySet() {
948         Set es = entrySet;
949         return (es != null) ? es : (entrySet = new EntrySet());
950     }
951 
952     private class EntrySet extends AbstractSet {
953         public Iterator iterator() {
954             return new HashIterator();
955         }
956 
957         public boolean contains(Object o) {
958             if (!(o instanceof Map.Entry))
959                 return false;
960             Map.Entry entry = (Map.Entry) o;
961             Object v = ConcurrentReaderHashMap.this.get(entry.getKey());
962             return v != null && v.equals(entry.getValue());
963         }
964 
965         public boolean remove(Object o) {
966             if (!(o instanceof Map.Entry))
967                 return false;
968             return ConcurrentReaderHashMap.this
969                     .findAndRemoveEntry((Map.Entry) o);
970         }
971 
972         public int size() {
973             return ConcurrentReaderHashMap.this.size();
974         }
975 
976         public void clear() {
977             ConcurrentReaderHashMap.this.clear();
978         }
979     }
980 
981     /***
982      * Helper method for entrySet.remove
983      */
984     protected synchronized boolean findAndRemoveEntry(Map.Entry entry) {
985         Object key = entry.getKey();
986         Object v = get(key);
987         if (v != null && v.equals(entry.getValue())) {
988             remove(key);
989             return true;
990         } else
991             return false;
992     }
993 
994     /***
995      * Returns an enumeration of the keys in this table.
996      * 
997      * @return an enumeration of the keys in this table.
998      * @see Enumeration
999      * @see #elements()
1000      * @see #keySet()
1001      * @see Map
1002      */
1003     public Enumeration keys() {
1004         return new KeyIterator();
1005     }
1006 
1007     /***
1008      * Returns an enumeration of the values in this table. Use the Enumeration
1009      * methods on the returned object to fetch the elements sequentially.
1010      * 
1011      * @return an enumeration of the values in this table.
1012      * @see java.util.Enumeration
1013      * @see #keys()
1014      * @see #values()
1015      * @see Map
1016      */
1017 
1018     public Enumeration elements() {
1019         return new ValueIterator();
1020     }
1021 
1022     /***
1023      * ConcurrentReaderHashMap collision list entry.
1024      */
1025 
1026     protected static class Entry implements Map.Entry {
1027 
1028         /*
1029          * The use of volatile for value field ensures that we can detect status
1030          * changes without synchronization. The other fields are never changed,
1031          * and are marked as final.
1032          */
1033 
1034         protected final int hash;
1035 
1036         protected final Object key;
1037 
1038         protected final Entry next;
1039 
1040         protected volatile Object value;
1041 
1042         Entry(int hash, Object key, Object value, Entry next) {
1043             this.hash = hash;
1044             this.key = key;
1045             this.next = next;
1046             this.value = value;
1047         }
1048 
1049         // Map.Entry Ops
1050 
1051         public Object getKey() {
1052             return key;
1053         }
1054 
1055         /***
1056          * Get the value. Note: In an entrySet or entrySet.iterator, unless the
1057          * set or iterator is used under synchronization of the table as a whole
1058          * (or you can otherwise guarantee lack of concurrent modification),
1059          * <tt>getValue</tt> <em>might</em> return null, reflecting the fact
1060          * that the entry has been concurrently removed. However, there are no
1061          * assurances that concurrent removals will be reflected using this
1062          * method.
1063          * 
1064          * @return the current value, or null if the entry has been detectably
1065          *         removed.
1066          */
1067         public Object getValue() {
1068             return value;
1069         }
1070 
1071         /***
1072          * Set the value of this entry. Note: In an entrySet or
1073          * entrySet.iterator), unless the set or iterator is used under
1074          * synchronization of the table as a whole (or you can otherwise
1075          * guarantee lack of concurrent modification), <tt>setValue</tt> is
1076          * not strictly guaranteed to actually replace the value field obtained
1077          * via the <tt>get</tt> operation of the underlying hash table in
1078          * multithreaded applications. If iterator-wide synchronization is not
1079          * used, and any other concurrent <tt>put</tt> or <tt>remove</tt>
1080          * operations occur, sometimes even to <em>other</em> entries, then
1081          * this change is not guaranteed to be reflected in the hash table. (It
1082          * might, or it might not. There are no assurances either way.)
1083          * 
1084          * @param value
1085          *            the new value.
1086          * @return the previous value, or null if entry has been detectably
1087          *         removed.
1088          * @exception NullPointerException
1089          *                if the value is <code>null</code>.
1090          * 
1091          */
1092 
1093         public Object setValue(Object value) {
1094             if (value == null)
1095                 throw new NullPointerException();
1096             Object oldValue = this.value;
1097             this.value = value;
1098             return oldValue;
1099         }
1100 
1101         public boolean equals(Object o) {
1102             if (!(o instanceof Map.Entry))
1103                 return false;
1104             Map.Entry e = (Map.Entry) o;
1105             return (key.equals(e.getKey()) && value.equals(e.getValue()));
1106         }
1107 
1108         public int hashCode() {
1109             return key.hashCode() ^ value.hashCode();
1110         }
1111 
1112         public String toString() {
1113             return key + "=" + value;
1114         }
1115 
1116     }
1117 
1118     protected class HashIterator implements Iterator, Enumeration {
1119         protected final Entry[] tab; // snapshot of table
1120 
1121         protected int index; // current slot
1122 
1123         protected Entry entry = null; // current node of slot
1124 
1125         protected Object currentKey; // key for current node
1126 
1127         protected Object currentValue; // value for current node
1128 
1129         protected Entry lastReturned = null; // last node returned by next
1130 
1131         protected HashIterator() {
1132             tab = ConcurrentReaderHashMap.this.getTableForReading();
1133             index = tab.length - 1;
1134         }
1135 
1136         public boolean hasMoreElements() {
1137             return hasNext();
1138         }
1139 
1140         public Object nextElement() {
1141             return next();
1142         }
1143 
1144         public boolean hasNext() {
1145 
1146             /*
1147              * currentkey and currentValue are set here to ensure that next()
1148              * returns normally if hasNext() returns true. This avoids surprises
1149              * especially when final element is removed during traversal --
1150              * instead, we just ignore the removal during current traversal.
1151              */
1152 
1153             for (;;) {
1154                 if (entry != null) {
1155                     Object v = entry.value;
1156                     if (v != null) {
1157                         currentKey = entry.key;
1158                         currentValue = v;
1159                         return true;
1160                     } else
1161                         entry = entry.next;
1162                 }
1163 
1164                 while (entry == null && index >= 0)
1165                     entry = tab[index--];
1166 
1167                 if (entry == null) {
1168                     currentKey = currentValue = null;
1169                     return false;
1170                 }
1171             }
1172         }
1173 
1174         protected Object returnValueOfNext() {
1175             return entry;
1176         }
1177 
1178         public Object next() {
1179             if (currentKey == null && !hasNext())
1180                 throw new NoSuchElementException();
1181 
1182             Object result = returnValueOfNext();
1183             lastReturned = entry;
1184             currentKey = currentValue = null;
1185             entry = entry.next;
1186             return result;
1187         }
1188 
1189         public void remove() {
1190             if (lastReturned == null)
1191                 throw new IllegalStateException();
1192             ConcurrentReaderHashMap.this.remove(lastReturned.key);
1193             lastReturned = null;
1194         }
1195 
1196     }
1197 
1198     protected class KeyIterator extends HashIterator {
1199         protected Object returnValueOfNext() {
1200             return currentKey;
1201         }
1202     }
1203 
1204     protected class ValueIterator extends HashIterator {
1205         protected Object returnValueOfNext() {
1206             return currentValue;
1207         }
1208     }
1209 
1210     /***
1211      * Save the state of the <tt>ConcurrentReaderHashMap</tt> instance to a
1212      * stream (i.e., serialize it).
1213      * 
1214      * @serialData The <i>capacity </i> of the ConcurrentReaderHashMap (the
1215      *             length of the bucket array) is emitted (int), followed by the
1216      *             <i>size </i> of the ConcurrentReaderHashMap (the number of
1217      *             key-value mappings), followed by the key (Object) and value
1218      *             (Object) for each key-value mapping represented by the
1219      *             ConcurrentReaderHashMap The key-value mappings are emitted in
1220      *             no particular order.
1221      */
1222 
1223     private synchronized void writeObject(java.io.ObjectOutputStream s)
1224             throws IOException {
1225         // Write out the threshold, loadfactor, and any hidden stuff
1226         s.defaultWriteObject();
1227 
1228         // Write out number of buckets
1229         s.writeInt(table.length);
1230 
1231         // Write out size (number of Mappings)
1232         s.writeInt(count);
1233 
1234         // Write out keys and values (alternating)
1235         for (int index = table.length - 1; index >= 0; index--) {
1236             Entry entry = table[index];
1237 
1238             while (entry != null) {
1239                 s.writeObject(entry.key);
1240                 s.writeObject(entry.value);
1241                 entry = entry.next;
1242             }
1243         }
1244     }
1245 
1246     /***
1247      * Reconstitute the <tt>ConcurrentReaderHashMap</tt> instance from a
1248      * stream (i.e., deserialize it).
1249      */
1250     private synchronized void readObject(java.io.ObjectInputStream s)
1251             throws IOException, ClassNotFoundException {
1252         // Read in the threshold, loadfactor, and any hidden stuff
1253         s.defaultReadObject();
1254 
1255         // Read in number of buckets and allocate the bucket array;
1256         int numBuckets = s.readInt();
1257         table = new Entry[numBuckets];
1258 
1259         // Read in size (number of Mappings)
1260         int size = s.readInt();
1261 
1262         // Read the keys and values, and put the mappings in the table
1263         for (int i = 0; i < size; i++) {
1264             Object key = s.readObject();
1265             Object value = s.readObject();
1266             put(key, value);
1267         }
1268     }
1269 
1270     /***
1271      * Return the number of slots in this table
1272      */
1273 
1274     public synchronized int capacity() {
1275         return table.length;
1276     }
1277 
1278     /***
1279      * Return the load factor
1280      */
1281     public float loadFactor() {
1282         return loadFactor;
1283     }
1284 }