I have to calculate a costly value. After this value is computed, I'd like to run a completion handler block:
-(void) performCostlyCalculationWithCompletionHandler:(void (^)(void)complete
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
id result = [self costlyCalculation];
dispatch_async(dispatch_get_main_queue(), ^{
complete(result);
});
});
}
Pretty standard.
Now, I'd like to be able to call this function repeatedly, without re-enqueueing costlyCalculation
. If costlyCalculation
is already running I'd like to just save the completion blocks and call them all with the same result
once costlyCalculation
finishes.
Is there a simple way to do this with GCD or an NSOperationQueue? Or should I just store the completion blocks in an NSArray
and call them myself? If I do this, what sort of synchronization do I need to put around this array?
UPDATE
I'm able to get close with dispatch_group_notify
. Basically, I can enqueue the work blocks and enqueue all completion handlers to run after the group:
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queue, ^(){
// Do something that takes a while
id result = [self costlyCalculation];
dispatch_group_async(group, dispatch_get_main_queue(), ^(){
self.result = result;
});
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^(){
complete(result);
});
This would work, but how can I tell if costlyCalcuation
is already running and not enqueue the work if I don't need to?