简体   繁体   English

与Boost.Thread类似的CEvent行为

[英]CEvent-like behaviour with Boost.Thread

Problem in words: 单词问题:

For my application, I have a class that reads from a serial port. 对于我的应用程序,我有一个从串行端口读取的类。 It uses Windows primitives for COM port handling and had a thread for asynchronous reading. 它使用Windows原语进行COM端口处理,并有一个用于异步读取的线程。 I'm trying to convert this away from Windows primitives using Boost libraries such as Boost.Asio and Boost.Thread. 我正在尝试使用Boost.Asio和Boost.Thread等Boost库将其转换为Windows原语。

In the Windows port, my IO thread had several MFC CEvent variables, each of which represented a message: Read requested, Write requested, Read completed, Write completed, IO Cancelled. 在Windows端口中,我的IO线程有几个MFC CEvent变量,每个变量代表一条消息:请求读取,请求写入,读取完成,写入完成,IO取消。 These were waited on with WaitForMultipleObjects. 使用WaitForMultipleObjects等待这些。

The problem I have is that Boost.Thread seems to have analogues for neither CEvent nor WaitForMultipleObjects. 我遇到的问题是Boost.Thread似乎既没有CEvent也没有WaitForMultipleObjects。 The closest I have come is by discarding these and replacing the events with a set of booleans, and then using a condition_variable, which has its notify_all() function called whenever a boolean changes. 我最接近的是丢弃这些并用一组布尔值替换事件,然后使用condition_variable,只要布尔值发生变化就会调用notify_all()函数。

However, boost::condition_variable differs in one critical way from CEvent: if a CEvent is signalled while it is not being waited on, then the next wait on it immediately succeeds. 但是,boost :: condition_variable在与CEvent的一个关键方式上有所不同:如果CEvent在未等待的情况下发出信号,那么下一次等待就会立即成功。 With boost::condition_variable, any notify function is ignored if it is not waiting. 使用boost :: condition_variable,如果没有等待,则忽略任何通知函数。

This means that there is always a gap between checking for the flags and waiting for the condition_variable in which a notification can be lost. 这意味着在检查标志和等待可能丢失通知的condition_variable之间总是存在差距。 This causes the thread to hang. 这会导致线程挂起。

Does anybody know of a solution to this problem? 有人知道这个问题的解决方案吗?

Problem in code: 代码中的问题:

// 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;

        ...
     }
}

How to emulate that in Boost.Thread? 如何在Boost.Thread中模拟它?

As you said, to resemble a windows style event you need a condition-variable plus a boolean flag. 正如您所说,为了类似于Windows样式事件,您需要一个条件变量加上一个布尔标志。 Of course you can combine several boolean flags into one if it satisfies your needs. 当然,如果满足您的需求,您可以将几个布尔标志合并为一个。

However, the problem you mentioned (condition variables never get an active state where wait will immediately return) is usually solved that way: 但是,您提到的问题(条件变量永远不会获得等待将立即返回的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();

By having the second thread to wait until the mutex is unlocked by the thread which will handle the condition you can ensure that each condition is handled. 通过使第二个线程等待直到互斥锁被处理该条件的线程解锁,您可以确保处理每个条件。 (Note: In Java the notify() method has to be called within the lock, which, depending on implementation details, could result in worse performance if done in C++, but ensures that the programmer has at least once thought about how to synchronize the firing of the condition with the receiver). (注意:在Java中,必须在锁中调用notify()方法,根据实现细节,如果在C ++中完成,可能会导致性能下降,但确保程序员至少考虑过如何同步用接收器发射条件)。

The reason why boost.thread does not provide windows-style events (and posix-semaphores, btw) is that those primitives make it quite easy to screw up. boost.thread之所以不提供windows风格的事件(以及posix-semaphores,顺便说一句),原因在于这些原语很容易搞砸。 If you do not plan to port your application to another platform, adapting your application to this different style may not be worth it. 如果您不打算将应用程序移植到另一个平台,那么将您的应用程序调整为这种不同的风格可能是不值得的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM