diff options
author | Rich Hickey <richhickey@gmail.com> | 2008-12-11 14:28:00 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2008-12-11 14:28:00 +0000 |
commit | c5e8c6f06292fab26d29cb951d8400394e0f8258 (patch) | |
tree | bca2cef66acef4a4ef2b36433bcb884bfcddea48 /src | |
parent | d49f0d32473d8387696049b8b10b8403d86e05e4 (diff) |
added if-not, memoize, and io!
io! blocks will throw exceptions when run in transactions
made await and await-for use io!
Diffstat (limited to 'src')
-rw-r--r-- | src/clj/clojure/core.clj | 50 | ||||
-rw-r--r-- | src/jvm/clojure/lang/LockingTransaction.java | 4 |
2 files changed, 46 insertions, 8 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index e1e8d707..8d46be01 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -444,6 +444,12 @@ (cat (concat x y) zs)))) ;;;;;;;;;;;;;;;;at this point all the support for syntax-quote exists;;;;;;;;;;;;;;;;;;;;;; +(defmacro if-not + "Evaluates test. If logical false, evaluates and returns then expr, otherwise else expr, if supplied, else nil." + ([test then] `(if-not ~test ~then nil)) + ([test then else] + `(if (not ~test) ~then ~else))) + (defn = "Equality. Returns true if x equals y, false if not. Same as Java x.equals(y) except it also works for nil, and compares @@ -1187,6 +1193,17 @@ (runInTransaction (fn [] ~@body)))) +(defmacro io! + "If an io! block occurs in a transaction, throws an + IllegalStateException, else runs body in an implicit do. If the + first expression in body is a literal string, will use that as the + exception message." + [& body] + (let [message (when (string? (first body)) (first body)) + body (if message (rest body) body)] + `(if (clojure.lang.LockingTransaction/isRunning) + (throw (new IllegalStateException ~(or message "I/O in transaction"))) + (do ~@body)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fn stuff ;;;;;;;;;;;;;;;; @@ -1522,13 +1539,14 @@ dispatched thus far, from this thread or agent, to the agent(s) have occurred." [& agents] + (io! "await in transaction" (when *agent* (throw (new Exception "Can't await in agent action"))) (let [latch (new java.util.concurrent.CountDownLatch (count agents)) count-down (fn [agent] (. latch (countDown)) agent)] (doseq [agent agents] (send agent count-down)) - (. latch (await)))) + (. latch (await))))) (defn await1 [#^clojure.lang.Agent a] (when (pos? (.getQueueCount a)) @@ -1541,13 +1559,14 @@ timeout (in milliseconds) has elapsed. Returns nil if returning due to timeout, non-nil otherwise." [timeout-ms & agents] - (when *agent* - (throw (new Exception "Can't await in agent action"))) - (let [latch (new java.util.concurrent.CountDownLatch (count agents)) - count-down (fn [agent] (. latch (countDown)) agent)] - (doseq [agent agents] - (send agent count-down)) - (. latch (await timeout-ms (. java.util.concurrent.TimeUnit MILLISECONDS))))) + (io! "await-for in transaction" + (when *agent* + (throw (new Exception "Can't await in agent action"))) + (let [latch (new java.util.concurrent.CountDownLatch (count agents)) + count-down (fn [agent] (. latch (countDown)) agent)] + (doseq [agent agents] + (send agent count-down)) + (. latch (await timeout-ms (. java.util.concurrent.TimeUnit MILLISECONDS)))))) (defmacro dotimes "bindings => name n @@ -3572,6 +3591,21 @@ ~@body (recur)))) +(declare atom swap!) + +(defn memoize + "Returns a memoized version of a referentially transparent function. The + memoized version of the function keeps a cache of the mapping from arguments + to results and, when calls with the same arguments are repeated often, has + higher performance at the expense of higher memory use." + [f] + (let [mem (atom {})] + (fn [& args] + (if-let [e (find @mem args)] + (val e) + (let [ret (apply f args)] + (swap! mem assoc args ret) + ret))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; helper files ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/src/jvm/clojure/lang/LockingTransaction.java b/src/jvm/clojure/lang/LockingTransaction.java index b71cf784..9ef38f1e 100644 --- a/src/jvm/clojure/lang/LockingTransaction.java +++ b/src/jvm/clojure/lang/LockingTransaction.java @@ -181,6 +181,10 @@ static LockingTransaction getEx(){ return t; } +static public boolean isRunning(){ + return getRunning() != null; +} + static LockingTransaction getRunning(){ LockingTransaction t = transaction.get(); if(t == null || t.info == null) |