xref: /trueos/lib/libdispatch/man/dispatch_apply.3 (revision bf5f91cb28c5878845eb00fbf329c042f6c643c9)
1.\" Copyright (c) 2008-2010 Apple Inc. All rights reserved.
2.Dd May 1, 2009
3.Dt dispatch_apply 3
4.Os Darwin
5.Sh NAME
6.Nm dispatch_apply
7.Nd schedule blocks for iterative execution
8.Sh SYNOPSIS
9.Fd #include <dispatch/dispatch.h>
10.Ft void
11.Fo dispatch_apply
12.Fa "size_t iterations" "dispatch_queue_t queue" "void (^block)(size_t)"
13.Fc
14.Ft void
15.Fo dispatch_apply_f
16.Fa "size_t iterations" "dispatch_queue_t queue" "void *context" "void (*function)(void *, size_t)"
17.Fc
18.Sh DESCRIPTION
19The
20.Fn dispatch_apply
21function provides data-level concurrency through a "for (;;)" loop like primitive:
22.Bd -literal
23dispatch_queue_t the_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
24size_t iterations = 10;
25
26// 'idx' is zero indexed, just like:
27// for (idx = 0; idx < iterations; idx++)
28
29dispatch_apply(iterations, the_queue, ^(size_t idx) {
30	printf("%zu\\n", idx);
31});
32.Ed
33.Pp
34Like a "for (;;)" loop, the
35.Fn dispatch_apply
36function is synchronous.
37If asynchronous behavior is desired, please wrap the call to
38.Fn dispatch_apply
39with a call to
40.Fn dispatch_async
41against another queue.
42.Pp
43Sometimes, when the block passed to
44.Fn dispatch_apply
45is simple, the use of striding can tune performance.
46Calculating the optimal stride is best left to experimentation.
47Start with a stride of one and work upwards until the desired performance is
48achieved (perhaps using a power of two search):
49.Bd -literal
50#define STRIDE 3
51
52dispatch_apply(count / STRIDE, queue, ^(size_t idx) {
53	size_t j = idx * STRIDE;
54	size_t j_stop = j + STRIDE;
55	do {
56		printf("%zu\\n", j++);
57	} while (j < j_stop);
58});
59
60size_t i;
61for (i = count - (count % STRIDE); i < count; i++) {
62	printf("%zu\\n", i);
63}
64.Ed
65.Sh IMPLIED REFERENCES
66Synchronous functions within the dispatch framework hold an implied reference
67on the target queue. In other words, the synchronous function borrows the
68reference of the calling function (this is valid because the calling function
69is blocked waiting for the result of the synchronous function, and therefore
70cannot modify the reference count of the target queue until after the
71synchronous function has returned).
72.Pp
73This is in contrast to asynchronous functions which must retain both the block
74and target queue for the duration of the asynchronous operation (as the calling
75function may immediately release its interest in these objects).
76.Sh FUNDAMENTALS
77Conceptually,
78.Fn dispatch_apply
79is a convenient wrapper around
80.Fn dispatch_async
81and a semaphore to wait for completion.
82In practice, the dispatch library optimizes this function.
83.Pp
84The
85.Fn dispatch_apply
86function is a wrapper around
87.Fn dispatch_apply_f .
88.Sh CAVEATS
89Unlike
90.Fn dispatch_async ,
91a block submitted to
92.Fn dispatch_apply
93is expected to be either independent or dependent
94.Em only
95on work already performed in lower-indexed invocations of the block. If
96the block's index dependency is non-linear, it is recommended to
97use a for-loop around invocations of
98.Fn dispatch_async .
99.Sh SEE ALSO
100.Xr dispatch 3 ,
101.Xr dispatch_async 3 ,
102.Xr dispatch_queue_create 3 ,
103.Xr dispatch_semaphore_create 3
104