Skip to content

Instantly share code, notes, and snippets.

@armed
Created September 16, 2020 15:05
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 armed/6376fe49e804e136197ff0a2ce19a942 to your computer and use it in GitHub Desktop.
Save armed/6376fe49e804e136197ff0a2ce19a942 to your computer and use it in GitHub Desktop.
(ns activator.singularizer-cache)
(def SINGULARITY (atom {}))
(def sing-update-in!
(partial swap! SINGULARITY update-in))
(def sing-assoc-in!
(partial swap! SINGULARITY assoc-in))
(defn wait-result
[func args]
(when-let [job (get-in @SINGULARITY [func args :job])]
(sing-update-in! [func args :count] inc)
(let [result @job]
(sing-update-in! [func args :count] dec)
(when (= 0 (get-in @SINGULARITY [func args :count]))
(sing-assoc-in! [func args :job] nil))
result)))
(defn singularize-fn
"Takes function and returns new function with
singular call restriction. Singular restriction means
that function with specific args can be called only once
at a time, all other same args parallell calls will be placed
in wait queue. Then single result will be pased to all calls."
[func]
(swap! SINGULARITY assoc func {})
(fn [& args]
(if-let [result (wait-result func args)]
result
(let [job (future (apply func args))]
(sing-assoc-in! [func args] {:job job
:count 0})
(wait-result func args)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment