danpalmer
danpalmer

Reputation: 2173

Grand Central Dispatch delayed execution design pattern

I am writing an application with a plugin system. Plugins must work on the main thread (this is not part of the question, I'm not looking for a bunch of answers that say I should remove this requirement).

Plugins get initialised asynchronously so the UI doesn't hang for a few seconds on launch, but other code immediately starts to interact with the plugins after launch. This obviously needs to be delayed until the plugins have finished loading.

Here is what I've got so far...

// Create operation queue
dispatch_queue_t queue = dispatch_queue_create(...);
dispatch_suspend(queue);

// Load the plugins
dispatch_group_t group = dispatch_group_create();
for each plugin {
    dispatch_group_async(group, dispatch_get_main_queue(), ^{
        load...
    });
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    dispatch_resume(queue);
});

// Add operations that interact with the plugins
dispatch_async(queue, ^{
    dispatch_async(dispatch_get_main_queue(), ^{
        operation...
    });
});

This will mean that any operations submitted won't start until the plugins have finished loading, however, any new operations will go through two queues before actually being processed. Is this a large overhead? Would it be worth queueing to begin with, and then swapping out method implementations when ready for one that doesn't bother queueing? This would be more tricky to do and I don't know if it would be worth it.

Finally, is there a better design pattern for this type of problem? Perhaps I should be using NSOperations and NSOperationQueues with dependencies? Or would they have a higher overhead than basic GCD operations?

Upvotes: 0

Views: 378

Answers (1)

jkh
jkh

Reputation: 3266

The "double overhead" is actually really low, but there is a slightly better design pattern you can use for this that is also more intuitive. Create your operation queue and then use dispatch_set_target_queue(queue, dispatch_get_main_queue()) to make it, in essence, a sub-queue of the main queue. This will ensure it executes on the main thread while not requiring you to do the cross-submission - you'll just submit the plug-in operation(s) directly to the operation queue.

Upvotes: 2

Related Questions