为NSRunLoop找到匹配的NSThread(需要修复Socket Rocket)

问题描述 投票:4回答:1

我正在努力修复Socket Rocket的竞争条件。很久以前就报告过这个bug,但仍然没有修复。

一年多以前,我写了一个修复程序,它打破了API(只能使用共享线程),这个代码在生产中成功运行(当有很多用户时根本没有崩溃)。

现在我想以这样的方式调整我的修复,它不会破坏SRWebSocket的API。为此,我需要找到匹配的NSThread原谅NSRunLoop。这是一对一的关系,但我找到一个可以帮助我的API有问题。


PS. A fix is quite simple. Every operation made on NSRunLoop must be done from a respective thread. There is no NSRunLoop or CFRunLoopAPI that can be safely used from another thread. So I've added such API toSRRunLoopThread`:
- (void)scheduleBlock: (void(^)())block
{
    [self performSelector: @selector(_runBlock:)
                 onThread: self
               withObject: [block copy]
            waitUntilDone: NO];
}

- (void)_runBlock: (void(^)())block
{
    block();
}

并在每个在这个NSRunLoop上完成某些事情的地方使用它。

此修复程序显示了为什么我需要找到匹配的NSThread

注意documentations声明performSelector:onThread:withObject:waitUntilDone:是线程安全的

您可以使用此方法将消息传递到应用程序中的其他线程。

我必须再次强调,documentation warns clearly认为NSRunLoop API没有线程安全:

警告

NSRunLoop类通常不被认为是线程安全的,并且只应在当前线程的上下文中调用其方法。您永远不应该尝试调用在不同线程中运行的NSRunLoop对象的方法,因为这样做可能会导致意外结果。

由于CFRunLoopNSRunLoop的桥梁自由桥接是一样的,所以它具有完全相同的弱点。因此,如果文档没有说它是线程安全的API,那么它没有线程安全,我不能在该上下文中使用它(所以@DisableR提出的答案显然是无效的)。

objective-c multithreading websocket core-foundation
1个回答
1
投票

您可以执行具有runloop的块而无需线程。块将在与运行循环相关联的线程上异步执行。

CFRunLoopPerformBlock([myNSRunLoop getCFRunLoop], kCFRunLoopCommonModes, block);
CFRunLoopWakeUp([myNSRunLoop getCFRunLoop]);

这是关于在macOS Tiger上实现-performSelectorOnMainThread:NSThread方法的讨论,但是这个问题与你的问题非常相似:http://www.cocoabuilder.com/archive/cocoa/112261-cfrunlooptimer-firing-delay.html

© www.soinside.com 2019 - 2024. All rights reserved.