com.blogspot.mydailyjava.weaklockfree.DetachedThreadLocal Maven / Gradle / Ivy
package com.blogspot.mydailyjava.weaklockfree;
/**
*
* A detached local that allows for explicit control of setting and removing values from a thread-local
* context.
*
* Instances of this class are non-blocking and fully thread safe.
*/
public class DetachedThreadLocal implements Runnable {
final WeakConcurrentMap map;
public DetachedThreadLocal(Cleaner cleaner) {
switch (cleaner) {
case THREAD:
case MANUAL:
map = new WeakConcurrentMap(cleaner == Cleaner.THREAD) {
@Override
protected T defaultValue(Thread key) {
return DetachedThreadLocal.this.initialValue(key);
}
};
break;
case INLINE:
map = new WeakConcurrentMap.WithInlinedExpunction() {
@Override
protected T defaultValue(Thread key) {
return DetachedThreadLocal.this.initialValue(key);
}
};
break;
default:
throw new AssertionError();
}
}
public T get() {
return map.get(Thread.currentThread());
}
public T getIfPresent() {
return map.getIfPresent(Thread.currentThread());
}
public void set(T value) {
map.put(Thread.currentThread(), value);
}
public void clear() {
map.remove(Thread.currentThread());
}
/**
* Clears all thread local references for all threads.
*/
public void clearAll() {
map.clear();
}
/**
* @param thread The thread to which this thread's thread local value should be pushed.
* @return The value being set.
*/
public T pushTo(Thread thread) {
T value = get();
if (value != null) {
map.put(thread, inheritValue(value));
}
return value;
}
/**
* @param thread The thread from which the thread thread local value should be fetched.
* @return The value being set.
*/
public T fetchFrom(Thread thread) {
T value = map.get(thread);
if (value != null) {
set(inheritValue(value));
}
return value;
}
/**
* @param thread The thread for which to set a thread-local value.
* @return The value accociated with this thread.
*/
public T get(Thread thread) {
return map.get(thread);
}
/**
* @param thread The thread for which to set a thread-local value.
* @param value The value to set.
*/
public void define(Thread thread, T value) {
map.put(thread, value);
}
/**
* @param thread The thread for which an initial value is created.
* @return The initial value for any thread local. If no default is set, the default value is {@code null}.
*/
protected T initialValue(Thread thread) {
return null;
}
/**
* @param value The value that is inherited.
* @return The inherited value.
*/
protected T inheritValue(T value) {
return value;
}
/**
* @return The weak map that backs this detached thread local.
*/
public WeakConcurrentMap getBackingMap() {
return map;
}
@Override
public void run() {
map.run();
}
/**
* Determines the cleaning format. A reference is removed either by an explicitly started cleaner thread
* associated with this instance ({@link Cleaner#THREAD}), as a result of interacting with this thread local
* from any thread ({@link Cleaner#INLINE} or manually by submitting the detached thread local to a thread
* ({@link Cleaner#MANUAL}).
*/
public enum Cleaner {
THREAD, INLINE, MANUAL
}
}