summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMeikel Brandmeyer <mb@kotka.de>2009-08-08 22:57:29 +0200
committerChouser <chouser@n01se.net>2009-11-10 10:42:12 -0500
commitfbacc4a5751fa5c15baa599b5a058cd81b05a247 (patch)
tree59ccee8c1eb4d2c74a92a8b64ada985e99c1dd8a
parent9bde10da7b13dd24b5666260d231d79792a34305 (diff)
Added bound-fn to define thread-local binding aware functions
bound-fn captures the thread-local bindings in effect where the function is defined. Installs these bindings before executing the body. This is useful for helper functions running in a different thread. Excluded with-bindings from clojure/main.clj to prevent name clash. Fixes #170 Signed-off-by: Chouser <chouser@n01se.net>
-rw-r--r--src/clj/clojure/core.clj36
-rw-r--r--src/clj/clojure/main.clj1
2 files changed, 37 insertions, 0 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 95402a00..2b66f6d0 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -1253,6 +1253,42 @@
(finally
(pop-thread-bindings))))))
+(defn with-bindings*
+ "Takes a map of Var/value pairs. Installs for the given Vars the associated
+ values as thread-local bindings. Then calls f with the supplied arguments.
+ Pops the installed bindings after f returned. Returns whatever f returns."
+ [binding-map f & args]
+ (push-thread-bindings binding-map)
+ (try
+ (apply f args)
+ (finally
+ (pop-thread-bindings))))
+
+(defmacro with-bindings
+ "Takes a map of Var/value pairs. Installs for the given Vars the associated
+ values as thread-local bindings. The executes body. Pops the installed
+ bindings after body was evaluated. Returns the value of body."
+ [binding-map & body]
+ `(with-bindings* ~binding-map (fn [] ~@body)))
+
+(defn bound-fn*
+ "Returns a function, which will install the same bindings in effect as in
+ the thread at the time bound-fn* was called and then call f with any given
+ arguments. This may be used to define a helper function which runs on a
+ different thread, but needs the same bindings in place."
+ [f]
+ (let [bindings (get-thread-bindings)]
+ (fn [& args]
+ (apply with-bindings* bindings f args))))
+
+(defmacro bound-fn
+ "Returns a function defined by the given fntail, which will install the
+ same bindings in effect as in the thread at the time bound-fn was called.
+ This may be used to define a helper function which runs on a different
+ thread, but needs the same bindings in place."
+ [& fntail]
+ `(bound-fn* (fn ~@fntail)))
+
(defn find-var
"Returns the global var named by the namespace-qualified symbol, or
nil if no var with that name."
diff --git a/src/clj/clojure/main.clj b/src/clj/clojure/main.clj
index 633c21e9..8c2e9449 100644
--- a/src/clj/clojure/main.clj
+++ b/src/clj/clojure/main.clj
@@ -9,6 +9,7 @@
;; Originally contributed by Stephen C. Gilardi
(ns clojure.main
+ (:refer-clojure :exclude [with-bindings])
(:import (clojure.lang Compiler Compiler$CompilerException
LineNumberingPushbackReader RT)))