与Boost.Thread类似的CEvent行为

时间:2009-08-30 14:42:03

标签: c++ multithreading boost waitformultipleobjects

单词中的问题:

对于我的应用程序,我有一个从串口读取的类。它使用Windows原语进行COM端口处理,并有一个用于异步读取的线程。我正在尝试使用Boost库(如Boost.Asio和Boost.Thread)将其转换为Windows原语。

在Windows端口中,我的IO线程有几个MFC CEvent变量,每个变量代表一条消息:请求读取,请求写入,读取完成,写入完成,IO取消。使用WaitForMultipleObjects等待这些。

我遇到的问题是Boost.Thread似乎既没有CEvent也没有WaitForMultipleObjects。我最接近的是丢弃这些并用一组布尔替换事件,然后使用condition_variable,只要布尔值发生变化,就会调用notify_all()函数。

然而,boost :: condition_variable在一个关键方面与CEvent不同:如果在没有等待的情况下发出CEvent信号,那么下一次等待就会立即成功。使用boost :: condition_variable,如果没有等待,则忽略任何通知函数。

这意味着在检查标志和等待可能丢失通知的condition_variable之间总是存在差距。这会导致线程挂起。

有人知道这个问题的解决方案吗?

代码中的问题:

// Old IO Thread
CEvent msg_cancel;
CEvent msg_read_req;
CEvent msg_write_req;
CEvent msg_read_comp;
CEvent msg_write_comp;

CEvent events[] = { 
    msg_cancel, 
    msg_read_req, 
    msg_write_req,
    msg_read_comp,
    msg_write_comp
};

bool cancel = false;

while (!cancel)
{
    switch(WaitForMultipleObjects(5, events, false, INFINITE))
    {
        case WAIT_OBJECT_0 :
            // msg_cancel
            cancel = true;
            break;

        ...
     }
}

如何在Boost.Thread中模拟它?

1 个答案:

答案 0 :(得分:3)

正如你所说,为了类似于windows风格的事件,你需要一个条件变量加上一个布尔标志。当然,如果满足您的需求,您可以将几个布尔标志组合成一个。

但是,您提到的问题(条件变量永远不会得到等待将立即返回的active状态)通常会以这种方式解决:

condition-variable
mutex

main-thread:
  lock(mutex) { start condition-signaling-thread }
  while(some predicate) {
    condition-variable.wait(mutex)
    do-stuff
  }

condition-signaling-thread:
  loop:      
    lock(mutex) {
      do-whatever
    }
    condition-variable.notify();

通过使第二个线程等待直到互斥锁被处理该条件的线程解锁,您可以确保处理每个条件。 (注意:在Java中,必须在锁中调用notify()方法,根据实现细节,如果在C ++中完成,可能会导致性能下降,但确保程序员至少考虑过如何同步用接收器发射条件。

boost.thread不提供windows风格事件(以及posix-semaphores,顺便说一句)的原因是这些原语很容易搞砸。如果您不打算将应用程序移植到另一个平台,那么将您的应用程序调整为这种不同的风格可能是不值得的。