单词中的问题:
对于我的应用程序,我有一个从串口读取的类。它使用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中模拟它?
答案 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,顺便说一句)的原因是这些原语很容易搞砸。如果您不打算将应用程序移植到另一个平台,那么将您的应用程序调整为这种不同的风格可能是不值得的。