Last active
August 29, 2015 14:14
-
-
Save danlentz/301a0f056ffd9c6605a9 to your computer and use it in GitHub Desktop.
Thread-safe Monotonic Clock for Clojure
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
(ns clock) | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;; Lock-Free Thread-safe Monotonic Clock | |
;; Dan Lentz <http://github.com/danlentz> | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;; We use epoch stamp (milliseconds) and zero-pad the low order bits | |
;; of millisecond stamp and provide atomic incremental | |
;; uuids-this- second subcounter on the low order bits, which | |
;; guarantee that two timestamps never collide regardless of clock | |
;; precision. | |
;; | |
;; 113914335216380000 (+ (* (epoch-time) 10000) 100103040000000000) | |
;; 113914335216380001 first contending timestamp | |
;; 113914335216380002 second contending timestamp | |
;; ... and so forth | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
(def ^:const +subcounter-resolution+ 9999) | |
(deftype State [^short seqid ^long millis]) | |
(let [-state- (atom (->State 0 0))] | |
(defn monotonic-time ^long [] | |
(let [^State new-state | |
(swap! -state- | |
(fn [^State current-state] | |
(loop [time-now (System/currentTimeMillis)] | |
(if-not (= (.millis current-state) time-now) | |
(->State 0 time-now) | |
(let [tt (.seqid current-state)] | |
(if (< tt +subcounter-resolution+) | |
(->State (inc tt) time-now) | |
(recur (System/currentTimeMillis))))))))] | |
(+ (.seqid new-state) | |
(+ (* (.millis new-state) 10000) 100103040000000000))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@danlentz Thanks! I'm looking forward for more ;)