package javolution37.javolution.realtime;
import java.io.Serializable;
import javolution37.javolution.lang.Reference;
import javolution37.javolution.util.FastMap;
/**
* This class represents a reference whose setting is local to the current
* {@link LocalContext}; setting outside of any {@link LocalContext} scope
* affects the reference default value (equivalent to {@link #setDefault}).
* For example:[code]
* public class Foo {
* public static final LocalReference> FORMAT
* = new LocalReference>(DEFAULT_FORMAT);
*
* public Text toString() {
* return FORMAT.get().format(this).toString();
* }
* }
* ...
* LocalContext.enter();
* try {
* Foo.FORMAT.set(localFormat);
* ... // This thread displays Foo instances using localFormat.
* } finally {
* LocalContext.exit(); // Reverts to previous format.
* }[/code]
*
* Accessing/setting a local reference is fast and does not require
* any form of synchronization. Local settings are inherited by
* {@link ConcurrentThread concurrent threads} spawned from within the
* same {@link LocalContext}.
*/
public class LocalReference implements Reference , Serializable {
/**
* Holds the default value for this reference.
*/
private T _defaultValue;
/**
* Indicates if this reference value has ever been locally overriden
* (optimization, most applications use default values).
*/
private boolean _hasBeenLocallyOverriden;
/**
* Default constructor (default referent is null).
*/
public LocalReference() {
this(null);
}
/**
* Creates a local reference having the specified default value.
*
* @param defaultValue the default value or root value of this variable.
*/
public LocalReference( T defaultValue) {
_defaultValue = defaultValue;
}
/**
* Returns the local value for this reference.
* The first outer {@link LocalContext} is searched first, then
* all outer {@link LocalContext} are recursively searched up to the
* global root context which contains the default value.
*
* @return the context-local value.
*/
public final T get() {
return (_hasBeenLocallyOverriden) ? retrieveValue() : _defaultValue;
}
private T retrieveValue() {
for (LocalContext ctx = Context.current().inheritedLocalContext; ctx != null; ctx = ctx
.getOuter().inheritedLocalContext) {
Object value = ctx._references.get(this);
if (value != null) {
return ( T ) value;
}
}
// Not found, returns default value.
return _defaultValue;
}
/**
* Sets the local value (referent) for this reference.
*
* @param value the new local value or null to inherit
* the outer value.
*/
public void set( T value) {
LocalContext ctx = Context.current().inheritedLocalContext;
if (ctx != null) {
FastMap references = ctx._references;
references.put(this, value);
_hasBeenLocallyOverriden = true;
return;
}
// No local context, sets default value.
_defaultValue = value;
}
/**
* Returns the default value for this reference.
*
* @return the defaultValue.
*/
public T getDefault() {
return _defaultValue;
}
/**
* Returns the local (non-inherited) value for this reference.
*
* @return the local value or null if none (value to be
* inherited or not set).
*/
public T getLocal() {
LocalContext ctx = Context.current().inheritedLocalContext;
return (ctx != null) ? ( T ) ctx._references.get(this)
: _defaultValue;
}
/**
* Sets the default value for this reference.
*
* @param defaultValue the root value.
*/
public void setDefault( T defaultValue) {
_defaultValue = defaultValue;
}
/**
* Returns the string representation of the current value of this
* reference.
*
* @return String.valueOf(this.get())
*/
public String toString() {
return String.valueOf(this.get());
}
}
Ads help maintain this website.