如何围绕阻塞呼叫实现定时等待?

时间:2010-11-20 10:29:54

标签: c++ multithreading boost timeout boost-thread

所以,情况就是这样。我有一个C ++库正在进行一些进程间通信,其中wait()函数阻塞并等待传入​​的消息。困难在于我需要一个定时等待,如果在指定的时间内没有收到任何消息,它将返回状态值。

最优雅的解决方案可能是重写库以向其API添加定时等待,但为了这个问题,我认为这是不可行的。 (实际上,它看起来很难,所以我想知道另一个选项是什么。)

以下是我在伪代码中使用忙等待循环执行此操作的方法:

while(message == false && current_time - start_time < timeout)
{
  if (Listener.new_message()) then message = true;
}
但是,我不希望忙着等待处理器周期。而且我也不想在循环中添加sleep()调用以避免处理器负载,因为这意味着响应更慢。我希望通过适当的块和中断来实现这一点。如果更好的解决方案涉及线程(似乎很可能),我们已经在使用boost::thread,所以我更愿意使用它。

我发布这个问题是因为这似乎是一种明确的“最佳实践”正确答案的情况,因为这是一种非常常见的模式。什么是正确的方法?

编辑添加:我担心的很大一部分是,这是程序中的一个位置,对于避免竞争条件或内存泄漏而言,性能至关重要且至关重要。因此,虽然“使用两个线程和一个计时器”是有用的建议,但我仍然试图找出如何以安全和正确的方式实际实现它,我可以很容易地看到自己在我的代码中犯了新手错误甚至不知道我做过。因此,非常感谢一些实际的示例代码!

另外,我关注多线程解决方案:如果我使用“将阻塞调用放在第二个线程中并对该线程执行timed-wait”方法,那么如果被阻塞,第二个线程会发生什么电话从不回来?我知道第一个线程中的定时等待将返回,我会看到没有回答已经发生并继续进行,但我是否“泄露”了一个将永远处于阻塞状态的线程?有什么办法可以避免吗? (有没有办法避免这种情况并避免泄漏第二个线程的内存?)如果阻塞调用没有返回,我需要一个完整的解决方案来避免泄漏。

6 个答案:

答案 0 :(得分:1)

您想要的是select(2),具体取决于您定位的操作系统。

答案 1 :(得分:1)

听起来你需要一个'监视器',能够通过共享互斥锁(通常)向线程发送资源可用性信号。在Boost.Thread中,condition_variable可以完成这项任务。

答案 2 :(得分:1)

您可能希望查看timed locks:您的阻止方法可以在开始等待之前获取锁定,并在数据可用时立即释放它。然后,您可以尝试在定时等待方法中获取锁定(超时)。

答案 3 :(得分:1)

将阻塞调用封装在单独的线程中。在该线程中有一个由条件变量保护的中间消息缓冲区(如前所述)。使主线程定时 - 等待该条件变量。如果满足条件,则接收中间存储的消息。

所以基本上在API和你的应用程序之间放置一个能够定时等待的新层。适配器模式。

答案 4 :(得分:1)

您可以使用sigaction(2)alarm(2),它们都是POSIX。您使用sigaction为超时设置回调操作,然后使用alarm设置计时器,然后进行阻止调用。如果阻塞调用未在您选择的超时内完成,则会中断阻塞调用(以秒为单位;如果您需要更精细的粒度,则可以使用setitimer(2))。

请注意,C中的信号有点毛茸茸,并且对信号处理程序中的操作有相当严格的限制。

此页面非常有用且相当简洁: http://www.gnu.org/s/libc/manual/html_node/Setting-an-Alarm.html

答案 5 :(得分:0)

关于

  

如果被阻止的呼叫永远不会返回,第二个线程会发生什么?

我相信,如果没有来自被调用函数(或库)的合作,你可以做 nothing 来恢复干净。 &#39;干净地&#39;意味着清理该线程拥有的所有资源,包括内存,其他线程,锁,文件,文件锁,套接字,GPU资源...... Un -cleanly,你确实可以杀死失控的线程。