summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2009-02-26 15:38:28 +0000
committerRich Hickey <richhickey@gmail.com>2009-02-26 15:38:28 +0000
commitab4068efb67ce7920d8d66f2443f881625159e9c (patch)
treeca5b4162c0d7a5553258c9482a603ac84b5dfa2b /src
parent2ea56006cb0ee74559ecd5d97e05944c6ee21fc4 (diff)
interim checkin - needs testing - made watches synchronous, send old+new state, added add-watch, remove-watch, redefined add-watcher in terms of add-watch
Diffstat (limited to 'src')
-rw-r--r--src/clj/clojure/core.clj31
1 files changed, 28 insertions, 3 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index f46d9063..a54e0f23 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -1212,6 +1212,27 @@
occurring, does nothing. Returns the number of actions dispatched."
[] (clojure.lang.Agent/releasePendingSends))
+(defn add-watch
+ "Experimental.
+ Adds a watch function to an agent/atom/var/ref reference. The watch
+ fn must be a fn of 4 args: a key, the reference, its old-state, its
+ new-state. Whenever the reference's state might have been changed,
+ any registered watches will have their functions sent. The watch fn
+ will be caled synchronously, on the agent's thread if an agent,
+ before any pending sends if agent or ref. Note that an atom's or
+ ref's state may have changed again prior to the fn call, so use
+ old-state rather than derefing the reference. Note also that watch fns
+ may be called from multiple threads simultaneously. Var watchers are
+ triggered only by root binding changes, not thread-local set!s"
+ [#^clojure.lang.IRef reference key fn]
+ (.addWatch reference key fn))
+
+(defn remove-watch
+ "Experimental.
+ Removes a watch (set by add-watch) from a reference"
+ [#^clojure.lang.IRef reference key]
+ (.removeWatch reference key))
+
(defn add-watcher
"Experimental.
Adds a watcher to an agent/atom/var/ref reference. The watcher must
@@ -1222,13 +1243,17 @@
be sent after the reference's state is changed. Var watchers are
triggered only by root binding changes, not thread-local set!s"
[#^clojure.lang.IRef reference send-type watcher-agent action-fn]
- (.addWatch reference watcher-agent action-fn (= send-type :send-off)))
+ (add-watch reference watcher-agent
+ (fn [watcher-agent reference old-state new-state]
+ (when-not (identical? old-state new-state)
+ ((if (= send-type :send-off) send-off send)
+ watcher-agent action-fn reference)))))
(defn remove-watcher
"Experimental.
Removes a watcher (set by add-watcher) from a reference"
- [#^clojure.lang.IRef reference watcher-agent]
- (.removeWatch reference watcher-agent))
+ [reference watcher-agent]
+ (remove-watch reference watcher-agent))
(defn agent-errors
"Returns a sequence of the exceptions thrown during asynchronous