如何设置并发::事件对象,仅当它现在未处于信号状态时

How to set Concurrency::event object only if it is not in signaled state now?

本文关键字:于信号 状态 信号 设置 何设置 并发 事件 对象      更新时间:2023-10-16

在我的代码中,只有当特殊事件未处于信号状态时,某些并发工作任务才应该开始工作。代码示例:

tasks.run([&](){
   if (event.wait(0)!=0)
   {
      event.set();
      // work code ...
   }
})

此类任务可能有许多实例,只有一个实例应该工作。但是wait()和set()是不同的方法,代码不是原子的。因此,可能是两个或多个任务实例开始工作的情况。我如何测试事件的信号状态并仅在非信号时锁定它,并以原子方式进行?

看起来你可以使用mutex::try_lock

代码应如下所示:

tasks.run([&](){   if (event.wait(0)!=0 && mutex.try_lock()) {      event.set();      mutex.unlock();      工作代码...   }})

不要忘记确保 event.set() 不会抛出异常,否则需要额外的努力来使此代码异常安全。

也许你应该把整个包装成 while (true) 来捕获"假阳性"案例,就像这样:

tasks.run([&](){   而(真) {      if (event.wait(0)!=0 && mutex.try_lock()) {         event.set();         mutex.unlock();         工作代码...         破;      }   }});

因此,未能获取锁的任务将返回到等待状态。

我的解决方案:

安全设置事件类:

namespace Concurrency {
class event_safe : public event
{
public:
    inline bool try_set()
    {
        critical_section::scoped_lock locker(m_lock);
        bool bRes = (wait(0)==Concurrency::COOPERATIVE_WAIT_TIMEOUT);
        if (bRes)
            set();
        return bRes;
    }
protected:
    critical_section m_lock;
};
}

工作代码:

tasks.run([&](){
   if (event.try_set()) {
      // work code ...
   }
})