Reputation: 9527
I am having this code
-(void) Method {
// WAIT_CODE
dispatch_async(myQueue,^{ CODE 1});
dispatch_async(myQueue,^{ CODE 2});
dispatch_barrier_async(myQueue,^{
// SOME CODE
dispatch_async(dispatch_get_main_queue(), ^{GUI UPDATE }
});
}
Problem is, when I call this method again and SOME CODE was not executed yet, I need to wait on WAIT_CODE before continue (BUT GUI must stay active)... How can I do this ?
Upvotes: 2
Views: 1993
Reputation: 7720
Option 1) Does it make sense to add a second serial queue so the code inside -method is run only when no other calls to the method are executing?
For example, in the caller would you have:
mySerialQueue = dispatch_queue_create("com.myapp.my-serial-queue", DISPATCH_QUEUE_SERIAL);
dispatch_async(mySerialQueue, [self method]);
Option 2) Make myQueue serial instead of concurrent (I assume it is concurrent because dispatch_barrier_async() only works on concurrent queues you own).
myQueue = dispatch_queue_create("com.myapp.myqueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(myQueue,^{ CODE 1});
dispatch_async(myQueue,^{ CODE 2});
dispatch_async(myQueue,^{
SOME CODE
dispatch_async(myQueue,^{
WAIT_CODE
dispatch_async(dispatch_get_main_queue(), ^{GUI UPDATE }
});
});
Option 3) Reorder the code to add WAIT_CODE after SOME_CODE
dispatch_async(myQueue,^{ CODE 1});
dispatch_async(myQueue,^{ CODE 2});
dispatch_barrier_async(myQueue,^{
SOME CODE // this code must block
WAIT_CODE // this code must block
dispatch_async(dispatch_get_main_queue(), ^{ GUI UPDATE }
});
Upvotes: 1
Reputation: 3522
You could also synchronize using a semaphore. Here is how your code could be structured.
-(void) Method
{
// Declared dispatch_semaphore_t _synch;
// in init: _synch = dispatch_semaphore_create(1);
// in dealloc: dispatch_release(_synch);
//
// Initialized with 1 so first call goes through.
// Subsequent calls are serialized and must wait on a signal.
//
dispatch_time_t blockingSleepSecondsIfNotDone = 0.01;
while (!dispatch_semaphore_wait(wait, DISPATCH_TIME_NOW))
usleep(USEC_PER_SEC * blockingSleepSecondsIfNotDone);
WAIT_CODE
dispatch_async(myQueue,^{ CODE 1});
dispatch_async(myQueue,^{ CODE 2});
dispatch_barrier_async(myQueue,^{
SOME CODE
dispatch_semaphore_signal(_synch);
dispatch_async(dispatch_get_main_queue(), ^{GUI UPDATE }
});
}
Upvotes: 1
Reputation: 28409
What are you trying to do?
Why do you have to wait?
If the queue is still executing SOME CODE
when you call this function again, those "new" blocks will get enqueued, and will not execute until after the SOME CODE
block runs. I assume myQueue
is a concurrent queue. The barrier call will wait for all previously enqueued blocks to execute before it runs. Furthermore, it will be the only block that runs on the queue, until it is done, then the queue will resume executing blocks concurrently.
Upvotes: 1