On 31.08.2012, at 19:35, Seth Willits wrote: Thank you very much Seth. It's a feasible approach. Your idea inspired me to a simple solution which is demonstrated in the running example below.
There is only one caveat: each pending completion handler occupies a thread. #include <Foundation/Foundation.h> #include <dispatch/dispatch.h> #include <stdio.h> typedef void(^work_t)(void); typedef void(^completion_t)(void); static void start(work_t work, dispatch_queue_t workerQueue, completion_t completion, dispatch_queue_t completionQueue) { dispatch_semaphore_t sem = dispatch_semaphore_create(0); dispatch_async(completionQueue, ^{ dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); dispatch_release(sem); completion(); }); dispatch_async(workerQueue, ^{ work(); dispatch_semaphore_signal(sem); }); } int main(int argc, const char * argv[]) { @autoreleasepool { dispatch_semaphore_t finished = dispatch_semaphore_create(0); dispatch_queue_t workerQueue = dispatch_get_global_queue(0, 0); dispatch_queue_t completionQueue = dispatch_queue_create("serialqueue", NULL); start(^{printf("A"); sleep(4);}, workerQueue, ^{printf("a");}, completionQueue); start(^{printf("B"); sleep(3);}, workerQueue, ^{printf("b");}, completionQueue); start(^{printf("C"); sleep(2);}, workerQueue, ^{printf("c");}, completionQueue); start(^{printf("D"); sleep(1);}, workerQueue, ^{printf("d");}, completionQueue); start(^{printf("\n"); }, workerQueue, ^{ printf("\nfinished"), dispatch_semaphore_signal(finished);}, completionQueue); dispatch_semaphore_wait(finished, DISPATCH_TIME_FOREVER); } return 0; } > On Aug 31, 2012, at 1:08 AM, Andreas Grosam wrote: > >> I have a number of operations that will be received serially. Each operation >> can be processed concurrently with respect to each other. I would like to >> invoke the completion blocks for each operation in the order as they have >> been received. > > > > If you have operations A, B, C, D where which should execute concurrently, > but their results used serially then: > > > dispatch_queue_t serialQueue = …; > dispatch_queue_t concurrentQueue = (global queue, or a new concurrent queue); > > > > > dispatch_semaphore_t semaphoreA = dispatch_semaphore_create(0); > __block id resultsOfA = nil; > > > wrapA = ^{ > resultsOfA = runA(); > dispatch_semaphore_signal(semaphoreA); > } > > > doneA =^{ > dispatch_semaphore_wait(semaphoreA); > completionHandlerForA(resultsOfA); > } > > > > > // the completion handlers are pushed onto a serial queue > // but will not execute until the semaphore is signaled > // after the work is done > dipatch_async(doneA, searialQueue); > dipatch_async(doneB, searialQueue); > dipatch_async(doneC, searialQueue); > dipatch_async(doneD, searialQueue); > > // The work fires off concurrently > dispatch_async(wrapA, concurrentQueue); > dispatch_async(wrapB, concurrentQueue); > dispatch_async(wrapC, concurrentQueue); > dispatch_async(wrapD, concurrentQueue); > > > > >> I'm searching a simple approach to achieve this, implemented using >> NSOperationQueue, NSOperation and dispatch lib. > > > You can do the above with NSOperationQueue using a serial queue and > concurrent queue, but you must use dependencies between the operations to > enforce the serial execution of the completion handlers. The standard > behavior of a serial NSOpQ is that only one thing may be executed at a time, > but it *does not care which order they were submitted in*. It's first *ready* > first out, not first in first out. So although you may have a dependency that > the completion handler operation come after the work operation, if B finishes > before A, B's completion handler will run first. To stop that you need to > have a dependency that A complete before B. The trouble with this is that it > ends up with a chain of retains through the dependencies properties > (dependencies aren't dropped from the operation even if they're met), so you > need to manually remove it from within the operation itself. It's messy. > > > > > -- > Seth Willits > > > > > _______________________________________________ > > Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) > > Please do not post admin requests or moderator comments to the list. > Contact the moderators at cocoa-dev-admins(at)lists.apple.com > > Help/Unsubscribe/Update your Subscription: > https://lists.apple.com/mailman/options/cocoa-dev/agrosam%40onlinehome.de > > This email sent to agro...@onlinehome.de _______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com