2

2 つの実行ループ間の通信用のメッセージ ポートを作成しようとする次のコードがあります。1 つの実行ループは pthread の代わりに実行され、もう 1 つはメインの実行ループです。この機能は、さまざまな条件下で正常に機能しているように見えますが、いずれも望ましい条件ではありません。

たとえば、kCFRunLoopDefaultMode の代わりに NULL を渡すと機能しますが、ブロックされません。

sndData とMessagePortProc コールバックからの戻り値 (rerun NULL) の両方に kCFRunLoopDefaultMode と NULL データを渡すことも期待どおりに機能しますが、MessagePortProc コールバックからデータを送受信する必要があるため、メッセージ ポートを使用する必要があり ます

kCFRunLoopDefaultMode が使用され、かつ MessagePortProc 戻り値または sndData パラメータのいずれかがNOT NULLである場合、 CFMessagePortSendRequest ブロックが返され、決して返されません。MessagePortProc は正常に呼び出され、呼び出された場所に制御を返すことはありません。エラーメッセージは出力されず、クラッシュも発生せず、ただそこに留まっています。

テストケースとして、送信データと受信データの両方に対して、以下に概説する小さなバイト配列から作成された単純な CFDataRef を使用しています。いずれかが、概説された動作を引き起こします。

UInt8 bytes[] = { 0, 1 };
CFDataRef sndData = CFDataCreate(kCFAllocatorDefault, bytes, 2);
SInt32 response = CFMessagePortSendRequest(remoteMsgPort, 0, sndData, 1, 1, kCFRunLoopDefaultMode, &rtnData);


CFDataRef MessagePortProc(CFMessagePortRef msgport, SInt32 msgid, CFDataRef data, void *info) {
    CFDataRef retData = NULL;

    ... Processing Done Here ...

    return retData;
}

void StartMessagePortRunLoop() {
    CFMessagePortContext context = {
        .version = 0,
        .info = NULL,
        .retain = NULL,
        .release = NULL,
        .copyDescription = NULL
    };

    localMsgPort = CFMessagePortCreateLocal(kCFAllocatorDefault, CFSTR("TextServiceMessagePort"), MessagePortProc, &context, NULL);
    if (localMsgPort != NULL) {
        sourceMsgPort = CFMessagePortCreateRunLoopSource(kCFAllocatorDefault, localMsgPort, 0);
        CFRunLoopAddSource(CFRunLoopGetMain(), sourceMsgPort, kCFRunLoopDefaultMode);
    }
}

void StopMessagePortRunLoop() {
    if (CFRunLoopContainsSource(CFRunLoopGetMain(), sourceMsgPort, kCFRunLoopDefaultMode)) {
        CFRunLoopRemoveSource(CFRunLoopGetMain(), sourceMsgPort, kCFRunLoopDefaultMode);
        CFRelease(sourceMsgPort);
    }

    CFMessagePortInvalidate(localMsgPort);
    CFRelease(localMsgPort);
}
4

0 に答える 0