<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Clojure Q&amp;A - Recent questions in Refs, agents, atoms</title>
<link>https://ask.clojure.org/index.php/questions/clojure/refs-agents-atoms</link>
<description></description>
<item>
<title>Why vswap is a macro instead of function like swap?</title>
<link>https://ask.clojure.org/index.php/14531/why-vswap-is-a-macro-instead-of-function-like-swap</link>
<description>&lt;p&gt;Why &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L2556C17&quot;&gt;clojure.core/vswap&lt;/a&gt; is a macro with tag hint instead of a function called on clojure.lang.Volatile similar to &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L2362&quot;&gt;clojure.core/swap&lt;/a&gt;?&lt;/p&gt;
</description>
<category>Refs, agents, atoms</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14531/why-vswap-is-a-macro-instead-of-function-like-swap</guid>
<pubDate>Sun, 04 May 2025 21:16:23 +0000</pubDate>
</item>
<item>
<title>Why does `await` fire off an `agent`'s watch?</title>
<link>https://ask.clojure.org/index.php/14357/why-does-await-fire-off-an-agent-s-watch</link>
<description>&lt;p&gt;I'm having trouble understand how &lt;code&gt;await&lt;/code&gt; works on agents.&lt;br&gt;
From the doc string reads&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Blocks the current thread (indefinitely!) until all actions dispatched&lt;br&gt;
thus far, from this thread or agent, to the agent(s) have occurred.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So sounds like it should wait for any tasks running on a given agent or any work that agent has dispatched itself (say to other agents or threads). So if I  &lt;code&gt;send&lt;/code&gt; something then I can &lt;code&gt;await&lt;/code&gt; for it to finish. &lt;/p&gt;
&lt;p&gt;However, it seems like a &lt;code&gt;watch&lt;/code&gt; will also triggers for some reason...&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(def bond (agent nil))

(add-watch bond
           :test
           (fn [_,_,_,_]
             (println &quot;pew pew&quot;)))

(await bond)

;; the value of bond hasnt changed but it prints &quot;pew pew&quot; ..?

;; can be called an arbitrary number of times - keeps firing

(await bond)
(await bond)
(await bond)
(await bond)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;add-watch&lt;/code&gt; docs read&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Whenever the reference's state might have been changed, any registered watches will have their functions called.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;However here the agent's state hasn't changed and yet it's fired&lt;/p&gt;
&lt;p&gt;What's going on?&lt;/p&gt;
</description>
<category>Refs, agents, atoms</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14357/why-does-await-fire-off-an-agent-s-watch</guid>
<pubDate>Sat, 25 Jan 2025 04:40:53 +0000</pubDate>
</item>
<item>
<title>Is there a polished version of auto-agents?</title>
<link>https://ask.clojure.org/index.php/14318/is-there-a-polished-version-of-auto-agents</link>
<description>&lt;p&gt;I was reading Clojure in Action and thinking about agents. It seems that by hooking up agents with watches, update functions, and some simple locks, you could create a “reactive&quot; state management. So that when some value &lt;code&gt;a&lt;/code&gt; is updated then all dependent state values update themselves automatically and in parallel on separate threads. While those values are updating you are free to change other state values that aren't in the same dependency graph&lt;/p&gt;
&lt;p&gt;I wrote up a quick draft but then started to look around online (it felt like a bit too obvious of an extension to the agent model). I found some similar ideas back in ~2009 but the trail goes dry. Is there some reason this isn't used more widely? Or is this some modern library I'm missing?&lt;/p&gt;
&lt;p&gt;There was a &quot;cell&quot; implementation by Stuart Sierra called &lt;code&gt;auto-agents&lt;/code&gt; - though I can't find the code&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://groups.google.com/g/clojure/c/NY834N34QvA&quot;&gt;https://groups.google.com/g/clojure/c/NY834N34QvA&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I also found this complete implementation but it's also got no traction at all&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/apatil/lazy-agent&quot;&gt;https://github.com/apatil/lazy-agent&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Has this crystallized into a library somewhere? I'm thinking of writing my own implementation but I wanted a sanity check. I'm concerned maybe this idea was dropped for some reasons I've not considered&lt;/p&gt;
&lt;p&gt;(I'm aware there are things like Javelin, Odoyle and Missionary that can accomplish similar things.. but while they decouple code, they're way too complicated and some don't have a threading story)&lt;/p&gt;
&lt;p&gt;This is a copy of my question on Reddit:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://reddit.com/comments/1hklfyh/comment/m3gyyoq&quot;&gt;https://reddit.com/comments/1hklfyh/comment/m3gyyoq&lt;/a&gt;&lt;/p&gt;
</description>
<category>Refs, agents, atoms</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14318/is-there-a-polished-version-of-auto-agents</guid>
<pubDate>Thu, 26 Dec 2024 18:41:21 +0000</pubDate>
</item>
<item>
<title>Memory leak in seque via agents</title>
<link>https://ask.clojure.org/index.php/14185/memory-leak-in-seque-via-agents</link>
<description>&lt;p&gt;We used &lt;code&gt;seque&lt;/code&gt; to manage a large database migration and observed a possible memory leak that required us to restart it several times.&lt;/p&gt;
&lt;p&gt;We iterated through hundreds of queries to extract data via reduce, each using its own &lt;code&gt;seque&lt;/code&gt; but &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/threatgrid/ctia/pull/1443#issuecomment-2404194366&quot;&gt;eventually ran out of memory&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I believe it could have been related to &lt;code&gt;seque&lt;/code&gt; and its use of agents, which was predicted to leak memory in &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojure.atlassian.net/browse/CLJ-1125&quot;&gt;CLJ-1125&lt;/a&gt;. We have not since tried a migration without &lt;code&gt;seque&lt;/code&gt; for comparison, but I instead turned my attention to &lt;code&gt;seque&lt;/code&gt; and found possibly-related problems.&lt;/p&gt;
&lt;p&gt;seque uses an agent to offer items to its buffer. Agents have a memory leak where the conveyed bindings of a &lt;code&gt;send&lt;/code&gt; are held by the executing Thread (the most relevant being &lt;code&gt;*agent*&lt;/code&gt;). This means even if the &lt;code&gt;seque&lt;/code&gt; is gc'ed, the agent persists if the thread is part of a cached thread pool, usually containing realized items from the producing seq (such as the first item to fail to be offered to the buffer).&lt;/p&gt;
&lt;p&gt;I believe this demonstrates &lt;code&gt;seque&lt;/code&gt; leaking memory (Clojure 1.12.0):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(let [pool-size 500]
  (defn expand-thread-pool! []
    (let [p (promise)]
      (mapv deref (mapv #(future (if (= (dec pool-size) %) (deliver p true) @p)) (range pool-size))))))

(let [_ (expand-thread-pool!) ;; increases likelihood of observing leak
      ready (promise)
      strong-ref (volatile! (Object.))
      weak-ref (java.lang.ref.WeakReference. @strong-ref)
      the-seque (volatile! (seque 1 (lazy-seq
                                      (let [s (repeat @strong-ref)]
                                        (deliver ready true)
                                        s))))]
  @ready
  (vreset! strong-ref nil)
  (vreset! the-seque nil)
  (System/gc)
  (doseq [i (range 10)
          :while (some? (.get weak-ref))]
    (prn &quot;waiting for gc...&quot;)
    (Thread/sleep 1000)
    (System/gc))
  (prn (if (nil? (.get weak-ref))
         &quot;garbage collection successful&quot;
         &quot;seque memory leak!!&quot;)))
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;seque memory leak!!&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This can be reproduced with agents. Once an agent has executed an action, a strong reference persists to the agent via &lt;code&gt;*agent*&lt;/code&gt; in the cached thread it was executed in. Here we observe the agent is not garbage collected if it has executed an action on a cached thread pool (Clojure 1.12.0):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(let [_ (expand-thread-pool!)
      strong-ref (volatile! (agent nil))
      weak-ref (java.lang.ref.WeakReference. @strong-ref)]
  ;#_#_ ;;uncomment this and the agent is freed
  (send-off @strong-ref vector)
  (doseq [i (range 10)
          :while (not (vector? @@strong-ref))]
    (Thread/sleep 1000))
  (vreset! strong-ref nil)
  (System/gc)
  (doseq [i (range 10)
          :while (some? (.get weak-ref))]
    (prn &quot;waiting for gc...&quot;)
    (Thread/sleep 1000)
    (System/gc))
  (prn (if (nil? (.get weak-ref))
         &quot;garbage collection successful&quot;
         &quot;agent memory leak!!&quot;)))
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;waiting for gc...&quot;
;&quot;agent memory leak!!&quot;
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Refs, agents, atoms</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14185/memory-leak-in-seque-via-agents</guid>
<pubDate>Thu, 10 Oct 2024 23:03:20 +0000</pubDate>
</item>
<item>
<title>Ref transactions causing deadlock at the REPL</title>
<link>https://ask.clojure.org/index.php/14016/ref-transactions-causing-deadlock-at-the-repl</link>
<description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;I've come across some strange behavior while playing around with refs at the REPL.&lt;br&gt;
So I have a ref with a simple watcher function:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defn watcher [_ r o n]
  (printf &quot;ref: %s old: %s new: %s time: %d\n&quot; @r o n (System/currentTimeMillis))
  (flush))

(def x (ref 2))
(add-watch x nil watcher) 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I then evaluate the following expression two times in a row: &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(future (dosync (ensure x) (Thread/sleep 3000) (alter x * 2)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What I would expect to happen is that the watcher function should print the ref's value two times in a row, about 3 seconds apart.&lt;br&gt;
But nothing happens.&lt;br&gt;
When I then try to access the ref with another command such as&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(dosync (ensure x) (alter x inc))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The REPL blocks completely. Once I did get the expected results several minutes later, another time I got this error message:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Execution error at reftest.core/eval24449 (form-init12758928819079876959.clj:34).                                               
Transaction failed after reaching retry limit
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What I find perplexing is that everything seems to work just fine when I evaluate this let-block:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(let [x (ref 2)]
  (add-watch x nil watcher)
  (println &quot;start:&quot; (deref x))
  (future (dosync (ensure x) (Thread/sleep 3000) (alter x * 2)))
  (future (dosync (ensure x) (Thread/sleep 3000) (alter x * 2)))
  (dosync (ensure x) (alter x inc))
  (println &quot;end:&quot; @x))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Is the behavior at the REPL some kind of bug or am I doing something wrong?&lt;br&gt;
How can I make sure that such STM transactions don't fail in real code?&lt;/p&gt;
</description>
<category>Refs, agents, atoms</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14016/ref-transactions-causing-deadlock-at-the-repl</guid>
<pubDate>Tue, 09 Jul 2024 14:28:33 +0000</pubDate>
</item>
<item>
<title>What's an ideomatic way to manage state in a library?</title>
<link>https://ask.clojure.org/index.php/13734/whats-an-ideomatic-way-to-manage-state-in-a-library</link>
<description>&lt;p&gt;I’m porting a JS library to clojure (and, potentially cljs), and I’m struggling with reasoning about local state. Imagine a scenario where you do RPC over websockets, and the server reply contextually depend on what the server had already sent you. You'd want to keep a local cache of the replies from the server, then.&lt;/p&gt;
&lt;p&gt;In OOP world it's expected you incapsulate both the socket and the cache and provide the library users an interface that sends RPCs and transparently handles the cache population and pulling results from it. What would be the ideomatic way to do the same in clojure[-script]? Would I just return a map and expect my functions to take it as a first argument, returning the update state along with the rpc result?&lt;/p&gt;
</description>
<category>Refs, agents, atoms</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/13734/whats-an-ideomatic-way-to-manage-state-in-a-library</guid>
<pubDate>Thu, 15 Feb 2024 12:46:36 +0000</pubDate>
</item>
<item>
<title>How to force a timeout?</title>
<link>https://ask.clojure.org/index.php/13545/how-to-force-a-timeout</link>
<description>&lt;pre&gt;&lt;code&gt;(defn tid []                                                        
  [(.getName (Thread/currentThread))                                                        
   (.getId (Thread/currentThread))])

   (defn atomize                                                   
  [f data]                                                                                  
  (let [atomix (atom [])                                                                    
        pool (Executors/newFixedThreadPool 12)                                              
        tasks (map                                                                          
               (fn [datum]                                                                  
                 (fn []                                                                     
                   (swap! atomix conj [(f datum) (tid)])))                                  
               data)]                                                                       
    (doseq [future (.invokeAll pool tasks)]                                                 
      (.get future  10 TimeUnit/MILLISECONDS ))                                             
    (.shutdown pool)                                                                        
    @atomix))




I can't figure out where to place a `sleep` to force a timeout. 
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Refs, agents, atoms</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/13545/how-to-force-a-timeout</guid>
<pubDate>Tue, 12 Dec 2023 13:56:49 +0000</pubDate>
</item>
<item>
<title>Somehow I have to loop after all</title>
<link>https://ask.clojure.org/index.php/13479/somehow-i-have-to-loop-after-all</link>
<description>&lt;p&gt;I know some little Lisp, but Clojure feels a bit different:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defn mojorate []
  (let [v (vec (range 1 11))
        max (- (count v) 1)
        atomix (atom [])
        chanl (async/chan)]
    (println v)
    (loop [i 0]
      (async/go
        (&amp;gt;! chanl (swap! atomix conj (/ (get v i) 2))))
      (if (= i max)
        (do (&amp;lt;!! (async/go (&amp;lt;! chanl)))
          (async/close! chanl)
          @atomix)
        (recur (inc i))))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It's just an exercise with channel, atom loop/recur etc.&lt;/p&gt;
&lt;p&gt;Can you do it like this?&lt;/p&gt;
</description>
<category>Refs, agents, atoms</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/13479/somehow-i-have-to-loop-after-all</guid>
<pubDate>Tue, 21 Nov 2023 19:50:16 +0000</pubDate>
</item>
<item>
<title>How can I retrieve all older values of a PDS like atom/ref/agents ?</title>
<link>https://ask.clojure.org/index.php/11604/how-can-retrieve-all-older-values-of-pds-like-atom-ref-agents</link>
<description>&lt;p&gt;Based on my impression a PDS like clojure atom/refs/agents stores all new values in a tree like data-structure as they get changed over-time.&lt;/p&gt;
&lt;p&gt;Now, my questions are&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In clojure, current values of an identity are could be accesses by defer/@ syntax, is it possible to access all the older values of an atom/ref/agent and print them ? If so, how ?&lt;/li&gt;
&lt;li&gt;If older values of an identity are NOT accessible, then what happens to them ? They are still in memory right ? If I cannot access them, what is the point of having a tree like structure ?&lt;/li&gt;
&lt;/ol&gt;
</description>
<category>Refs, agents, atoms</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/11604/how-can-retrieve-all-older-values-of-pds-like-atom-ref-agents</guid>
<pubDate>Sun, 27 Feb 2022 11:04:39 +0000</pubDate>
</item>
<item>
<title>calling realized? on a delay which is currently executing blocks the caller</title>
<link>https://ask.clojure.org/index.php/10004/calling-realized-delay-currently-executing-blocks-caller</link>
<description>&lt;p&gt;If a &lt;code&gt;delay&lt;/code&gt; is currently processing, calling &lt;code&gt;realized?&lt;/code&gt; causes the caller to block until the delay has completed and then returns true.&lt;/p&gt;
&lt;p&gt;The behaviour I would have expected is that it should return false, which is what happens with futures. After all, if you wanted to wait until it was completed, you would &lt;code&gt;deref&lt;/code&gt; it.&lt;/p&gt;
&lt;p&gt;(also there don't seem to be any tags or categories related to concurrent programming, but since delay is part of clojure.core, I assume this is the correct place to ask)&lt;/p&gt;
</description>
<category>Refs, agents, atoms</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/10004/calling-realized-delay-currently-executing-blocks-caller</guid>
<pubDate>Tue, 05 Jan 2021 14:07:29 +0000</pubDate>
</item>
<item>
<title>How to known all the actions of an agent have been executed?</title>
<link>https://ask.clojure.org/index.php/10000/how-to-known-all-the-actions-of-an-agent-have-been-executed</link>
<description>&lt;p&gt;(def a (agent 0))&lt;/p&gt;
&lt;p&gt;(dotimes [_ 100]&lt;br&gt;
   (send-off a inc))&lt;/p&gt;
&lt;p&gt;How to determine the 100 actions have all been finished?&lt;/p&gt;
</description>
<category>Refs, agents, atoms</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/10000/how-to-known-all-the-actions-of-an-agent-have-been-executed</guid>
<pubDate>Tue, 05 Jan 2021 03:33:56 +0000</pubDate>
</item>
<item>
<title>Where is volatile! officially documented?</title>
<link>https://ask.clojure.org/index.php/9323/where-is-volatile-officially-documented</link>
<description>&lt;p&gt;I was looking for documentation of &lt;code&gt;volatile!&lt;/code&gt; etc., but I came up short.&lt;/p&gt;
&lt;p&gt;There is some information in the Jira ticket &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojure.atlassian.net/browse/CLJ-1512&quot;&gt;https://clojure.atlassian.net/browse/CLJ-1512&lt;/a&gt; (opening statement clarified by Fogus), and some additional flavor was contributed in the form of an unusually vivid question about the needs of stateful transducers in &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojure.atlassian.net/browse/CLJ-2146&quot;&gt;https://clojure.atlassian.net/browse/CLJ-2146&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Java also has something called &quot;volatile&quot;, which is described (for example) at &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html&quot;&gt;https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html&lt;/a&gt;.  But Clojure's docstrings do not refer to Java's concept, which they easily could do if it were similar.&lt;/p&gt;
&lt;p&gt;Does Clojure have official documentation about &lt;code&gt;volatile!&lt;/code&gt;?&lt;/p&gt;
</description>
<category>Refs, agents, atoms</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/9323/where-is-volatile-officially-documented</guid>
<pubDate>Sat, 23 May 2020 22:02:28 +0000</pubDate>
</item>
<item>
<title>Tests for clojure.core/atom</title>
<link>https://ask.clojure.org/index.php/2407/tests-for-clojure-core-atom</link>
<description>&lt;p&gt;As per discussion with Alex Miller Mars 3rd 2016 on clojure-dev, Alex suggested we should add tests to clojure.core/atom functionality, of which there is none today.&lt;/p&gt;
&lt;p&gt;I proposed tests for&lt;br&gt;
- the various ways to instatiate atoms (with and without validator and metadata)&lt;br&gt;
- that validators throws correctly&lt;br&gt;
- adding and removing watchers and that they trig as one would expected.&lt;br&gt;
- various ways of changing values (no aim for finding high-load concurrency issues or patological cases or similar).&lt;br&gt;
- that the arities of the interface in IAtom .swap works as expected - ie no reflection warnings (help/pointers for these type of cases needed!)&lt;br&gt;
- generative, tests trying to find the glitches while using atoms (the things excluded above).&lt;/p&gt;
&lt;p&gt;Alex suggested generative testing, but no performance tests.&lt;/p&gt;
&lt;p&gt;The patch &quot;0001-atom-unit-tests.clj&quot; (attached) contains &lt;strong&gt;unit&lt;/strong&gt; tests for &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;creating &quot;bare&quot; atom&lt;/li&gt;
&lt;li&gt;creating atom with validator&lt;/li&gt;
&lt;li&gt;that validate-fn triggers and that the atom is unchanged&lt;/li&gt;
&lt;li&gt;that deref (@) reader macro creates correct '(clojure.core/deref a)&lt;/li&gt;
&lt;li&gt;that CAS works for ordinary values (no validator-triggering etc).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are plenty of combinations &lt;strong&gt;not&lt;/strong&gt; covered with these tests, but this is a start. &lt;/p&gt;
&lt;p&gt;To cover all cases (like cas-ing with invalid values and other strange things) generative testing is indeed a must.&lt;/p&gt;
</description>
<category>Refs, agents, atoms</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/2407/tests-for-clojure-core-atom</guid>
<pubDate>Mon, 18 Apr 2016 09:19:10 +0000</pubDate>
</item>
<item>
<title>atom watchers are not atomic with respect to reset!</title>
<link>https://ask.clojure.org/index.php/3816/atom-watchers-are-not-atomic-with-respect-to-reset</link>
<description>It is possible that two threads calling `reset!` on an atom can interleave, causing the corresponding watches to be called with the same old value but different new values. This contradicts the guarantee that atoms update atomically.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(defn reset-test []&lt;br /&gt;
&amp;nbsp;&amp;nbsp;(let [my-atom (atom :start&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:validator (fn [x] (Thread/sleep 100) true))&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;watch-results (atom [])]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(add-watch my-atom :watcher (fn [k a o n] (swap! watch-results conj [o n])))&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(future (reset! my-atom :next))&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(future (reset! my-atom :next))&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(Thread/sleep 500)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@watch-results))&lt;br /&gt;
&lt;br /&gt;
(reset-test)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Yields [[:start :next] [:start :next]]. Similar behavior can be observed when mixing reset! and swap!.&lt;br /&gt;
&lt;br /&gt;
h2. Expected behavior&lt;br /&gt;
&lt;br /&gt;
Under atomic circumstances, (reset-test) should yield [[:start :next] [:next :next]]. This would &amp;quot;serialize&amp;quot; the resets and give more accurate information to the watches. This is the same behavior one would achieve by using (swap! my-atom (constantly :next)).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(defn swap-test []&lt;br /&gt;
&amp;nbsp;&amp;nbsp;(let [my-atom (atom :start&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:validator (fn [x] (Thread/sleep 100) true))&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;watch-results (atom [])]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(add-watch my-atom :watcher (fn [k a o n] (swap! watch-results conj [o n])))&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(future (swap! my-atom (constantly :next)))&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(future (swap! my-atom (constantly :next)))&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(Thread/sleep 500)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@watch-results))&lt;br /&gt;
&lt;br /&gt;
(swap-test)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Yields [[:start :next] [:next :next]]. The principle of least surprise suggests that these two functions should yield similar output.&lt;br /&gt;
&amp;nbsp;&lt;br /&gt;
h3. Alternative expected behavior&lt;br /&gt;
&lt;br /&gt;
It could be that atoms and reset! do not guarantee serialized updates with respect to calls to watches. In this case, it would be prudent to note this in the docstring for atom.&lt;br /&gt;
&lt;br /&gt;
h2. Analysis&lt;br /&gt;
&lt;br /&gt;
The code for Atom.reset non-atomically reads and sets the internal AtomicReference. This allows for multiple threads to interleave the gets and sets, resulting in holding a stale value when notifying watches. Note that this should not affect the new value, just the old value.&lt;br /&gt;
&lt;br /&gt;
h2. Approach&lt;br /&gt;
&lt;br /&gt;
Inside Atom.reset(), validation should happen first, then a loop calling compareAndSet on the internal state (similar to how it is implemented in swap()) should run until compareAndSet returns true. Note that this is still faster than the swap! constantly pattern shown above, since it only validates once and the tighter loop should have fewer interleavings. But it has the same watch behavior.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
public Object reset(Object newval){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;validate(newval);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for(;;)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Object oldval = state.get();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(state.compareAndSet(oldval, newval))&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;notifyWatches(oldval, newval);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return newval;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;
}&lt;br /&gt;
</description>
<category>Refs, agents, atoms</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/3816/atom-watchers-are-not-atomic-with-respect-to-reset</guid>
<pubDate>Mon, 29 Jun 2015 14:26:56 +0000</pubDate>
</item>
</channel>
</rss>