Rhino DSL 中的竞争条件?
在我当前的项目中,我正在使用 Boo/Rhino DSL(顺便说一句,这是多么棒的事情啊)。
在深入研究代码时,我遇到了以下代码:
engine.Cache.WriteLock( () =>
{
engine.Storage.NotifyOnChange(urls, delegate(string invalidatedUrl)
{
engine.Cache.Remove(invalidatedUrl);
if (!standAloneCompilation.Contains(invalidatedUrl))
standAloneCompilation.Add(invalidatedUrl);
});
});
这里的意图非常明确:当从其中删除 url 时,必须保护 engine.Cache
免受竞争条件的影响。我在这里看到的问题是,真正受保护的是对 Storage.NotifyOnChange
的调用,而不是 Cache.Remove
。
NotifyOnChange
所做的就是获取提供的委托并将其作为事件处理程序附加到它创建的“FileWatcher”。因此,这里的写锁不是保护 Cache.Remove ,而是保护创建 FileWatcher ,并使 Cache.Remove 不受保护。
我非常尊重 Boo 和 Rhino,这让我想知道 - 这里是否遗漏了一些东西?或者写锁应该真正移动到委托内部?
如果您想知道,这里是 NotifyOnChange 代码:
public virtual void NotifyOnChange(IEnumerable<string> urls, Action<string> action)
{
lock (pathToFileWatchers)
{
string[] commonPaths = GatherCommonPaths(urls);
foreach (string path in commonPaths)
{
FileSystemWatcher watcher;
if(pathToFileWatchers.TryGetValue(path, out watcher)==false)
{
pathToFileWatchers[path] = watcher = new FileSystemWatcher(path, FileNameFormat);
watcher.EnableRaisingEvents = true;
}
watcher.Changed += delegate(object sender, FileSystemEventArgs e)
{
action(e.FullPath);
};
}
}
}
In my current project I am working with Boo/Rhino DSL (what a great thing(s) by the way).
In digging in the code I came across the following piece of code:
engine.Cache.WriteLock( () =>
{
engine.Storage.NotifyOnChange(urls, delegate(string invalidatedUrl)
{
engine.Cache.Remove(invalidatedUrl);
if (!standAloneCompilation.Contains(invalidatedUrl))
standAloneCompilation.Add(invalidatedUrl);
});
});
the intention here is pretty clear: the engine.Cache
has to be protected from race condition when a url is removed from it. The problem I see here is that what is really protected is a call to the Storage.NotifyOnChange
- not the Cache.Remove
.
And all NotifyOnChange
does is taking the supplied delegate and attach it as an event handler to the 'FileWatcher' it creates. So instead of protecting the Cache.Remove
the write lock here protects creating the the FileWatcher, and leaves the Cache.Remove
unprotected.
I have great respect to both Boo and Rhino, which makes me wonder - am missing something here? or the write lock should be really moved inside the delegate?
Here is the NotifyOnChange code if you are wondering:
public virtual void NotifyOnChange(IEnumerable<string> urls, Action<string> action)
{
lock (pathToFileWatchers)
{
string[] commonPaths = GatherCommonPaths(urls);
foreach (string path in commonPaths)
{
FileSystemWatcher watcher;
if(pathToFileWatchers.TryGetValue(path, out watcher)==false)
{
pathToFileWatchers[path] = watcher = new FileSystemWatcher(path, FileNameFormat);
watcher.EnableRaisingEvents = true;
}
watcher.Changed += delegate(object sender, FileSystemEventArgs e)
{
action(e.FullPath);
};
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论