在编写可以在同一个线程中为多个客户端提供服务的服务器时,可以使用poll / select。 select和poll,但需要一个文件描述符才能工作。出于这个原因,我不确定如何执行简单的异步操作,例如实现一个简单的回调来分解长时间运行的操作或延迟回调而不退出select / poll循环。怎么去做这个?理想情况下,我想这样做而不需要产生新的线程。
简而言之,我正在寻找一种可以执行所有异步操作的机制。窗口WaitForMultipleObjects
或Symbian TRequestStatus
似乎更适合广义异步操作。
答案 0 :(得分:1)
对于任意回调,维护一个POSIX管道(参见pipe(2))。如果要执行延迟调用,请将包含函数指针和可选上下文指针的结构写入写端。读取结束只是select的另一个输入。如果它选择可读,则读取相同的结构,并以上下文作为参数调用该函数。
对于定时回调,按照适当的时间顺序维护列表。列表中的条目是例如{到期时间(自上一次回调以来的间隔);函数指针;可选的上下文指针}。如果此列表为空,则在select()中永久阻止。否则,在第一个事件到期时超时。在每次调用之前,重新计算第一个事件的到期时间。
隐藏合理界面背后的细节。
答案 1 :(得分:0)
select()
和poll()
是系统调用 - 这意味着你的程序正在调用操作系统内核做某事而你的程序在等待从内核返回时什么都不做,除非你使用其他线程。
虽然select()
和poll()
用于异步I / O,但这些函数(系统调用)不是异步的 - 它们将阻塞(除非您指定一些超时),直到描述符发生了某些事情为止你在看。
最佳策略是不时检查描述符(指定小超时值),如果没有,请在空闲时执行您想要的操作,否则处理I / O.
答案 2 :(得分:0)
您可以利用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>
}
}
答案 3 :(得分:0)
对于使用select循环的立即回调,可以使用其中一个始终处于活动状态的特殊文件,如/ dev / zero。将允许尽快选择退出,但也允许其他文件变为活动状态。
对于定时延迟,我只能选择使用超时。
上述两种情况都不太好,所以请发送更好的答案。