itok's Lab

昔の開発ネタを記録として残してます

CFRunLoopとCFRunLoopSourceの簡単サンプル

RunLoop のドキュメントを見ても、載っているサンプルは CFRunLoopTimer なので、CFRunLoopSource を使った簡単サンプルでも。

CFRunLoopSourceRef src;
CFRunLoopRef loop;
// (1)
void thread() {
    CFRunLoopSourceContext context = {0};
    context.perform = &performCallback;
    src = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
    loop = CFRunLoopGetCurrent();
    CFRunLoopAddSource(loop, src, kCFRunLoopCommonModes);
    CFRunLoopRun();
}
// (2)
void signal() {
    CFRunLoopSourceSignal(src);
    CFRunLoopWakeUp(loop);
}
// (3)
void performCallback(void* info) {
// do something
}

これだけではなんですので、簡単に解説を。

(1) はいわばスレッドのエントリポイントでの処理。そのスレッドにおける RunLoop に Source を追加しています。これで Source にシグナルが送られれば RunLoop が動き出すというわけ。

で、(2) はそのシグナルを送る側の話。CFRunLoopSourceSignal だけでもよさそうだけれど、今は CFRunLoopRun で際限なく待たせている形になっているので、それを起こしてあげないとシグナルが到達しません。なので、CFRunLoopWakeUp も必要。(CFRunLoopRunInMode を使っている場合でも、すぐにシグナルを処理して欲しい場合は明示的に起こしてあげましょう)

(3) はシグナルが送られた時のコールバック。ここに実際の処理を書いていきます。

とまあ、これだけで簡単なスレッド間のメッセージのやり取りが実現します。