Objective-C スレッドと libuv スレッドとのやりとり
libuv 専用スレッドと通常の Objective-C スレッドとのやりとりの仕方、ついでに書いておく。
tl;dr - libuv スレッドから Objective-C スレッドに対して何か送るときは Objective-C の作法がそのまま使える。逆は uv_async
を使う
libuv スレッドから Objective-C スレッド
これは Objective-C の世界の作法がそのまま使える。
iOS4+ と OSX 10.6+ であれば GCD で、
dispatch_async(dispatch_get_main_queue(), ^{
// ここはメインスレッド
});
のようなのを書くだけでメインスレッドの動作を定義できるから、そこでメソッド呼ぶなり Notification を発行するなりすれば良いので楽ちん。
それ以下の環境だったら performSelector:onThread:withObject:waitUntilDone:
系のを使う。
Objective-C スレッドから libuv スレッド
libuv スレッドでは NSRunLoop が回ってないので上記の作法は使えない。代わりに uv_async
を使う。
まず、libuv スレッドで async コールバックを設定:
static void async_cb(uv_async_t* handle, int status) {
}
uv_async_init(self->loop, &self->async, async_cb);
で、呼び出し側(Objective-Cスレッド)から
uv_async_send(&obj->async);
とすれば async_cb
が libuv スレッドで発動するという寸法。
データを渡したいときは
@synchronized (obj.send_queue) {
[obj.send_queue addObject:@"foo"];
}
uv_async_send(&obj->async);
という感じにしておいて、取り出す側も
static void async_cb(uv_async_t* handle, int status) {
NSArray* queue;
@synchronized (self.send_queue) {
queue = [NSArray arrayWithArray:self.send_queue];
[self.send_queue removeAllObjects];
}
// 処理
}
みたいにすれば良い。
async コールバックは複数作ることができるから、用途に応じてコールバックを使い分けるのがよさそう。(データ送信用、スレッド終了用など)