Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Threadlocal counter in Clojure

I have a web app where i want to be able to track the number of times a given function is called in a request (i.e. thread).

I know that it is possible to do in a non-thread local way with a ref, but how would I go about doing it thread locally?

like image 530
Casper Avatar asked Sep 12 '11 11:09

Casper


2 Answers

There's a tool for this in useful called thread-local. You can write, for example, (def counter (thread-local (atom 0))). This will create a global variable which, when derefed, will yield a fresh atom per thread. So you could read the current value with @@counter, or increment it with (swap! @counter inc). Of course, you could also get hold of the atom itself with @counter and just treat it like a normal atom from then on.

like image 184
amalloy Avatar answered Oct 22 '22 10:10

amalloy


You can use a dynamic global var, bound to a value with binding in combination with the special form set! to change its value. Vars bound with binding are thread-local. The following will increase *counter* every time my-fn is called for any form called within a with-counter call:

(def ^{:dynamic true} *counter*)

(defmacro with-counter [& body]
  `(binding [*counter* 0]
     ~@body
     *counter*))

(defn my-fn []
  (set! *counter* (inc *counter*)))

To demonstrate, try:

(with-counter (doall (repeatedly 5 my-fn)))
;; ==> 5

For more information, see http://clojure.org/vars#set

like image 32
Gert Avatar answered Oct 22 '22 12:10

Gert