method1:
- (void) method1
{
[_condition lock];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
//Fetach data from remote, when finished call method2
[self fetchData];
});
[_condition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:30.0]];
// Do something.
[_condition unlock];
}
method2:
- (void) method2
{
[_condition lock];
[_condition signal];
[_condition unlock];
}
If Thread 1 is in method1, by executing [_condition waitUtilDate ...];
it unlocks its lock. Thread 2 entered this area and also wait on the condition by executing [_condition waitUtilDate ...]
.
Both Thread 1 and Thread 2 enqueued a Block(request 1 request 2) to fetch the same data from remote. When request 1 finishes, it calls method2 to signal _condition:
broadcast
) and cancel request 2 when request 1 finishes. But, a better way is to refuse Thread 2 to enter the critical area, after request 1 is sent out. But I coundn't lock twice before entering the critical area. So what can I do? Thanks.
If you're trying to prevent duplicate requests you can do this with a boolean flag that you set when starting the request and then clear when you're done. You'd protect your critical regions with a mutex/semaphore/NSLock/etc.
[_lock lock];
if (_fetching) {
[_lock unlock];
return;
}
_fetching = YES;
[self startRequestWithCompletion: ^{
[_lock lock];
_fetching = NO;
[_lock unlock];
}];
[_lock unlock];
Or you can use an NSOperationQueue and NSOperation to handle this more elegantly. You'd test the queue to see if there are any pending or running operations before starting a new one.
if (_operationQueue.operationCount)
return;
[_operationQueue addOperationWithBlock: ^{
// get your data
}];
How you do this really depends on exactly what you're fetching and whether the response may change based on input data. For example, I use NSOperations extensively to manage background computations. However, user input could change the result of those computations and invalidate any previous work. I hang on to a reference the NSOperation itself so I can cancel it and restart a new one where appropriate.