I have multiple asynchronous tasks that all depend on an initial async authentication step to succeed. I'm using a semaphore to block all the secure tasks until the authentication completes. It's mostly for timing purposes, as the tasks rely on a secure token obtained at the end of authentication. The authentication involves a network request, and may take several seconds.
The difficulty in my code below seems to be that the dispatch_semaphore_signal() issued after authentication only signals that the first semaphore lock may continue. The second would continue to block. There could in future be many moew blocking tasks, all waiting on the semaphore.
I'm wondering if there is a cleaner way to go about this blocking. I believe that each waiting task could immediately issue another dispatch_semaphore_signal(), thus releasing the next task, and so on. Is there a way to release all blocking semaphores in one call?
Is there a cleaner way to do this with GCD? I'm not adept with GCD, so code snippets help, in the context of the below usage.
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
// in actuality, these 3 may be any where in the app, in different classes, methods, etc
// so a completionHandler is not possible
[self authentication]; // async, could take many seconds
[self authenticatedTask1]; // async
[self authenticatedTask2]; // async
- (void) authentication {
// async url request, assume it is configured here
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
// authenticate
authenticated = TRUE;
secure_token = @"4rjiofwefsdf"; // obtained during auth
dispatch_semaphore_signal(sem);
}];
}
- (void) authenticatedTask1 {
// put on new thread, so semaphore doesn't block program
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
if(!authenticated){
// wait until authenticated
dispatch_semaphore_wait(sem)
}
// continue after authenticated, using secure_token
});
}
- (void) authenticatedTask2 {
// put on new thread, so semaphore doesn't block program
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
if(!authenticated){
// wait until authenticated
dispatch_semaphore_wait(sem)
}
// continue after authenticated, using secure_token
});
}
You can put the authenticated tasks into their own suspended dispatch queue, and resume the dispatch queue once the authentication succeeded.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With