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);
}