我有一个线程可以监听单个UDP套接字,但也需要偶尔醒来才能执行其他任务。这些任务是由时间的推移或其他线程上的活动触发的。我目前的设计是使用select()超时值作为调度计时器,并在需要从另一个线程唤醒数据包时将数据包写入套接字(回环)地址。
然而,Apple表示,select()超时不应该被用于每秒唤醒超过几次。而且,在实践中,我发现它们可能被延迟100毫秒或更多,而我想要10-20毫秒的分辨率。它们只是试图阻止cpu密集的轮询,还是使用select()本身有问题。有没有更好的方法?
用kqueue/kevent替换select会有帮助吗?或者,创建一个专用的调度线程,使用mach_wait_until()来处理定时器,然后写入套接字来唤醒网络线程?或者,在专用线程中完成所有的工作,并让网络线程将传入的数据排队到它?
发布于 2013-10-02 02:19:08
我对这种方法有些不快。为什么在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
});
}
}
然后,您可以使用定时器调度源运行定期任务。
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()。
https://stackoverflow.com/questions/19128612
复制相似问题