I originally posted this problem in the old devforums, and now have a reduced test case.
I still don't understand what's fundamentally the issue here, but basically the new compiler is somehow allowing a block to get added to a GCD queue twice in some situations. In the following code, the 10 worker blocks each do their thing and the parent block waits until they're all done. This used to work really well (through Xcode 5.1.1), but now, occationally, one of the worker threads will get added to the queue *twice*.
Jeffrey
int main(int argc, const char * argv[]) {
@autoreleasepool {
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
NSUInteger totalWorkers = 10;
NSMutableArray *workers = [[NSMutableArray alloc] init];
for (NSUInteger iWorker=0; iWorker<totalWorkers; iWorker++) {
__block int numThreads = 0;
workerType worker = ^{
numThreads++;
if (numThreads>1) {
NSLog(@"Whoops! Called by two threads");
}
int y = 0;
for (int i=0; i<1000; i++) {
y += 1;
}
dispatch_group_leave(group);
numThreads--;
};
[workers addObject: worker];
}
void (^parent)(void) = ^{
for (NSUInteger i=0; i<totalWorkers; i++) {
dispatch_group_enter(group);
}
for ( workerType aWorker in workers ) {
dispatch_async( queue, ^{
aWorker();
});
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
};
NSUInteger n = 0;
while (1) {
parent();
n++;
if (n%10000==0) {
NSLog(@"Looped %lu", n);
}
}
}
return 0;
}