package java.lang;
import java.io.Serializable;
/**
* This is a gwt-only mirror of a ThreadLocal map.
*
* Although it may be possible to use html5 workers to mimic threads,
* for now, this object is a simple get/set bean, to replicate behavior of ThreadLocal.
*
* This will allow pure java clients to enable multithreading,
* so all core code will be threadsafe when html5 web workers can support using compiled gwt.
*
* For optimal efficiency, this will likely require compiling multiple independant gwt modules
* which simply export a common javascript api to communicate across windows.
*
* Due to web workers not sharing memory space or objects access across multiple threads,
* each ThreadLocal instance will still be nothing more than a singleton bean wrapper.
*
*
*/
public class ThreadLocal<T> implements Serializable{
private static final long serialVersionUID = 6815410897499755586L;
/**
* The singleton bean value we will be wrapping.
*/
protected T value;
/**
* A boolean used so we can mimic accurate ThreadLocal behavior,
* which is to only call {@link #initialValue()} once, and once only,
* until {@link #remove()} is called.
*
* To override this behavior and call {@link #initialValue()} until it returns non-null,
* just subclass ThreadLocal and define a method,
* protected void setInitialValue(){
* T value = initialValue();
* set(value);
* return value;
* }
*
*/
protected transient boolean isInitialized = false;
/**
* Returns the current thread's "initial value" for this
* thread-local variable. This method will be invoked the first
* time a thread accesses the variable with the {@link #get}
* method, unless the thread previously invoked the {@link #set}
* method, in which case the <tt>initialValue</tt> method will not
* be invoked for the thread. Normally, this method is invoked at
* most once per thread, but it may be invoked again in case of
* subsequent invocations of {@link #remove} followed by {@link #get}.
*
* <p>This implementation simply returns <tt>null</tt>; if the
* programmer desires thread-local variables to have an initial
* value other than <tt>null</tt>, <tt>ThreadLocal</tt> must be
* subclassed, and this method overridden. Typically, an
* anonymous inner class will be used.
*
* @return the initial value for this thread-local
*/
protected T initialValue() {
return null;
}
/**
* Creates a thread local variable.
*/
public ThreadLocal() {
}
/**
* Returns the value in the current thread's copy of this
* thread-local variable. If the variable has no value for the
* current thread, it is first initialized to the value returned
* by an invocation of the {@link #initialValue} method.
*
* @return the current thread's value of this thread-local
*/
public T get() {
return value==null?setInitialValue():value;
}
/**
* Variant of set() to establish initialValue. Used instead
* of set() in case user has overridden the set() method.
*
* @return the initial value
*/
protected T setInitialValue() {
if (!isInitialized){
value = initialValue();
isInitialized = true;
}
return value;
}
/**
* Sets the current thread's copy of this thread-local variable
* to the specified value. Most subclasses will have no need to
* override this method, relying solely on the {@link #initialValue}
* method to set the values of thread-locals.
*
* @param value the value to be stored in the current thread's copy of
* this thread-local.
*/
public void set(T value) {
this.value = value;
isInitialized=true;
}
/**
* Removes the current thread's value for this thread-local
* variable. If this thread-local variable is subsequently
* {@linkplain #get read} by the current thread, its value will be
* reinitialized by invoking its {@link #initialValue} method,
* unless its value is {@linkplain #set set} by the current thread
* in the interim. This may result in multiple invocations of the
* <tt>initialValue</tt> method in the current thread.
*
* @since 1.5
*/
public void remove() {
isInitialized = false;
value = null;
}
}