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 コールバックは複数作ることができるから、用途に応じてコールバックを使い分けるのがよさそう。(データ送信用、スレッド終了用など)

by typester / at 2012-01-24T14:12:00 / objc · libuv / Comments(0)