Reputation: 14258
Comparing the source code of clojure.lang.Ref
and clojure.lang.Atom
, I see that they both inherit from clojure.lang.ARef
.
In clojure.lang.ARef
there is a function notifyWatches
which lets all the watch function know that a change has been made.
the swap!
and reset!
functions in clojure.lang.Atom
calls notifyWatches
in its implementation.
eg.
public Object swap(IFn f) {
for(; ;)
{
Object v = deref();
Object newv = f.invoke(v);
validate(newv);
if(state.compareAndSet(v, newv))
{
notifyWatches(v, newv);
return newv;
}
}
}
However, when I do a search for notifyWatches
in clojure.lang.Ref
, it comes up with nothing. The alter
function looks like this.
public Object alter(IFn fn, ISeq args) {
LockingTransaction t = LockingTransaction.getEx();
return t.doSet(this, fn.applyTo(RT.cons(t.doGet(this), args)));
}
How do all the watch functions of a ref get notified if none of the methods are calling notifyWatches?
Upvotes: 3
Views: 386
Reputation: 8344
The call to notifyWatches
you are looking for occurs in the run
method of the LockingTransaction
class.
Changes to refs happen in transactions. Note that the call to the doSet
method of LockingTransaction
is passed this
(a reference to the Ref). The change that will be applied within the transaction is established by the doSet
method but that change is effected within the run
method of LockingTransaction
. When the transaction is run successfully notifyWatches
is called using the reference to the Ref recorded by doSet
.
Upvotes: 3
Reputation: 91577
clojure.lang.Ref extends clojure.lang.ARef which has the watches and provides the notifyWatches method
Upvotes: 2