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 ([email protected])
>
> 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 [email protected]
_______________________________________________
Cocoa-dev mailing list ([email protected])
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 [email protected]