summaryrefslogtreecommitdiff
path: root/src/dotnet-library/scala/util/Fluid.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotnet-library/scala/util/Fluid.scala')
-rw-r--r--src/dotnet-library/scala/util/Fluid.scala78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/dotnet-library/scala/util/Fluid.scala b/src/dotnet-library/scala/util/Fluid.scala
new file mode 100644
index 0000000000..ebfefada35
--- /dev/null
+++ b/src/dotnet-library/scala/util/Fluid.scala
@@ -0,0 +1,78 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util
+
+
+import java.lang.InheritableThreadLocal
+
+/** Fluids provide a binding mechanism where the current
+ * value is found through <em>dynamic scope</em>, but where
+ * access to the fluid itself is resolved through </em>static
+ * binding</em> to a variable referencing the fluid.
+ *
+ * The current value can be retrieved with the
+ * <code>value</code> method. New values can 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 fluid reverts to the previous value.
+ *
+ * Usage of <code>withValue</code> looks like this:
+ * <blockquote><pre>
+ * someFluid.withValue(newValue) {
+ * // ... code called in here that calls value ...
+ * // ... will be given back the newValue ...
+ * }
+ * </pre></blockquote>
+ *
+ * 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.
+ *
+ * @author Lex Spoon
+ * @version 1.0, 21/03/2006
+ */
+class Fluid[T](init: T) {
+ private val tl = new InheritableThreadLocal {
+ override def initialValue = init.asInstanceOf[AnyRef]
+ }
+
+ /** Retrieve the current value */
+ def value: T = tl.get.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
+ tl.set(newval)
+
+ try { thunk } finally {
+ tl.set(oldval)
+ }
+ }
+
+ /** Change the currently bound value, discarding the old value.
+ * Usually withValue() gives better semantics.
+ */
+ def value_=(newval: T) = { tl.set(newval) }
+
+ override def toString: String = "Fluid(" + value +")"
+}