有没有办法阻塞单个线程,直到信号量或input事件?

我将同时编写一个来自TCP / IP连接和共享内存队列的程序处理请求。 这意味着程序应该阻塞,直到队列中有请求或套接字上有input。 然后它将处理请求并继续。 有没有办法做到这一点在单个线程? 我的意思是某种select同时使用信号量和套接字。 在我的情况下,延迟是很重要的,我也不想忙于等待。 该程序将在Windows上运行。 谢谢。

等待几种可能发生的事情之一的Windows方式是WaitForMultipleObjectsEx 。 给它一个可以变成“信号”的Windows“句柄”数组(这些句柄称为同步对象),当它们中的任何一个被发信号时,函数返回并告诉你它是哪一个。

问题是,在WinSock库中实现的套接字不是Windows句柄。 你不能把它放到WaitForMultipleObjectsEx数组中。

幸运的是,WinSock提供了一个函数WSAEventSelect ,可以将套接字链接到Windows事件对象。 事件对象是最简单的同步对象类型。 在这种情况下,当套接字准备被读取( FD_READ )时,您会要求它发出事件对象的信号。 然后你会把事件对象放到数组旁边。

Windows Semaphore已经是一个同步对象 – 请参阅MSDN中的CreateSemaphore 。 当它的计数大于0时,就会发出信号(这是你所期望的信号量)。

如果你不明白同步对象的整个思想,阅读MSDN没有帮助,我会推荐Jim Beveridge的书在Win32多线程应用程序 。 这是一本老书,所以它没有套接字或信号量,但它解释了如何使用事件对象,互斥体和一般的WaitForMultipleObjects ; 那么socket和信号量就会很容易理解。

一种方法是使用重叠的I / O并使用hEvent机制来发信号通知I / O完成。 然后,您可以使用WaitForMultipleObjects() API等待队列信号和hEvent / s。

另一种方法是使用重叠的I / O和完成例程。 然后,您可以使用WaitForSingleObectEx() API在bAlertable参数设置为true的情况下等待信号量,以便线程可以处理排队的完成例程,例如:

 while(WAIT_IO_COMPLETION!=WaitForSingleObjectEx(queueSema,INFINITE,true)){ [deque object and handle it]; }; 

这两种方案都允许您设置超时轮询服务器以保持连接打开和/或检查是否关闭。

Libevent是一种抽象出I / O事件的方法,它有一种手动触发事件的方法。

使用libevent设置基于文件的事件如下所示(从文档复制):

 void callback_func(evutil_socket_t fd, short what, void *arg) { ... } struct event *ev1, *ev2; struct event_base *base = event_base_new(); /* The caller has already set up fd1, fd2 somehow, and make them nonblocking. */ ev1 = event_new(base, fd1, EV_TIMEOUT|EV_READ|EV_PERSIST, callback_func, (char*)"Reading event"); ev2 = event_new(base, fd2, EV_WRITE|EV_PERSIST, callback_func, (char*)"Writing event"); event_add(ev1, NULL); event_add(ev2, NULL); 

如果你想创建一个不与任何文件描述符关联的事件,则传递一个fd:

 ev = event_new(base, -1, EV_PERSIST | EV_READ, callback_func, NULL); event_add(ev, NULL); 

现在,不是提高信号量,而是触发事件:

 event_active(ev, EV_WRITE, 0);