Skip to content

Instantly share code, notes, and snippets.

@hiredman
Created February 11, 2020 21:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hiredman/d5f0cfe20af8328295edab23c20f9452 to your computer and use it in GitHub Desktop.
Save hiredman/d5f0cfe20af8328295edab23c20f9452 to your computer and use it in GitHub Desktop.
(require '[clojure.core.async.impl.protocols :as impl]
'[clojure.core.async.impl.dispatch :as dispatch]
'[clojure.core.async.impl.channels :as c]
'[clojure.core.async :as async])
;;=> nil
(defn wait [watchable expected?]
(reify
impl/ReadPort
(take! [this handler]
(let [k (Object.)
handle! (fn []
(.lock handler)
(let [good (and (impl/active? handler)
(impl/commit handler))]
(.unlock handler)
good))]
(add-watch watchable k (fn [k r os ns]
(if (impl/active? handler)
(when-let [good (and (expected? os ns)
(handle!))]
(remove-watch watchable k)
(dispatch/run #(good ns)))
(remove-watch watchable k))))
(let [v @watchable]
(when-let [good (and (expected? v v)
(handle!))]
(remove-watch watchable k)
(c/box v)))))))
;;=> #'user/wait
(def x (atom :foo))
;;=> #'user/x
(first (async/alts!! [(async/timeout 1000) (wait x (fn [old new] (= new :bar)))]))
;;=> nil
(reset! x :bar)
;;=> :bar
(first (async/alts!! [(async/timeout 1000) (wait x (fn [old new] (= new :bar)))]))
;;=> :bar
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment