比较clojure.lang.Ref
和clojure.lang.Atom
的源代码,我发现它们都继承自clojure.lang.ARef
。
在clojure.lang.ARef
中有一个函数notifyWatches
,让所有监视函数都知道已经进行了更改。
swap!
中的reset!
和clojure.lang.Atom
函数在其实施中调用notifyWatches
。
例如
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;
}
}
}
但是,当我在notifyWatches
中搜索clojure.lang.Ref
时,它什么都没有。 alter
函数看起来像这样。
public Object alter(IFn fn, ISeq args) {
LockingTransaction t = LockingTransaction.getEx();
return t.doSet(this, fn.applyTo(RT.cons(t.doGet(this), args)));
}
如果没有方法调用notifyWatches,那么ref的所有watch函数如何得到通知?
答案 0 :(得分:3)
您要查找的notifyWatches
来自run
类的LockingTransaction
方法。
对交易的更改发生在交易中。请注意,对doSet
LockingTransaction
方法的调用已通过this
(对Ref的引用)。在事务中将应用的更改由doSet
方法确定,但该更改在run
LockingTransaction
方法中生效。成功运行交易时notifyWatches
使用对doSet
记录的参考号的引用进行调用。
答案 1 :(得分:2)
clojure.lang.Ref扩展clojure.lang.ARef the watches并提供notifyWatches方法