diff options
author | Rich Hickey <richhickey@gmail.com> | 2009-02-26 15:38:28 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2009-02-26 15:38:28 +0000 |
commit | ab4068efb67ce7920d8d66f2443f881625159e9c (patch) | |
tree | ca5b4162c0d7a5553258c9482a603ac84b5dfa2b | |
parent | 2ea56006cb0ee74559ecd5d97e05944c6ee21fc4 (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
-rw-r--r-- | src/clj/clojure/core.clj | 31 |
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 |