766 |
|
int cycles = 0; |
767 |
|
|
768 |
|
/** Linked list of weak iterator references */ |
769 |
< |
private Node head = null; |
769 |
> |
private Node head; |
770 |
|
|
771 |
|
/** Used to expunge stale iterators */ |
772 |
|
private Node sweeper = null; |
774 |
|
private static final int SHORT_SWEEP_PROBES = 4; |
775 |
|
private static final int LONG_SWEEP_PROBES = 16; |
776 |
|
|
777 |
+ |
Itrs(Itr initial) { |
778 |
+ |
register(initial); |
779 |
+ |
} |
780 |
+ |
|
781 |
|
/** |
782 |
|
* Sweeps itrs, looking for and expunging stale iterators. |
783 |
|
* If at least one was found, tries harder to find more. |
787 |
|
*/ |
788 |
|
void doSomeSweeping(boolean tryHarder) { |
789 |
|
assert lock.getHoldCount() == 1; |
790 |
+ |
assert head != null; |
791 |
|
int probes = tryHarder ? LONG_SWEEP_PROBES : SHORT_SWEEP_PROBES; |
792 |
|
Node o, p; |
793 |
|
final Node sweeper = this.sweeper; |
794 |
+ |
boolean passedGo; // to limit search to one full sweep |
795 |
|
|
796 |
< |
if (sweeper != null && sweeper.get() != null) { |
791 |
< |
o = sweeper; |
792 |
< |
p = o.next; |
793 |
< |
} else { |
796 |
> |
if (sweeper == null) { |
797 |
|
o = null; |
798 |
|
p = head; |
799 |
+ |
passedGo = true; |
800 |
+ |
} else { |
801 |
+ |
o = sweeper; |
802 |
+ |
p = o.next; |
803 |
+ |
passedGo = false; |
804 |
|
} |
805 |
|
|
806 |
< |
for (; p != null && probes > 0; probes--) { |
806 |
> |
for (; probes > 0; probes--) { |
807 |
> |
if (p == null) { |
808 |
> |
if (passedGo) |
809 |
> |
break; |
810 |
> |
o = null; |
811 |
> |
p = head; |
812 |
> |
passedGo = true; |
813 |
> |
} |
814 |
|
final Itr it = p.get(); |
815 |
|
final Node next = p.next; |
816 |
|
if (it == null || it.isDetached()) { |
819 |
|
// unlink p |
820 |
|
p.clear(); |
821 |
|
p.next = null; |
822 |
< |
if (o == null) |
822 |
> |
if (o == null) { |
823 |
|
head = next; |
824 |
+ |
if (next == null) { |
825 |
+ |
// We've run out of iterators to track; retire |
826 |
+ |
itrs = null; |
827 |
+ |
return; |
828 |
+ |
} |
829 |
+ |
} |
830 |
|
else |
831 |
|
o.next = next; |
832 |
|
} else { |
834 |
|
} |
835 |
|
p = next; |
836 |
|
} |
816 |
– |
if (head == null) // no more iterators to track |
817 |
– |
itrs = null; |
837 |
|
|
838 |
|
this.sweeper = (p == null) ? null : o; |
839 |
|
} |
877 |
|
|
878 |
|
/** |
879 |
|
* Called whenever an interior remove (not at takeIndex) occured. |
880 |
+ |
* |
881 |
+ |
* Notifies all iterators, and expunges any that are now stale. |
882 |
|
*/ |
883 |
|
void removedAt(int removedIndex) { |
884 |
|
for (Node o = null, p = head; p != null;) { |
1002 |
|
nextItem = itemAt(nextIndex = takeIndex); |
1003 |
|
cursor = incCursor(takeIndex); |
1004 |
|
if (itrs == null) { |
1005 |
< |
itrs = new Itrs(); |
985 |
< |
itrs.register(this); |
1005 |
> |
itrs = new Itrs(this); |
1006 |
|
} else { |
1007 |
|
itrs.register(this); // in this order |
1008 |
|
itrs.doSomeSweeping(false); |