Last active
September 28, 2022 18:05
-
-
Save dustingetz/62425ef8733fb0daff2e8a9aef54ca15 to your computer and use it in GitHub Desktop.
binding conveyance
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defmacro future | |
"Takes a body of expressions and yields a future object that will | |
invoke the body in another thread, and will cache the result and | |
return it on all subsequent calls to deref/@. If the computation has | |
not yet finished, calls to deref/@ will block, unless the variant of | |
deref with timeout is used. See also - realized?." | |
{:added "1.1"} | |
[& body] `(future-call (^{:once true} fn* [] ~@body))) | |
| |
(defn future-call | |
"Takes a function of no args and yields a future object that will | |
invoke the function in another thread, and will cache the result and | |
return it on all subsequent calls to deref/@. If the computation has | |
not yet finished, calls to deref/@ will block, unless the variant | |
of deref with timeout is used. See also - realized?." | |
{:added "1.1" | |
:static true} | |
[f] | |
(let [f (binding-conveyor-fn f) | |
fut (.submit clojure.lang.Agent/soloExecutor ^Callable f)] | |
(reify | |
clojure.lang.IDeref | |
(deref [_] (deref-future fut)) | |
clojure.lang.IBlockingDeref | |
(deref | |
[_ timeout-ms timeout-val] | |
(deref-future fut timeout-ms timeout-val)) | |
clojure.lang.IPending | |
(isRealized [_] (.isDone fut)) | |
java.util.concurrent.Future | |
(get [_] (.get fut)) | |
(get [_ timeout unit] (.get fut timeout unit)) | |
(isCancelled [_] (.isCancelled fut)) | |
(isDone [_] (.isDone fut)) | |
(cancel [_ interrupt?] (.cancel fut interrupt?))))) | |
| |
(defn binding-conveyor-fn | |
{:private true | |
:added "1.3"} | |
[f] | |
(let [frame (clojure.lang.Var/cloneThreadBindingFrame)] | |
(fn | |
([] | |
(clojure.lang.Var/resetThreadBindingFrame frame) | |
(f)) | |
([x] | |
(clojure.lang.Var/resetThreadBindingFrame frame) | |
(f x)) | |
([x y] | |
(clojure.lang.Var/resetThreadBindingFrame frame) | |
(f x y)) | |
([x y z] | |
(clojure.lang.Var/resetThreadBindingFrame frame) | |
(f x y z)) | |
([x y z & args] | |
(clojure.lang.Var/resetThreadBindingFrame frame) | |
(apply f x y z args))))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://github.com/clojure/clojure/blob/5ffe3833508495ca7c635d47ad7a1c8b820eab76/src/jvm/clojure/lang/Var.java#L71-L106 | |
package clojure.lang; | |
... | |
public final class Var extends ARef implements IFn, IRef, Settable, Serializable{ | |
... | |
static class Frame{ | |
final static Frame TOP = new Frame(PersistentHashMap.EMPTY, null); | |
//Var->TBox | |
Associative bindings; | |
//Var->val | |
// Associative frameBindings; | |
Frame prev; | |
public Frame(Associative bindings, Frame prev){ | |
// this.frameBindings = frameBindings; | |
this.bindings = bindings; | |
this.prev = prev; | |
} | |
protected Object clone() { | |
return new Frame(this.bindings, null); | |
} | |
} | |
static final ThreadLocal<Frame> dvals = new ThreadLocal<Frame>(){ | |
protected Frame initialValue(){ | |
return Frame.TOP; | |
} | |
}; | |
... | |
volatile Object root; | |
volatile boolean dynamic = false; | |
transient final AtomicBoolean threadBound; | |
public final Symbol sym; | |
public final Namespace ns; | |
//IPersistentMap _meta; | |
public static Object getThreadBindingFrame(){ | |
return dvals.get(); | |
} | |
public static Object cloneThreadBindingFrame(){ | |
return dvals.get().clone(); | |
} | |
public static void resetThreadBindingFrame(Object frame){ | |
dvals.set((Frame) frame); | |
} | |
public Var setDynamic(){ | |
this.dynamic = true; | |
return this; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment