Welcome! Please see the About page for a little more info on how this works.

0 votes
ago in Refs, agents, atoms by

I'm having trouble understand how await works on agents.
From the doc string reads

Blocks the current thread (indefinitely!) until all actions dispatched
thus far, from this thread or agent, to the agent(s) have occurred.

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 send something then I can await for it to finish.

However, it seems like a watch will also triggers for some reason...

(def bond (agent nil))

(add-watch bond
           :test
           (fn [_,_,_,_]
             (println "pew pew")))

(await bond)

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

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

(await bond)
(await bond)
(await bond)
(await bond)

add-watch docs read

Whenever the reference's state might have been changed, any registered watches will have their functions called.

However here the agent's state hasn't changed and yet it's fired

What's going on?

1 Answer

+1 vote
ago by

If you look at the source of await, you'll see it send a function to each agent provided as arguments, that counts down a latch (and returns the agent's value).

A watch is triggered every time a fn is sent to that agent -- because any fn "might have [..] changed" the state.

ago by
edited ago by
oh huh.. the implementation makes sense but that sounds like a bug..? Or at least a mismatch with the documentation - yeah? Furthermore I'm not sure how I can distinguish between the two in a `watch` (looks identical to sending the agent's current value)

It also doesn't seem to handle "all actions dispatched
thus far, from this thread or agent" if the agent does something `async`
ago by
? The clojure.core.async kind of "async" is beyond the scope of "actions dispatched... to the agent(s)".
ago by
sorry, overloaded term. In my use case specifically the agent sends a value to another agent. You can't await inside the agent action, and you can't await the first agent to wait for the chain to execute. So there is no way to wait for the second agent without explicitly tracking everything from the main thread.
...