Expands the table if possible.
()
| 2936 | * Expands the table if possible. |
| 2937 | */ |
| 2938 | @GuardedBy("this") |
| 2939 | void expand() { |
| 2940 | AtomicReferenceArray<ReferenceEntry<K, V>> oldTable = table; |
| 2941 | int oldCapacity = oldTable.length(); |
| 2942 | if (oldCapacity >= MAXIMUM_CAPACITY) { |
| 2943 | return; |
| 2944 | } |
| 2945 | |
| 2946 | /* |
| 2947 | * Reclassify nodes in each list to new Map. Because we are using power-of-two expansion, the |
| 2948 | * elements from each bin must either stay at same index, or move with a power of two offset. |
| 2949 | * We eliminate unnecessary node creation by catching cases where old nodes can be reused |
| 2950 | * because their next fields won't change. Statistically, at the default threshold, only about |
| 2951 | * one-sixth of them need cloning when a table doubles. The nodes they replace will be garbage |
| 2952 | * collectable as soon as they are no longer referenced by any reader thread that may be in |
| 2953 | * the midst of traversing table right now. |
| 2954 | */ |
| 2955 | |
| 2956 | int newCount = count; |
| 2957 | AtomicReferenceArray<ReferenceEntry<K, V>> newTable = newEntryArray(oldCapacity << 1); |
| 2958 | threshold = newTable.length() * 3 / 4; |
| 2959 | int newMask = newTable.length() - 1; |
| 2960 | for (int oldIndex = 0; oldIndex < oldCapacity; ++oldIndex) { |
| 2961 | // We need to guarantee that any existing reads of old Map can |
| 2962 | // proceed. So we cannot yet null out each bin. |
| 2963 | ReferenceEntry<K, V> head = oldTable.get(oldIndex); |
| 2964 | |
| 2965 | if (head != null) { |
| 2966 | ReferenceEntry<K, V> next = head.getNext(); |
| 2967 | int headIndex = head.getHash() & newMask; |
| 2968 | |
| 2969 | // Single node on list |
| 2970 | if (next == null) { |
| 2971 | newTable.set(headIndex, head); |
| 2972 | } else { |
| 2973 | // Reuse the consecutive sequence of nodes with the same target |
| 2974 | // index from the end of the list. tail points to the first |
| 2975 | // entry in the reusable list. |
| 2976 | ReferenceEntry<K, V> tail = head; |
| 2977 | int tailIndex = headIndex; |
| 2978 | for (ReferenceEntry<K, V> e = next; e != null; e = e.getNext()) { |
| 2979 | int newIndex = e.getHash() & newMask; |
| 2980 | if (newIndex != tailIndex) { |
| 2981 | // The index changed. We'll need to copy the previous entry. |
| 2982 | tailIndex = newIndex; |
| 2983 | tail = e; |
| 2984 | } |
| 2985 | } |
| 2986 | newTable.set(tailIndex, tail); |
| 2987 | |
| 2988 | // Clone nodes leading up to the tail. |
| 2989 | for (ReferenceEntry<K, V> e = head; e != tail; e = e.getNext()) { |
| 2990 | int newIndex = e.getHash() & newMask; |
| 2991 | ReferenceEntry<K, V> newNext = newTable.get(newIndex); |
| 2992 | ReferenceEntry<K, V> newFirst = copyEntry(e, newNext); |
| 2993 | if (newFirst != null) { |
| 2994 | newTable.set(newIndex, newFirst); |
| 2995 | } else { |
no test coverage detected