我一直对如何编写以下代码以将其用于单元测试感兴趣:
是否可以使用检查特定线程是否被阻塞的方法来扩展 NSThread?
现在我正在使用 NSCondition:Xcode 向我展示了由-wait调用以阻塞线程的链:
[NSCondition wait]
pthread_cond_wait$UNIX2003
_pthread_cond_wait
__psynch_cvwait
除了检查 NSCondition 完成的锁之外,如果可能的话,我非常感谢方法也适用于任何其他阻塞功能(调度信号量、条件锁、休眠线程等)——我不知道 Objective-C 的内部结构,如果它们可以被一种方法捕获,或者每种方法都需要自己的方法。
这是我想要实现的一个简单示例。这个神秘的方法叫做isBlocked。
// Some test case
// ...
__block NSThread *thread;
NSCondition *condition = [NSCondition alloc] init];
dispatch_async(someQueue(), ^{
thread = NSThread.currentThread;
[condition lock];
[condition wait];
[condition unlock];
});
while(1) {
NSLog(@"Thread is blocked: %d", thread.isBlocked);
}
注意:我不擅长 C 和所有这些低级 POSIX 的东西,所以,请详细一点。
注2:我对调度队列的解决方案也很感兴趣:如果有人可以告诉我如何测试 someQueue() 被 -[NSCondition wait] 阻止的事实(而不是它将被阻止的事实(fx在 -[condition wait] 运行并设置块之前破解一些代码),但线程/队列被阻塞的事实),我会像处理 -[NSThread isBlocked] 方法一样接受这个作为答案.
注 3:怀疑像“不可能”这样的坏消息,我声称任何关于捕获 -[condition wait] 已运行并且线程被设置为阻塞(见注 2)这一事实的想法都值得赞赏,也可以被接受为一个答案!
更新 1以解决 Richard J. Ross III 的好答案。不幸的是,他的回答在我原来的例子中不起作用,这个版本更接近我的真实工作(尽管它与我最初提供的例子没有太大区别——很抱歉我没有将它包含在第一版问题):
// Example
// Here I've bootstrapped Richard's isLocking categories for both NSThread and NSCondition
// ...
// somewhere in SenTesting test case...
__block NSThread *thread;
NSCondition *condition = [NSCondition alloc] init];
__block BOOL wePassedBlocking = NO;
dispatch_async(someQueue(), ^{
thread = NSThread.currentThread;
[condition lock];
[condition wait];
[condition unlock];
wePassedBlocking = YES; // (*) This line is occasionally never reached!
});
while(!thread.isWaitingOnCondition); // I want this loop to exit after the condition really locks someQueue() and _thread_ __.
// sleep(1);
[condition lock];
[condition broadcast]; // BUT SOMETIMES this line is called before -[condition wait] is called inside someQueue() so the entire test case becomes blocked!
[condition unlock];
while(!wePassedBlocking); // (*) And so this loop occasionally never ends!
如果我取消注释sleep(1)测试开始工作非常稳定,没有任何偶尔的锁定!
这导致我们遇到问题,Richard 的类别确实在实际阻塞完成之前设置状态正好一行,这意味着有时测试用例的主线程在我们实际阻塞someQueue/thread之前捕获这个新状态,因为 Richard 的代码不包含任何同步机制:@synchronized、NSLock 或类似的东西!我希望我能清楚地解释这个棘手的案例。对于任何对我在这里发布的内容有疑问的人,我想说我也一直在尝试多个队列甚至更复杂的案例,如果需要,我准备提供更多示例。理查德,再次感谢您的努力,如果您理解我的这些观点,让我们一起思考更多!
更新 2
我看到了一个死胡同:显然,要真正设置waitingOnCondition的状态,我们需要将此状态的更改包装在一些同步闭包中,但问题是关闭同步锁,解锁同步锁,应该在 -[condition wait],但它不能,因为线程已经被阻塞。再次,我希望我描述得很清楚。