2929 */
3030package org .jruby .embed .internal ;
3131
32- import java .lang .ref .PhantomReference ;
33- import java .lang .ref .Reference ;
34- import java .lang .ref .ReferenceQueue ;
32+ import java .lang .ref .Cleaner ;
33+ import java .lang .ref .Cleaner .Cleanable ;
3534import java .util .concurrent .ConcurrentHashMap ;
3635import java .util .concurrent .atomic .AtomicReference ;
3736import java .util .function .Supplier ;
4443 */
4544class ThreadLocalContext {
4645 private final ConcurrentHashMap <LocalContextCleaningAction , Object > contextRefs = new ConcurrentHashMap <>();
46+ private final Cleaner cleaner = Cleaner .create ();
4747 private final Supplier <LocalContext > localContextFactory ;
48- private final Cleaner cleaner = new Cleaner ();
4948
5049 public ThreadLocalContext (final Supplier <LocalContext > localContextFactory ) {
5150 this .localContextFactory = localContextFactory ;
@@ -62,13 +61,13 @@ protected AtomicReference<LocalContextCleaningAction> initialValue() {
6261 // GC'd (i.e. when this class gets GC'd because terminate() was never called).
6362 // see ThreadLocal JavaDoc: ref will stay reachable "as long as the thread is
6463 // alive and the ThreadLocal instance is accessible"
65- ctx .register (ref , cleaner );
64+ final Cleanable cleanable = cleaner .register (ref , ctx );
6665 if (contextHolder == null )
6766 // boundary case if we're already terminating: clean up immediately, because
6867 // there is no more cleanup thread to do that later
6968 // the returned context will be null, but that's to be expected when operating
7069 // on an object that has been terminated
71- ctx . run ();
70+ cleanable . clean ();
7271 return ref ;
7372 }
7473 };
@@ -78,7 +77,6 @@ public LocalContext get() {
7877 }
7978
8079 public void terminate () {
81- cleaner .interrupt ();
8280 contextHolder = null ;
8381 for (final LocalContextCleaningAction ref : contextRefs .keySet ())
8482 ref .run ();
@@ -90,14 +88,11 @@ public void terminate() {
9088 * everything that is GC-reachable from them will stay reachable until the
9189 * cleaning action has been run.
9290 */
93- static class LocalContextCleaningAction extends AtomicReference <LocalContext > implements Runnable {
91+ private static class LocalContextCleaningAction extends AtomicReference <LocalContext > implements Runnable {
9492 private static final long serialVersionUID = 1L ;
9593
9694 private final ConcurrentHashMap <LocalContextCleaningAction , Object > contextRefs ;
9795
98- @ SuppressWarnings ("unused" ) // only used to make sure the PhantomReference doesn't get GC'd
99- private CleanerReference phantomReference ;
100-
10196 private LocalContextCleaningAction (final ConcurrentHashMap <LocalContextCleaningAction , Object > contextRefs ,
10297 final LocalContext context ) {
10398 super (context );
@@ -116,42 +111,5 @@ public void run() {
116111 lc .remove ();
117112 contextRefs .remove (this );
118113 }
119-
120- private void register (final AtomicReference <LocalContextCleaningAction > ref , final Cleaner cleaner ) {
121- phantomReference = new CleanerReference (ref , cleaner .q , this );
122- }
123- }
124-
125- private static class CleanerReference extends PhantomReference <AtomicReference <LocalContextCleaningAction >> {
126- private Runnable cleanup ;
127-
128- public CleanerReference (final AtomicReference <LocalContextCleaningAction > referent ,
129- final ReferenceQueue <AtomicReference <LocalContextCleaningAction >> q , final Runnable cleanup ) {
130- super (referent , q );
131- this .cleanup = cleanup ;
132- }
133- }
134-
135- private static class Cleaner extends Thread {
136- private final ReferenceQueue <AtomicReference <LocalContextCleaningAction >> q = new ReferenceQueue <>();
137-
138- public Cleaner () {
139- setName ("JRuby-ThreadLocalContext-Cleaner-" + getId ());
140- setDaemon (true );
141- start ();
142- }
143-
144- @ Override
145- public void run () {
146- while (!interrupted ()) {
147- final Reference <?> cleanable ;
148- try {
149- cleanable = q .remove ();
150- } catch (InterruptedException e ) {
151- break ;
152- }
153- ((CleanerReference ) cleanable ).cleanup .run ();
154- }
155- }
156114 }
157115}
0 commit comments