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.104 by dl, Fri Apr 15 23:07:20 2011 UTC vs.
Revision 1.105 by dl, Wed Apr 20 15:36:08 2011 UTC

# Line 210 | Line 210 | public class ConcurrentHashMap<K, V> ext
210  
211      /**
212       * Gets the ith element of given table (if nonnull) with volatile
213 <     * read semantics.
213 >     * read semantics. Note: This is manually integrated into a few
214 >     * performance-sensitive methods to reduce call overhead.
215       */
216      @SuppressWarnings("unchecked")
217      static final <K,V> HashEntry<K,V> entryAt(HashEntry<K,V>[] tab, int i) {
# Line 360 | Line 361 | public class ConcurrentHashMap<K, V> ext
361                          else
362                              node = new HashEntry<K,V>(hash, key, value, first);
363                          int c = count + 1;
364 <                        if (c > threshold && first != null &&
364 <                            tab.length < MAXIMUM_CAPACITY)
364 >                        if (c > threshold && tab.length < MAXIMUM_CAPACITY)
365                              rehash(node);
366                          else
367                              setEntryAt(tab, index, node);
# Line 618 | Line 618 | public class ConcurrentHashMap<K, V> ext
618  
619      /**
620       * Gets the jth element of given segment array (if nonnull) with
621 <     * volatile element access semantics via Unsafe.
621 >     * volatile element access semantics via Unsafe. (The null check
622 >     * can trigger harmlessly only during deserialization.) Note:
623 >     * because each element of segments array is set only once (using
624 >     * fully ordered writes), some performance-sensitive methods rely
625 >     * on this method only as a recheck upon null reads.
626       */
627      @SuppressWarnings("unchecked")
628      static final <K,V> Segment<K,V> segmentAt(Segment<K,V>[] ss, int j) {
# Line 884 | Line 888 | public class ConcurrentHashMap<K, V> ext
888       * @throws NullPointerException if the specified key is null
889       */
890      public V get(Object key) {
891 <        int hash = hash(key.hashCode());
892 <        for (HashEntry<K,V> e = entryForHash(segmentForHash(hash), hash);
893 <             e != null; e = e.next) {
894 <            K k;
895 <            if ((k = e.key) == key || (e.hash == hash && key.equals(k)))
896 <                return e.value;
891 >        Segment<K,V> s; // manually integrate access methods to reduce overhead
892 >        HashEntry<K,V>[] tab;
893 >        int h = hash(key.hashCode());
894 >        long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE;
895 >        if ((s = (Segment<K,V>)UNSAFE.getObjectVolatile(segments, u)) != null &&
896 >            (tab = s.table) != null) {
897 >            for (HashEntry<K,V> e = (HashEntry<K,V>) UNSAFE.getObjectVolatile
898 >                     (tab, ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE);
899 >                 e != null; e = e.next) {
900 >                K k;
901 >                if ((k = e.key) == key || (e.hash == h && key.equals(k)))
902 >                    return e.value;
903 >            }
904          }
905          return null;
906      }
# Line 903 | Line 914 | public class ConcurrentHashMap<K, V> ext
914       *         <tt>equals</tt> method; <tt>false</tt> otherwise.
915       * @throws NullPointerException if the specified key is null
916       */
917 +    @SuppressWarnings("unchecked")
918      public boolean containsKey(Object key) {
919 <        int hash = hash(key.hashCode());
920 <        for (HashEntry<K,V> e = entryForHash(segmentForHash(hash), hash);
921 <             e != null; e = e.next) {
922 <            K k;
923 <            if ((k = e.key) == key || (e.hash == hash && key.equals(k)))
924 <                return true;
919 >        Segment<K,V> s; // same as get() except no need for volatile value read
920 >        HashEntry<K,V>[] tab;
921 >        int h = hash(key.hashCode());
922 >        long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE;
923 >        if ((s = (Segment<K,V>)UNSAFE.getObjectVolatile(segments, u)) != null &&
924 >            (tab = s.table) != null) {
925 >            for (HashEntry<K,V> e = (HashEntry<K,V>) UNSAFE.getObjectVolatile
926 >                     (tab, ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE);
927 >                 e != null; e = e.next) {
928 >                K k;
929 >                if ((k = e.key) == key || (e.hash == h && key.equals(k)))
930 >                    return true;
931 >            }
932          }
933          return false;
934      }
# Line 1003 | Line 1022 | public class ConcurrentHashMap<K, V> ext
1022       *         <tt>null</tt> if there was no mapping for <tt>key</tt>
1023       * @throws NullPointerException if the specified key or value is null
1024       */
1025 +    @SuppressWarnings("unchecked")
1026      public V put(K key, V value) {
1027 +        Segment<K,V> s;
1028          if (value == null)
1029              throw new NullPointerException();
1030          int hash = hash(key.hashCode());
1031          int j = (hash >>> segmentShift) & segmentMask;
1032 <        Segment<K,V> s = segmentAt(segments, j);
1033 <        if (s == null)
1032 >        if ((s = (Segment<K,V>)UNSAFE.getObject          // nonvolatile; recheck
1033 >             (segments, (j << SSHIFT) + SBASE)) == null) //  in ensureSegment
1034              s = ensureSegment(j);
1035          return s.put(key, hash, value, false);
1036      }
# Line 1021 | Line 1042 | public class ConcurrentHashMap<K, V> ext
1042       *         or <tt>null</tt> if there was no mapping for the key
1043       * @throws NullPointerException if the specified key or value is null
1044       */
1045 +    @SuppressWarnings("unchecked")
1046      public V putIfAbsent(K key, V value) {
1047 +        Segment<K,V> s;
1048          if (value == null)
1049              throw new NullPointerException();
1050          int hash = hash(key.hashCode());
1051          int j = (hash >>> segmentShift) & segmentMask;
1052 <        Segment<K,V> s = segmentAt(segments, j);
1053 <        if (s == null)
1052 >        if ((s = (Segment<K,V>)UNSAFE.getObject
1053 >             (segments, (j << SSHIFT) + SBASE)) == null)
1054              s = ensureSegment(j);
1055          return s.put(key, hash, value, true);
1056      }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines