in ttl-core/src/main/java/com/alibaba/ttl3/internal/util/ConcurrentReferenceHashMap.java [611:668]
private void restructure(boolean allowResize, @Nullable Reference<K, V> ref) {
boolean needsResize;
lock();
try {
int countAfterRestructure = this.count.get();
Set<Reference<K, V>> toPurge = Collections.emptySet();
if (ref != null) {
toPurge = new HashSet<>();
while (ref != null) {
toPurge.add(ref);
ref = this.referenceManager.pollForPurge();
}
}
countAfterRestructure -= toPurge.size();
// Recalculate taking into account count inside lock and items that
// will be purged
needsResize = (countAfterRestructure > 0 && countAfterRestructure >= this.resizeThreshold);
boolean resizing = false;
int restructureSize = this.references.length;
if (allowResize && needsResize && restructureSize < MAXIMUM_SEGMENT_SIZE) {
restructureSize <<= 1;
resizing = true;
}
// Either create a new table or reuse the existing one
Reference<K, V>[] restructured =
(resizing ? createReferenceArray(restructureSize) : this.references);
// Restructure
for (int i = 0; i < this.references.length; i++) {
ref = this.references[i];
if (!resizing) {
restructured[i] = null;
}
while (ref != null) {
if (!toPurge.contains(ref)) {
Entry<K, V> entry = ref.get();
if (entry != null) {
int index = getIndex(ref.getHash(), restructured);
restructured[index] = this.referenceManager.createReference(
entry, ref.getHash(), restructured[index]);
}
}
ref = ref.getNext();
}
}
// Replace volatile members
if (resizing) {
this.references = restructured;
this.resizeThreshold = (int) (this.references.length * getLoadFactor());
}
this.count.set(Math.max(countAfterRestructure, 0));
} finally {
unlock();
}
}