代码之家  ›  专栏  ›  技术社区  ›  doron

选择/轮询循环中的回调和延迟

  •  0
  • doron  · 技术社区  · 14 年前

    在编写可以在同一线程中为多个客户机提供服务的服务器时,可以使用轮询/选择。但是,选择并轮询需要一个文件描述符才能工作。因此,我不确定如何执行简单的异步操作,比如实现一个简单的回调来中断长时间运行的操作,或者在不退出select/poll循环的情况下实现一个延迟的回调。这是怎么回事?理想情况下,我希望在不使用生成新线程的情况下执行此操作。

    简言之,我正在寻找一种机制,用它我可以执行所有异步操作。窗户 WaitForMultipleObjects 或塞班 TRequestStatus 似乎更适合于广义异步操作。

    4 回复  |  直到 14 年前
        1
  •  1
  •   fizzer    14 年前

    对于任意回调,请维护posix管道(请参见管道(2))。当您要执行延迟调用时,请将一个由函数指针和可选上下文指针组成的结构写入到写入端。读取端只是选择的另一个输入。如果选择可读,则读取相同的结构,并使用上下文作为参数调用函数。

    对于定时回调,按到期时间顺序维护列表。列表中的条目是结构,例如“到期时间”(作为上一次回调后的间隔);函数指针;可选上下文指针。如果此列表为空,请在select()中永久阻止。否则,在第一个事件到期时超时。在每次调用选择之前,重新计算第一个事件的到期时间。

    在合理的界面后面隐藏细节。

        2
  •  0
  •   qrdl    14 年前

    select() poll() 是系统调用——这意味着你的程序正在调用操作系统内核来做一些事情,而你的程序在等待从内核返回时什么也不能做,除非你使用其他线程。

    虽然 选择() 污染() 用于异步I/O,这些函数(SysCalls)不是异步的-它们将阻塞(除非您指定一些超时),直到您正在监视的描述符出现问题为止。

    最好的策略是逐时检查描述符(指定小的超时值),如果没有什么,则在空闲时间做您想做的,否则处理I/O。

        3
  •  0
  •   Richard Pennington    14 年前

    您可以利用select()或poll()的超时时间定期执行后台操作:

    for ( ;; ) {
       ...
       int fds = select(<fds and timeout>);
       if (fds < 0) {
           <error occured>
       } else if if (fds == 0) {
           <handle timeout, do some background work.>
       } else {
           <handle the active file descriptors>
       }
     }
    
        4
  •  0
  •   doron    14 年前

    对于使用select循环的即时回调,可以使用像/dev/zero这样始终处于活动状态的特殊文件之一。将允许选择退出,但也将允许其他文件变为活动状态。

    对于定时延迟,我只能在选择时使用超时。

    以上两项都不太好,请发送更好的答案。