net.sf.ehcache.util.lang.VicariousThreadLocal Maven / Gradle / Ivy
/**
* Copyright 2006 Thomas Hawtin
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.ehcache.util.lang;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
/**
* A drop-in replacement {@code ThreadLocal} implementation that does not leak
* when thread-local values reference the {@code ThreadLocal} object.
* The code is optimised to cope with frequently changing values.
*
* In comparison to plain {@code ThreadLocal}, this implementation:
* - from the point of view of a single thread,
* each thread-local
* {code #get} requires access to four objects instead of two
*
- is fractionally slower in terms of CPU cycles for {code #get}
*
- uses around twice the memory for each thead-local value
*
- uses around four times the memory for each {@code ThreadLocal}
*
- may release thread-local values for garbage collection more promptly
*
*/
public class VicariousThreadLocal extends ThreadLocal {
/**
* Maps a unique WeakReference onto each Thread.
*/
private static final ThreadLocal> weakThread =
new ThreadLocal>();
/**
* Returns a unique object representing the current thread.
* Although we use a weak-reference to the thread,
* we could use practically anything
* that does not reference our class-loader.
*/
static WeakReference currentThreadRef() {
WeakReference ref = weakThread.get();
if (ref == null) {
ref = new WeakReference(Thread.currentThread());
weakThread.set(ref);
}
return ref;
}
/**
* Object representing an uninitialised value.
*/
private static final Object UNINITIALISED = new Object();
/**
* Actual ThreadLocal implementation object.
*/
private final ThreadLocal> local =
new ThreadLocal>();
/**
* Maintains a strong reference to value for each thread,
* so long as the Thread has not been collected.
* Note, alive Threads strongly references the WeakReference<Thread>
* through weakThread.
*/
private volatile Holder strongRefs;
/**
* Compare-and-set of {@link #strongRefs}.
*/
private static final AtomicReferenceFieldUpdater strongRefsUpdater =
AtomicReferenceFieldUpdater.newUpdater(VicariousThreadLocal.class, Holder.class, "strongRefs");
/**
* Queue of Holders belonging to exited threads.
*/
private final ReferenceQueue