代码之家  ›  专栏  ›  技术社区  ›  Brooks Moses

如何在阻塞调用周围实现定时等待?

  •  3
  • Brooks Moses  · 技术社区  · 14 年前

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

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

    下面是我如何处理繁忙的等待循环(伪代码):

    while(message == false && current_time - start_time < timeout)
    {
      if (Listener.new_message()) then message = true;
    }
    

    不过,我不希望繁忙的等待占用处理器周期。我也不想只增加一个 sleep() 在循环中调用以避免处理器负载,因为这意味着响应较慢。我想要一些适当的块和中断来完成这项工作。如果更好的解决方案涉及线程(这似乎是可能的),我们已经在使用 boost::thread 所以我更喜欢用那个。

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

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

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

    6 回复  |  直到 6 年前
        1
  •  1
  •   John Zwinck    14 年前

    你可以用 sigaction(2) alarm(2) ,两者都是posix。使用sigaction为超时设置回调操作,然后使用alarm设置计时器,然后进行阻塞调用。如果阻塞调用没有在您选择的超时内完成(以秒为单位;如果您需要更细的粒度,可以使用 setitimer(2) )

    请注意,C中的信号有点多毛,对于您可以在信号处理程序中执行的操作有相当严格的限制。

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

        2
  •  1
  •   Cactus    14 年前

    你想要的是 select(2) ,取决于您要瞄准的操作系统。

        3
  •  1
  •   Paul Michalik    14 年前

    听起来您需要一个“监视器”,能够通过一个共享的互斥(通常)向线程发送资源可用性的信号。在增压中。螺纹A condition_variable 能胜任这项工作。

        4
  •  1
  •   Philipp    14 年前

    你可能想看看 timed locks :您的阻塞方法可以在开始等待前获取锁,并在数据可用时立即释放锁。然后,您可以尝试在timed wait方法中获取锁(超时)。

        5
  •  1
  •   LumpN    14 年前

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

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

        6
  •  0
  •   Pablo H    6 年前

    关于

    如果被阻塞的调用从未返回,那么第二个线程会发生什么情况?

    我相信有 没有什么 你可以做恢复 干净利落 没有来自被调用函数(或库)的协作。“cleanly”指清除该线程拥有的所有资源,包括内存、其他线程、锁、文件、文件锁、套接字、GPU资源… 联合国 -很明显,你确实可以杀死失控的线程。