diff options
Diffstat (limited to 'src/library/dotnet/util/DynamicVariable.scala')
-rw-r--r-- | src/library/dotnet/util/DynamicVariable.scala | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/library/dotnet/util/DynamicVariable.scala b/src/library/dotnet/util/DynamicVariable.scala new file mode 100644 index 0000000000..101ebe9573 --- /dev/null +++ b/src/library/dotnet/util/DynamicVariable.scala @@ -0,0 +1,83 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.util + + +import Predef._ +import System.Threading.Thread +import System.LocalDataStoreSlot + +/** <p> + * DynamicVariables provide a binding mechanism where the current + * value is found through <em>dynamic scope</em>, but where + * access to the variable itself is resolved through <em>static + * scope</em>. + * </p> + * <p> + * The current value can be retrieved with the + * <code>value</code> method. New values should be + * pushed using the <code>withValue</code> method. + * Values pushed via <code>withValue</code> only + * stay valid while the <code>withValue</code>'s + * <em>second</em> argument, a parameterless closure, + * executes. When the second argument finishes, + * the variable reverts to the previous value. + * </p> + * <p> + * Usage of <code>withValue</code> looks like this: + * </p> + * <blockquote><pre> + * someDynamicVariable.withValue(newValue) { + * // ... code called in here that calls value ... + * // ... will be given back the newValue ... + * } + * </pre></blockquote> + * <p> + * Each thread gets its own stack of bindings. When a + * new thread is created, the fluid gets a copy of + * the stack of bindings from the parent thread, and + * from then on the bindings for the new thread + * are independent of those for the original thread. + * </p> + * + * @author Lex Spoon + * @version 1.1, 2007-5-21 + */ +class DynamicVariable[T](init: T) { + private val slot: LocalDataStoreSlot = Thread.AllocateDataSlot() + value = init + + /** Retrieve the current value */ + def value: T = Thread.GetData(slot).asInstanceOf[T] + + /** Set the value of the fluid while executing the specified + * thunk. + * + * @param newval The value to which to set the fluid + * @param thunk The code to evaluate under the new setting + */ + def withValue[S](newval: T)(thunk: =>S): S = { + val oldval = value + value = newval + + try { thunk } finally { + value = oldval + } + } + + /** Change the currently bound value, discarding the old value. + * Usually withValue() gives better semantics. + */ + def value_=(newval: T) = { Thread.SetData(slot, newval.asInstanceOf[AnyRef]) } + + override def toString: String = "DynamicVariable(" + value +")" +} |