56
56
*
57
57
* @author Phillip Webb
58
58
* @author Juergen Hoeller
59
+ * @author Brian Clozel
59
60
* @since 3.2
60
61
* @param <K> the key type
61
62
* @param <V> the value type
@@ -568,7 +569,7 @@ public void clear() {
568
569
* references that have been garbage collected.
569
570
* @param allowResize if resizing is permitted
570
571
*/
571
- protected final void restructureIfNecessary (boolean allowResize ) {
572
+ void restructureIfNecessary (boolean allowResize ) {
572
573
int currCount = this .count .get ();
573
574
boolean needsResize = allowResize && (currCount > 0 && currCount >= this .resizeThreshold );
574
575
Reference <K , V > ref = this .referenceManager .pollForPurge ();
@@ -581,7 +582,7 @@ private void restructure(boolean allowResize, @Nullable Reference<K, V> ref) {
581
582
boolean needsResize ;
582
583
lock ();
583
584
try {
584
- int countAfterRestructure = this .count .get ();
585
+ int expectedCount = this .count .get ();
585
586
Set <Reference <K , V >> toPurge = Collections .emptySet ();
586
587
if (ref != null ) {
587
588
toPurge = new HashSet <>();
@@ -590,11 +591,11 @@ private void restructure(boolean allowResize, @Nullable Reference<K, V> ref) {
590
591
ref = this .referenceManager .pollForPurge ();
591
592
}
592
593
}
593
- countAfterRestructure -= toPurge .size ();
594
+ expectedCount -= toPurge .size ();
594
595
595
- // Recalculate taking into account count inside lock and items that
596
- // will be purged
597
- needsResize = (countAfterRestructure > 0 && countAfterRestructure >= this .resizeThreshold );
596
+ // Estimate new count, taking into account count inside lock and items that
597
+ // will be purged.
598
+ needsResize = (expectedCount > 0 && expectedCount >= this .resizeThreshold );
598
599
boolean resizing = false ;
599
600
int restructureSize = this .references .length ;
600
601
if (allowResize && needsResize && restructureSize < MAXIMUM_SEGMENT_SIZE ) {
@@ -607,6 +608,7 @@ private void restructure(boolean allowResize, @Nullable Reference<K, V> ref) {
607
608
(resizing ? createReferenceArray (restructureSize ) : this .references );
608
609
609
610
// Restructure
611
+ int newCount = 0 ;
610
612
for (int i = 0 ; i < this .references .length ; i ++) {
611
613
ref = this .references [i ];
612
614
if (!resizing ) {
@@ -615,10 +617,13 @@ private void restructure(boolean allowResize, @Nullable Reference<K, V> ref) {
615
617
while (ref != null ) {
616
618
if (!toPurge .contains (ref )) {
617
619
Entry <K , V > entry = ref .get ();
620
+ // Also filter out null references that are now null
621
+ // they should be polled the queue in a later restructure call.
618
622
if (entry != null ) {
619
623
int index = getIndex (ref .getHash (), restructured );
620
624
restructured [index ] = this .referenceManager .createReference (
621
625
entry , ref .getHash (), restructured [index ]);
626
+ newCount ++;
622
627
}
623
628
}
624
629
ref = ref .getNext ();
@@ -630,7 +635,7 @@ private void restructure(boolean allowResize, @Nullable Reference<K, V> ref) {
630
635
this .references = restructured ;
631
636
this .resizeThreshold = (int ) (this .references .length * getLoadFactor ());
632
637
}
633
- this .count .set (Math .max (countAfterRestructure , 0 ));
638
+ this .count .set (Math .max (newCount , 0 ));
634
639
}
635
640
finally {
636
641
unlock ();
@@ -667,14 +672,14 @@ private int getIndex(int hash, Reference<K, V>[] references) {
667
672
/**
668
673
* Return the size of the current references array.
669
674
*/
670
- public final int getSize () {
675
+ public int getSize () {
671
676
return this .references .length ;
672
677
}
673
678
674
679
/**
675
680
* Return the total number of references in this segment.
676
681
*/
677
- public final int getCount () {
682
+ public int getCount () {
678
683
return this .count .get ();
679
684
}
680
685
}
0 commit comments