sclass TestPhantomCleanUp {
settable bool withGC;
settable double maxWait = 60.0; // how many seconds
gettable bool referenceWasCleared;
gettable Duration delayBeforeClearance;
// The object to be referenced & cleared by the GC.
// Don't keep any references to it, of course!
swappable O createReferent() {
ret new S("copy of a string");
}
run {
temp new RunnablesReferenceQueue queue;
class MyPhantomRef extends PhantomReference is Runnable {
new Flag flag;
*(A a, RunnablesReferenceQueue queue) {
super(a, queue!);
}
run {
printWithMS("Behold the phantom!");
flag.raise();
}
}
var ref = new MyPhantomRef(createReferent(), queue);
printWithMS("Made the object.");
if (withGC) {
print("GC.");
timedGC();
}
long time = sysNow();
printWithMS("Now waiting...");
if (ref.flag.waitUntilUp(toMS_int(maxWait))) {
delayBeforeClearance = msToDuration(sysNow()-time);
referenceWasCleared = true;
printWithMS("Cool! Reference was cleared after "
+ renderElapsedSecondsPleasantly(delayBeforeClearance)
+ " (" + withOrWithout(withGC) + " GC)");
} else
printWithMS("Ouch. Reference not cleared even after " + maxWait + " s");
}
svoid allTests {
testSmallObject();
testHumungousObject();
}
svoid testSmallObject {
for (gc : falseTrue()) {
printAfterNL("Small object test!");
new TestPhantomCleanUp().withGC(gc).run();
}
}
svoid testHumungousObject {
for (gc : falseTrue()) {
printAfterNL("Humungous object test!");
var tpcu = new TestPhantomCleanUp().withGC(gc);
// pretty likely to be humungous
// Def. humungous: an array bigger than (G1 region size/2)
// Check "jinfo -flags $pid" to see the region size
tpcu.createReferent = -> new byte[8*oneMegabyte_int()];
tpcu.run();
}
}
}