C++ 便携式C++;11种同时等待套接字和bool变量的方法

C++ 便携式C++;11种同时等待套接字和bool变量的方法,c++,windows,multithreading,sockets,c++11,C++,Windows,Multithreading,Sockets,C++11,我有一个无限循环的线程,它接收和处理来自套接字的数据。我希望该线程阻塞(休眠),直到套接字上的数据可用于读取,或者“exit”布尔变量变为true(由另一个线程设置)。是否可以在不轮询和不使用任何第三方库(sockets库除外)的情况下以可移植的方式实现这一点?如果不能以可移植的方式进行操作,那么在Windows(仍然没有轮询和第三方库)下进行操作的最佳方式是什么 示例代码: bool exit = false; // or "std::atomic<bool> exit" or a

我有一个无限循环的线程,它接收和处理来自套接字的数据。我希望该线程阻塞(休眠),直到套接字上的数据可用于读取,或者“exit”布尔变量变为true(由另一个线程设置)。是否可以在不轮询和不使用任何第三方库(sockets库除外)的情况下以可移植的方式实现这一点?如果不能以可移植的方式进行操作,那么在Windows(仍然没有轮询和第三方库)下进行操作的最佳方式是什么

示例代码:

bool exit = false; // or "std::atomic<bool> exit" or anything else
void fn()
{
    SOCKET s;
    // init socket, establish connection, etc
    for(;;)
    {
        // This thread goes to wait (blocks) until data becomes available on socket
        // OR exit var is set to true (by a different thread) - how?
        if(exit) break;
        // receive and process data from socket
    }
}
bool exit=false;//或者“std::atomic exit”或者其他任何东西
无效fn()
{
插座;
//初始化套接字、建立连接等
对于(;;)
{
//此线程将等待(阻塞),直到套接字上的数据可用
//或者exit var设置为true(由另一个线程执行)-如何设置?
如果(退出)中断;
//从套接字接收和处理数据
}
}

设置消息队列

这些消息的形式为“请退出”或“DataOnSocket”

当队列中出现任何内容,处理队列,然后再次等待队列时,您的线程或任务将被激活。如果它得到“请退出”,它就会开始清理

您可能需要在条件变量和套接字上等待不同的线程/任务,以便将信息传递到统一队列

我之所以说“线程或任务”,是因为有一个完整的线程专门用于等待是过分的。遗憾的是,C++11线程非常完美

基本上,此解决方案允许线程通过将等待每个事件的任务委托给其他线程来等待多个事件,而其他线程“在管道上”发送通知。您可以想象创建一个公共基础结构,其中希望等待多个对象的线程告诉调度中心它正在等待什么,然后等待自己的条件变量

调度中心会等待您的线程想要等待的每一件事情,当它们发生时,调度中心会继续找出应该通知哪些线程,然后通知它们


离理想还差得很远,但它确实允许您在完全符合标准的C++11环境中实现这一点。并且可以为您提供一个类似于windows中“等待多个对象”的界面。(事实上,在windows上,如果您的C++11同步原语的
本机句柄
是可接受的,那么您可以省去很多机器)。

您所要求的需要一个统一的事件处理框架。此时,即使是boost也不能提供这种功能。对于windows,答案是
WaitForMultipleObjects
afaik.btw,您必须准确定义“无轮询”的含义,因为
WaitForMultipleObjects
对我来说是轮询的一种形式(几乎所有等待事件的函数都是这样的)@didierc我担心
WaitForMultipleObjects
是唯一的解决方案-当您实际上需要任何多线程时,所有花哨的C++11多线程功能都是无用的:(而且“没有轮询”意味着在我的代码中没有轮询-如果操作系统特定的例程这样做-这很好-我相信它会比我自己的代码中做得更好10倍。如果你以阻塞方式等待,那么你通常也不能等待bool。但是你可以做的是在阻塞等待之前检查bool。为了取消等待,你可以添加一个虚拟管道(或类似)这种方法适用于大多数
选择
、boost.asio并等待多种样式的框架。正如@John5342可能暗示的那样,另一种方法是将cond-var模拟为写入描述符,从而允许对常规文件和cond-var进行轮询。考虑到这一点,
原子的
并不是为等待而设计的,所以我想你指的是cond var。这听起来不错,但如果有一个优先级队列,这样退出请求就可以推到前面,可能会更好吗?@Yakk我不明白你的建议如何解决在套接字上以某种方式向等待
FD\u READ
通知的线程发送信号的问题(使用
选择
WSAWaitForMultipleEvents
等)退出。@PowerGamer线程不在套接字上等待:线程在框架上等待,框架上有一个工作线程在套接字上等待,另一个工作线程在另一个信号上等待,当其中一个信号到达时,它会通过框架转发它们。在某些情况下,与非框架等待事件的互操作是不可能的(因为不可能保证只使用信号或套接字消息,但不能同时使用这两种消息),也不允许在框架外公开C++11线程原语,但它应该可以工作。C++11线程在这一点上过于原始。@Yakk Ok,那么如何给“等待套接字的工作线程”发信号呢要退出?@powergamer,对于非C++11事件,您必须能够向等待的线程发送信号。对于套接字,您创建自己的受控套接字,并让线程在套接字和外部套接字上同时等待。对于等待不受控制的windows事件,同样地,创建一个由您控制的windows事件,然后让等待的线程在多个对象上等待。对于C++11事件代码,还要确保框架能够唤醒线程,可能是通过触发有问题的事件本身。是的,它最终会变得非常混乱。