dispatch_apply.3   [plain text]

.\" Copyright (c) 2008-2009 Apple Inc. All rights reserved.
.Dd May 1, 2009
.Dt dispatch_apply 3
.Os Darwin
.Nm dispatch_apply
.Nd schedule blocks for iterative execution
.Fd #include <dispatch/dispatch.h>
.Ft void
.Fo dispatch_apply
.Fa "size_t iterations" "dispatch_queue_t queue" "void (^block)(size_t)"
.Ft void
.Fo dispatch_apply_f
.Fa "size_t iterations" "dispatch_queue_t queue" "void *context" "void (*function)(void *, size_t)"
.Fn dispatch_apply
function provides data-level concurrency through a "for (;;)" loop like primitive:
.Bd -literal
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
.Fn dispatch_apply
function is synchronous.
If asynchronous behavior is desired, please wrap the call to
.Fn dispatch_apply
with a call to
.Fn dispatch_async
against another queue.
Sometimes, when the block passed to
.Fn 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):
.Bd -literal
#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);
.Fn dispatch_apply
is a convenient wrapper around
.Fn dispatch_async
and a semaphore to wait for completion.
In practice, the dispatch library optimizes this function.
.Fn dispatch_apply
function is a wrapper around
.Fn dispatch_apply_f .
.Xr dispatch_async 3 ,
.Xr dispatch_semaphore_create 3 ,
.Xr dispatch_queue_create 3