iOS select / kqueue / kevent与mach_wait_until调度

时间:2013-10-02 01:26:43

标签: ios multithreading sockets

我有一个侦听单个UDP套接字的线程,但也需要偶尔唤醒以执行其他任务。这些任务由时间的推移或其他线程上的活动触发。我目前的设计是使用select()超时值作为调度计时器,并在需要从另一个线程唤醒时将数据包写入套接字(环回)地址。

然而,Apple文档称,select()超时不应该用于每秒唤醒超过几次。而且,在实践中,我发现它们可能会延迟100毫秒或更长,而我希望分辨率为10-20毫秒。他们只是试图阻止cpu密集型轮询,或者使用select()本身是否有问题。有更好的方法吗?

用kqueue / kevent替换select会有帮助吗?或者,创建一个专用的调度线程,用mach_wait_until()来处理定时器,然后写入套接字以唤醒网络线程?或者,在专用线程中完成所有工作,并让网络线程将传入数据队列到它?

1 个答案:

答案 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()。