我已经编写了一个类似于Grand Central Dispatch的类,它将对要在线程池上执行的块进行排队。 (为什么你想知道?因为我需要一个具有线程亲和力的GCD。)
代码非常简单:
static let sharedInstance=CuprumOperationQueue()
func addOperation(operation: ()->()) {
dispatch_async(_operationsQueue) {
//Place the operation on the queue
self._operations.append(operation)
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) {
self.pushQueue()
}
}
}
func getOperation() -> ClosureType? {
var operation: ClosureType?=nil;
dispatch_sync(_operationsQueue) {
if (!self._operations.isEmpty) {
operation=self._operations.removeFirst();
}
}
return operation;
}
func pushQueue() {
for thread in _threads {
if (CFRunLoopIsWaiting(thread.runLoop)) {
if let operation = self.getOperation() {
CFRunLoopPerformBlock(thread.runLoop, kCFRunLoopDefaultMode, operation); //(2)
CFRunLoopWakeUp(thread.runLoop);
} else {
//There are no more operations to perform
break;
}
}
}
}
我使用GCD串行队列(_operationsQueue)来序列化对块(_operations)的数组访问。当运行循环即将休眠时,线程(使用观察者运行CFRunLoop)调用pushQueue。
我按如下方式使用队列:
[[CuprumOperationQueue sharedInstance] addOperation:^{ //(1)
[[NSOperationQueue mainQueue] addOperationWithBlock:^(void) {
NSLog(@"test %p",self);
}];
}];
问题是调用上述代码段的对象永远不会被释放。它没有被报告为仪器中的泄漏,因此至少有一些可达参考。我只是不知道在哪里。我怀疑某处有一个保留周期,因为从NSLog语句中删除自引用会导致该对象被释放。但这不是整个问题,因为使用NSOperationQueue替换等效线(1)也会导致对象被正确释放(即使在第二个块中使用自引用)。因此,只有与我的自定义队列结合才会出现问题。
如果在基于Swift的队列类中,我删除了带有(2)的行上的调用,该对象也被正确释放。
正如您所看到的,没有多少代码可以导致问题,但我真的不知道这可能会导致保留周期。
任何见解都将受到高度赞赏。