ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentHashMap.java
(Generate patch)

Comparing jsr166/src/main/java/util/concurrent/ConcurrentHashMap.java (file contents):
Revision 1.45 by dl, Sat Apr 10 14:21:45 2004 UTC vs.
Revision 1.46 by dl, Tue Apr 13 13:33:52 2004 UTC

# Line 114 | Line 114 | public class ConcurrentHashMap<K, V> ext
114       */
115      static final int MAX_SEGMENTS = 1 << 16; // slightly conservative
116  
117 +    /**
118 +     * Number of unsynchronized retries in size and containsValue
119 +     * methods before resorting to locking. This is used to avoid
120 +     * unbounded retries if tables undergo continuous modification
121 +     * which would make it impossible to obtain an accurate result.
122 +     */
123 +    static final int RETRIES_BEFORE_LOCK = 2;
124 +
125      /* ---------------- Fields -------------- */
126  
127      /**
# Line 165 | Line 173 | public class ConcurrentHashMap<K, V> ext
173      /* ---------------- Inner Classes -------------- */
174  
175      /**
176 +     * ConcurrentHashMap list entry. Note that this is never exported
177 +     * out as a user-visible Map.Entry.
178 +     *
179 +     * Because the value field is volatile, not final, it is legal wrt
180 +     * the Java Memory Model for an unsynchronized reader to see null
181 +     * instead of initial value when read via a data race.  Although a
182 +     * reordering leading to this is not likely to ever actually
183 +     * occur, the Segment.readValueUnderLock method is used as a
184 +     * backup in case a null (pre-initialized) value is ever seen in
185 +     * an unsynchronized access method.
186 +     */
187 +    static final class HashEntry<K,V> {
188 +        final K key;
189 +        final int hash;
190 +        volatile V value;
191 +        final HashEntry<K,V> next;
192 +
193 +        HashEntry(K key, int hash, HashEntry<K,V> next, V value) {
194 +            this.key = key;
195 +            this.hash = hash;
196 +            this.next = next;
197 +            this.value = value;
198 +        }
199 +    }
200 +
201 +    /**
202       * Segments are specialized versions of hash tables.  This
203       * subclasses from ReentrantLock opportunistically, just to
204       * simplify some locking and avoid separate construction.
# Line 218 | Line 252 | public class ConcurrentHashMap<K, V> ext
252           * Number of updates that alter the size of the table. This is
253           * used during bulk-read methods to make sure they see a
254           * consistent snapshot: If modCounts change during a traversal
255 <         * of segments computing size or checking contatinsValue, then
255 >         * of segments computing size or checking containsValue, then
256           * we might have an inconsistent view of state so (usually)
257           * must retry.
258           */
# Line 517 | Line 551 | public class ConcurrentHashMap<K, V> ext
551          }
552      }
553  
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    }
554  
555  
556      /* ---------------- Public operations -------------- */
# Line 657 | Line 674 | public class ConcurrentHashMap<K, V> ext
674          long sum = 0;
675          long check = 0;
676          int[] mc = new int[segments.length];
677 <        // Try at most twice to get accurate count. On failure due to
677 >        // Try a few times to get accurate count. On failure due to
678          // continuous async changes in table, resort to locking.
679 <        for (int k = 0; k < 2; ++k) {
679 >        for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
680              check = 0;
681              sum = 0;
682              int mcsum = 0;
# Line 745 | Line 762 | public class ConcurrentHashMap<K, V> ext
762          final Segment[] segments = this.segments;
763          int[] mc = new int[segments.length];
764  
765 <        // Try at most twice without locking
766 <        for (int k = 0; k < 2; ++k) {
765 >        // Try a few times without locking
766 >        for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
767              int sum = 0;
768              int mcsum = 0;
769              for (int i = 0; i < segments.length; ++i) {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines