我有一个侦听单个UDP套接字的线程,但也需要偶尔唤醒以执行其他任务。这些任务由时间的推移或其他线程上的活动触发。我目前的设计是使用select()超时值作为调度计时器,并在需要从另一个线程唤醒时将数据包写入套接字(环回)地址。
然而,Apple文档称,select()超时不应该用于每秒唤醒超过几次。而且,在实践中,我发现它们可能会延迟100毫秒或更长,而我希望分辨率为10-20毫秒。他们只是试图阻止cpu密集型轮询,或者使用select()本身是否有问题。有更好的方法吗?
用kqueue / kevent替换select会有帮助吗?或者,创建一个专用的调度线程,用mach_wait_until()来处理定时器,然后写入套接字以唤醒网络线程?或者,在专用线程中完成所有工作,并让网络线程将传入数据队列到它?
答案 0 :(得分:0)
有些东西让我对这种方法感到不满。你为什么在select()线程上发生任何事情?
如果你需要一个专用于等待传入数据包的线程,它们会使该线程尽可能地等待。
while (1) {
int numsockets = select(…);
if (numsockets > 0) {
// Read data (only drain the socket)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Process data
});
}
}
然后,您可以使用timer dispatch sources运行定期任务。
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
dispatch_source_set_event_handler(source, ^{
// Periodic process data
});
uint64_t nsec = 0.001 * NSEC_PER_SEC;
dispatch_source_set_timer(source, dispatch_time(DISPATCH_TIME_NOW, nsec), nsec, 0);
dispatch_resume(source);
我不知道,但我被告知您甚至可以使用调度源来替换select()。