Created
January 17, 2015 19:52
-
-
Save ciniglio/bf80f6ceb664f75032ae to your computer and use it in GitHub Desktop.
Clojure race condition
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
;; Original from | |
;; https://github.com/aphyr/prism/blob/d59aa8cc3b59b44f5241e53d452340bfc3936343/src/com/aphyr/prism.clj#L63 | |
(defn slur | |
"Takes a unary function f, and a time in ms. Returns a function g such that | |
(g x) causes (f x) to be invoked unless (g x) had been invoked less than dt | |
ms ago." | |
[dt f] | |
; Maintain a map of args to invocation times. | |
(let [ts (atom {})] | |
(fn g [x] | |
(let [now (System/currentTimeMillis) | |
ts (swap! ts (fn [ts] | |
(let [prev (get ts x)] | |
(if (and prev (< (- now prev) dt)) | |
ts | |
(assoc ts x now))))) | |
prev (get ts x)] | |
; If we're the first to call, or it's been longer than dt ms, call f. | |
(when (or (= now prev) | |
(<= dt (- now prev))) | |
(f x)))))) | |
(defn my-slur | |
[dt f] | |
(let [ts (ref {})] | |
(fn g [x] | |
(when (dosync | |
(let [now (System/currentTimeMillis) | |
prev (get @ts x 0) | |
enough-time-has-passed (> (- now prev) dt) | |
ts (alter ts (fn [ts] | |
(if enough-time-has-passed | |
(assoc ts x now) | |
ts)))] | |
enough-time-has-passed)) | |
(f x))))) | |
(defn test-slur [slur] | |
(let [a (atom []) | |
dt 10 | |
f (fn [_] (swap! a #(conj % (System/currentTimeMillis)))) | |
g (slur dt f)] | |
(doseq [x (range 1 10000)] (g 1)) | |
(if (> (count @a) 1) | |
(let [diffs (reduce #(and %1 %2) (map (partial < dt)(map - (subvec @a 1) @a)))] | |
diffs) | |
a))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment