Rhino DSL 中的竞争条件?

发布于 2024-10-03 08:13:49 字数 1737 浏览 6 评论 0原文

在我当前的项目中,我正在使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文