NAME¶
dispatch_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_concurrent_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT);
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);
}
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
().
SEE ALSO¶
dispatch(3),
dispatch_async(3),
dispatch_queue_create(3),
dispatch_semaphore_create(3)