Skip to content

Instantly share code, notes, and snippets.

@aamedina
Created September 17, 2013 17:22
Show Gist options
  • Select an option

  • Save aamedina/6597546 to your computer and use it in GitHub Desktop.

Select an option

Save aamedina/6597546 to your computer and use it in GitHub Desktop.
(defmacro future
[& body]
`(mvc.impl.future/future-call (fn [] (cljs.core.async.macros/go ~@body))))
(defn future-call
([f]
(let [p (promise)
task (fn []
(try (let [val (atom {:done false :cancelled false :value p})
val-chan (chan)]
(go (let [v (<! (f))]
(deliver p v)
(put! val-chan v)
(swap! val assoc :done true)))
[val val-chan])
(catch js/Error e
(deliver-exception p e))))
[state state-chan] (task)]
(Future. state state-chan))))
(extend-protocol INotify
channels/ManyToManyChannel
(-attend [this f]
(let [p (promise)]
(take! this #(f %))
p)))
(defn deliver
[promise val]
(if (instance? js/Error val)
(deliver-exception promise val)
(if (and (not (realized? promise))
(satisfies? INotify val))
(attend val (fn [v]
(try (deliver promise v)
(catch js/Error e
(deliver-exception promise e)))))
(-deliver promise val))))
(deftype Promise [latch v ^:mutable q ^:mutable e val-chan]
IDeliver
(-deliver [this val]
(when (and (pos? @latch) (compare-and-set! v latch val))
(swap! latch dec)
(try (put! val-chan val)
(catch js/Error e
(deliver-exception this e)))
this))
(-deliver-exception [this exception]
(-deliver this exception))
;; remaining implementations omitted
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment