Most atom operators return the previous value before the swap such as std::atomic::fetch_add
in C++. It's natural to use atomic int as a global increasing id starting from 0. Why does Clojure's atom return the value which is swapped in?
(def global-counter (atom 0))
(defn next! [] (dec (swap! global-counter inc)))
Is there a better way to create a zero-based counter in Clojure?
Counter question: Do you know why std::atomic::fetch_add
returns the pre-transaction value? (I don't.)
Calling swap!
peforms a transaction and returns its result. In a concurrent scenario, if it returned the pre-transaction value, the only deterministic way to get the transaction result would be to repeat the in-transaction application, e. g.
(def pre-tx (std-swap! global-counter inc))
(def tx-result (inc pre-tx))
Certainly, an opposite example could be made up for the pre-transaction value. However, in most cases (and your example case too - see below), the tx-result is the value relevant for further reference. This is why swap!
was designed to return it directly. For different requirements, a ref
is suitable (Unless using an atom
is requirement, in which case you have to create your own spin-loop with compare-and-set!
).
In your example,next!
should return 1
on the first call and there is no reason to dec
it as long as counting is the given example. Counting always starts with one: If you count one, your total count is 1
. If next!
ever returned 0
(imaginary) last!
would return -1
, an invalid total count.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With