--- /dev/null 2015-04-10 13:19:24.023596515 +0200 +++ new/src/java.base/share/classes/java/lang/ref/ReferenceHandling.java 2015-05-28 17:55:25.356603807 +0200 @@ -0,0 +1,119 @@ +package java.lang.ref; + +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinWorkerThread; +import java.util.concurrent.RecursiveAction; +import java.util.concurrent.TimeUnit; + +/** + * A holder for a ForkJoinPool and tasks executing Finalizer(s), Cleaner(s) and + * enqueuing other Reference(s). + */ +final class ReferenceHandling { + + private static final ForkJoinPool pool = createPool(); + + /** + * Starts handling of references. Called once from {@code Reference.} + * after VM has booted. + */ + static void start() { + pool.execute(new PendingChunkPoller()); + } + + /** + * Called from {@link Finalizer#runFinalization()} as part of forked secondary + * finalizer thread to run all pending finalizers. We just help the ForkJoinPool + * by waiting for it to quiesce. + */ + static void runFinalization() { + do {} while (!pool.awaitQuiescence(5, TimeUnit.SECONDS)); + } + + /** + * Creates new ForkJoinPool for handling the references. + */ + private static ForkJoinPool createPool() { + return new ForkJoinPool( + Runtime.getRuntime().availableProcessors(), + ForkJoinPool.defaultForkJoinWorkerThreadFactory, + null, + true + ); + } + + /** + * An eternal task submitted once during initialization. + * Polls for pending references and dispatches handling tasks. + */ + private static final class PendingChunkPoller extends RecursiveAction { + @Override + protected void compute() { + boolean[] morePending = new boolean[1]; + // this is an eternal task - never ends + while (true) { + Reference chunk = Reference.pollPendingChunk(true, morePending); + if (chunk != null) { + if (morePending[0]) { + // fork a handling task and return for more + new PendingChunkHandler(chunk).fork(); + } else { + // no more pending, so we can handle the chunk directly + Reference.handlePendingChunk(chunk); + } + } + } + } + } + + /** + * A task that handles one chunk of references. + */ + private static final class PendingChunkHandler extends RecursiveAction { + private Reference chunk; + + PendingChunkHandler(Reference chunk) { + this.chunk = chunk; + } + + @Override + protected void compute() { + Reference r = this.chunk; + if (r != null) { + this.chunk = null; + Reference.handlePendingChunk(r); + } + } + } + + /** + * A task for handling a single Finalizer. + */ + static final class FinalizerHandler extends RecursiveAction { + private Finalizer finalizer; + + FinalizerHandler(Finalizer finalizer) { + this.finalizer = finalizer; + } + + @Override + protected void compute() { + Finalizer finalizer = this.finalizer; + if (finalizer != null) { + this.finalizer = null; + finalizer.runFinalizer(); + } + } + + void submit() { + if (Thread.currentThread() instanceof ForkJoinWorkerThread) { + // internal submission + fork(); + } else { + // external submission + pool.submit(this); + } + } + } +} +