如果现在没有处于信号状态,如何设置Concurrency :: event对象?

时间:2014-01-14 10:58:04

标签: c++ concurrency

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

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

      // work code ...
   }
})

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

2 个答案:

答案 0 :(得分:1)

您似乎可以使用mutex::try_lock

代码应如下所示:

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

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

可能是你应该把整个包裹起来(true)来捕捉'假阳性'的情况,就像那样:

tasks.run([&](){
   while(true) {
      if (event.wait(0)!=0 && mutex.try_lock()) {
         event.set();
         mutex.unlock();
         // work code ...
         break;
      }
   }
});

因此未能获得锁定的任务将返回等待状态。

答案 1 :(得分:0)

我的解决方案:

安全设置事件类:

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 ...
   }
})