0

我有一个 Objective-C 应用程序,它使用一个通过 [NSThread detachNewThreadSelector] 生成的显式后台线程。这个后台线程是一个 HTTP 流解复用器,它产生视频和音频帧并将它们放入两个专用对象队列中。除了初始大小之外,这些队列是相同的。他们使用一个 NSLock 和一对 dispatch_semaphores 来实现一个阻塞队列。这是主要的 5 个操作的实现方式:

- (id) init:(uint)queueSize {
    queue = [[NSMutableArray alloc] initWithCapacity:queueSize];
    freeSlots = dispatch_semaphore_create(queueSize);
    objectsReady = dispatch_semaphore_create(0);
    lock = [[NSLock alloc] init];

    return [super init];
}

- (void)dealloc {
    NSLog(@"BlockingQ is being destroyed");
}

- (id) dequeue {
    dispatch_semaphore_wait(objectsReady, DISPATCH_TIME_FOREVER);
    [lock lock];
    id anObject = [queue objectAtIndex:0];
    [queue removeObjectAtIndex:0];
    [lock unlock];
    dispatch_semaphore_signal(freeSlots);

    return anObject;
}

- (void) enqueue:(id)element {
    dispatch_semaphore_wait(freeSlots, DISPATCH_TIME_FOREVER);
    [lock lock];
    [queue addObject:element];
    [lock unlock];
    dispatch_semaphore_signal(objectsReady);
}

- (uint) count {
    [lock lock];
    uint ret = [queue count];
    [lock unlock];
    return ret;
}

当需要停止播放时,我通知后台线程它需要停止,然后等待它终止。完成后,我尝试通过执行以下操作来清理队列:

- (void) clear {
    [lock lock];
    [queue removeAllObjects];
    while (dispatch_semaphore_wait(objectsReady, DISPATCH_TIME_NOW) == 0)
        dispatch_semaphore_signal(freeSlots);
    [lock unlock];
}

while 循环的目的是“平衡”等待/信号调用,并确保两个信号量在它们的值等于它们的初始值时被释放。我从阅读此讨论中了解到:为什么此代码会导致“EXC_BAD_INSTRUCTION”?

然而,当其中一个队列被销毁时,即使这个循环也不能让我免于崩溃。调试器显示的汇编代码片段几乎与上面链接中显示的相同。

所以,我的问题是:

  1. 将 GCD 信号量与 NSThreads 混合使用是否合法?
  2. 如何确保信号量处于良好状态以被销毁?

非常感谢!

4

0 回答 0