dispatch_apply(3) BSD Library Functions Manual dispatch_apply(3)NAMEdispatch_apply — schedule blocks for iterative execution
SYNOPSIS
#include <dispatch/dispatch.h>
void
dispatch_apply(size_t iterations, dispatch_queue_t queue,
void (^block)(size_t));
void
dispatch_apply_f(size_t iterations, dispatch_queue_t queue,
void *context, void (*function)(void *, size_t));
DESCRIPTION
The dispatch_apply() function provides data-level concurrency through a
"for (;;)" loop like primitive:
dispatch_queue_t the_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
size_t iterations = 10;
// 'idx' is zero indexed, just like:
// for (idx = 0; idx < iterations; idx++)
dispatch_apply(iterations, the_queue, ^(size_t idx) {
printf("%zu\n", idx);
});
Like a "for (;;)" loop, the dispatch_apply() function is synchronous. If
asynchronous behavior is desired, please wrap the call to
dispatch_apply() with a call to dispatch_async() against another queue.
Sometimes, when the block passed to dispatch_apply() is simple, the use
of striding can tune performance. Calculating the optimal stride is best
left to experimentation. Start with a stride of one and work upwards
until the desired performance is achieved (perhaps using a power of two
search):
#define STRIDE 3
dispatch_apply(count / STRIDE, queue, ^(size_t idx) {
size_t j = idx * STRIDE;
size_t j_stop = j + STRIDE;
do {
printf("%zu\n", j++);
} while (j < j_stop);
});
size_t i;
for (i = count - (count % STRIDE); i < count; i++) {
printf("%zu\n", i);
}
IMPLIED REFERENCES
Synchronous functions within the dispatch framework hold an implied ref‐
erence on the target queue. In other words, the synchronous function bor‐
rows the reference of the calling function (this is valid because the
calling function is blocked waiting for the result of the synchronous
function, and therefore cannot modify the reference count of the target
queue until after the synchronous function has returned).
This is in contrast to asynchronous functions which must retain both the
block and target queue for the duration of the asynchronous operation (as
the calling function may immediately release its interest in these
objects).
FUNDAMENTALS
Conceptually, dispatch_apply() is a convenient wrapper around
dispatch_async() and a semaphore to wait for completion. In practice,
the dispatch library optimizes this function.
The dispatch_apply() function is a wrapper around dispatch_apply_f().
CAVEATS
Unlike dispatch_async(), a block submitted to dispatch_apply() is
expected to be either independent or dependent only on work already per‐
formed in lower-indexed invocations of the block. If the block's index
dependency is non-linear, it is recommended to use a for-loop around
invocations of dispatch_async().
SEE ALSOdispatch(3), dispatch_async(3), dispatch_queue_create(3),
dispatch_semaphore_create(3)Darwin May 1, 2009 Darwin