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.109 by jsr166, Wed Apr 27 12:58:52 2011 UTC vs.
Revision 1.112 by jsr166, Fri Jun 3 02:28:05 2011 UTC

# Line 199 | Line 199 | public class ConcurrentHashMap<K, V> ext
199          static {
200              try {
201                  UNSAFE = sun.misc.Unsafe.getUnsafe();
202 <                Class k = HashEntry.class;
202 >                Class<?> k = HashEntry.class;
203                  nextOffset = UNSAFE.objectFieldOffset
204                      (k.getDeclaredField("next"));
205              } catch (Exception e) {
# Line 404 | Line 404 | public class ConcurrentHashMap<K, V> ext
404              int newCapacity = oldCapacity << 1;
405              threshold = (int)(newCapacity * loadFactor);
406              HashEntry<K,V>[] newTable =
407 <                (HashEntry<K,V>[]) new HashEntry[newCapacity];
407 >                (HashEntry<K,V>[]) new HashEntry<?,?>[newCapacity];
408              int sizeMask = newCapacity - 1;
409              for (int i = 0; i < oldCapacity ; i++) {
410                  HashEntry<K,V> e = oldTable[i];
# Line 648 | Line 648 | public class ConcurrentHashMap<K, V> ext
648              int cap = proto.table.length;
649              float lf = proto.loadFactor;
650              int threshold = (int)(cap * lf);
651 <            HashEntry<K,V>[] tab = (HashEntry<K,V>[])new HashEntry[cap];
651 >            HashEntry<K,V>[] tab = (HashEntry<K,V>[])new HashEntry<?,?>[cap];
652              if ((seg = (Segment<K,V>)UNSAFE.getObjectVolatile(ss, u))
653                  == null) { // recheck
654                  Segment<K,V> s = new Segment<K,V>(lf, threshold, tab);
# Line 729 | Line 729 | public class ConcurrentHashMap<K, V> ext
729          // create segments and segments[0]
730          Segment<K,V> s0 =
731              new Segment<K,V>(loadFactor, (int)(cap * loadFactor),
732 <                             (HashEntry<K,V>[])new HashEntry[cap]);
733 <        Segment<K,V>[] ss = (Segment<K,V>[])new Segment[ssize];
732 >                             (HashEntry<K,V>[])new HashEntry<?,?>[cap]);
733 >        Segment<K,V>[] ss = (Segment<K,V>[])new Segment<?,?>[ssize];
734          UNSAFE.putOrderedObject(ss, SBASE, s0); // ordered write of segments[0]
735          this.segments = ss;
736      }
# Line 840 | Line 840 | public class ConcurrentHashMap<K, V> ext
840          // Try a few times to get accurate count. On failure due to
841          // continuous async changes in table, resort to locking.
842          final Segment<K,V>[] segments = this.segments;
843 <        int size;
844 <        boolean overflow; // true if size overflows 32 bits
845 <        long sum;         // sum of modCounts
846 <        long last = 0L;   // previous sum
847 <        int retries = -1; // first iteration isn't retry
848 <        try {
849 <            for (;;) {
850 <                if (retries++ == RETRIES_BEFORE_LOCK) {
851 <                    for (int j = 0; j < segments.length; ++j)
852 <                        ensureSegment(j).lock(); // force creation
853 <                }
854 <                sum = 0L;
855 <                size = 0;
856 <                overflow = false;
857 <                for (int j = 0; j < segments.length; ++j) {
858 <                    Segment<K,V> seg = segmentAt(segments, j);
859 <                    if (seg != null) {
860 <                        sum += seg.modCount;
861 <                        int c = seg.count;
862 <                        if (c < 0 || (size += c) < 0)
863 <                            overflow = true;
864 <                    }
843 >        final int segmentCount = segments.length;
844 >
845 >        long previousSum = 0L;
846 >        for (int retries = -1; retries < RETRIES_BEFORE_LOCK; retries++) {
847 >            long sum = 0L;    // sum of modCounts
848 >            long size = 0L;
849 >            for (int i = 0; i < segmentCount; i++) {
850 >                Segment<K,V> segment = segmentAt(segments, i);
851 >                if (segment != null) {
852 >                    sum += segment.modCount;
853 >                    size += segment.count;
854                  }
866                if (sum == last)
867                    break;
868                last = sum;
869            }
870        } finally {
871            if (retries > RETRIES_BEFORE_LOCK) {
872                for (int j = 0; j < segments.length; ++j)
873                    segmentAt(segments, j).unlock();
855              }
856 +            if (sum == previousSum)
857 +                return ((size >>> 31) == 0) ? (int) size : Integer.MAX_VALUE;
858 +            previousSum = sum;
859          }
860 <        return overflow ? Integer.MAX_VALUE : size;
860 >
861 >        long size = 0L;
862 >        for (int i = 0; i < segmentCount; i++) {
863 >            Segment<K,V> segment = ensureSegment(i);
864 >            segment.lock();
865 >            size += segment.count;
866 >        }
867 >        for (int i = 0; i < segmentCount; i++)
868 >            segments[i].unlock();
869 >        return ((size >>> 31) == 0) ? (int) size : Integer.MAX_VALUE;
870      }
871  
872      /**
# Line 949 | Line 942 | public class ConcurrentHashMap<K, V> ext
942          if (value == null)
943              throw new NullPointerException();
944          final Segment<K,V>[] segments = this.segments;
945 <        boolean found = false;
946 <        long last = 0L;   // previous sum
954 <        int retries = -1;
945 >        long previousSum = 0L;
946 >        int lockCount = 0;
947          try {
948 <            outer: for (;;) {
949 <                if (retries++ == RETRIES_BEFORE_LOCK) {
950 <                    for (int j = 0; j < segments.length; ++j)
951 <                        ensureSegment(j).lock(); // force creation
952 <                }
953 <                long sum = 0L;
954 <                for (int j = 0; j < segments.length; ++j) {
955 <                    HashEntry<K,V>[] tab;
956 <                    Segment<K,V> seg = segmentAt(segments, j);
957 <                    if (seg != null && (tab = seg.table) != null) {
948 >            for (int retries = -1; ; retries++) {
949 >                long sum = 0L;    // sum of modCounts
950 >                for (int j = 0; j < segments.length; j++) {
951 >                    Segment<K,V> segment;
952 >                    if (retries == RETRIES_BEFORE_LOCK) {
953 >                        segment = ensureSegment(j);
954 >                        segment.lock();
955 >                        lockCount++;
956 >                    } else {
957 >                        segment = segmentAt(segments, j);
958 >                        if (segment == null)
959 >                            continue;
960 >                    }
961 >                    HashEntry<K,V>[] tab = segment.table;
962 >                    if (tab != null) {
963                          for (int i = 0 ; i < tab.length; i++) {
964                              HashEntry<K,V> e;
965                              for (e = entryAt(tab, i); e != null; e = e.next) {
966                                  V v = e.value;
967 <                                if (v != null && value.equals(v)) {
968 <                                    found = true;
972 <                                    break outer;
973 <                                }
967 >                                if (v != null && value.equals(v))
968 >                                    return true;
969                              }
970                          }
971 <                        sum += seg.modCount;
971 >                        sum += segment.modCount;
972                      }
973                  }
974 <                if (retries > 0 && sum == last)
975 <                    break;
976 <                last = sum;
974 >                if ((retries >= 0 && sum == previousSum) || lockCount > 0)
975 >                    return false;
976 >                previousSum = sum;
977              }
978          } finally {
979 <            if (retries > RETRIES_BEFORE_LOCK) {
980 <                for (int j = 0; j < segments.length; ++j)
986 <                    segmentAt(segments, j).unlock();
987 <            }
979 >            for (int j = 0; j < lockCount; j++)
980 >                segments[j].unlock();
981          }
989        return found;
982      }
983  
984      /**
# Line 996 | Line 988 | public class ConcurrentHashMap<K, V> ext
988       * full compatibility with class {@link java.util.Hashtable},
989       * which supported this method prior to introduction of the
990       * Java Collections framework.
991 <
991 >     *
992       * @param  value a value to search for
993       * @return <tt>true</tt> if and only if some key maps to the
994       *         <tt>value</tt> argument in this table as
# Line 1449 | Line 1441 | public class ConcurrentHashMap<K, V> ext
1441              Segment<K,V> seg = segments[k];
1442              if (seg != null) {
1443                  seg.threshold = (int)(cap * seg.loadFactor);
1444 <                seg.table = (HashEntry<K,V>[]) new HashEntry[cap];
1444 >                seg.table = (HashEntry<K,V>[]) new HashEntry<?,?>[cap];
1445              }
1446          }
1447  
# Line 1474 | Line 1466 | public class ConcurrentHashMap<K, V> ext
1466          int ss, ts;
1467          try {
1468              UNSAFE = sun.misc.Unsafe.getUnsafe();
1469 <            Class tc = HashEntry[].class;
1470 <            Class sc = Segment[].class;
1469 >            Class<?> tc = HashEntry[].class;
1470 >            Class<?> sc = Segment[].class;
1471              TBASE = UNSAFE.arrayBaseOffset(tc);
1472              SBASE = UNSAFE.arrayBaseOffset(sc);
1473              ts = UNSAFE.arrayIndexScale(tc);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines