]> git.saurik.com Git - apple/libdispatch.git/blob - man/dispatch_apply.3
libdispatch-187.5.tar.gz
[apple/libdispatch.git] / man / dispatch_apply.3
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
19 The
20 .Fn dispatch_apply
21 function provides data-level concurrency through a "for (;;)" loop like primitive:
22 .Bd -literal
23 dispatch_queue_t the_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
24 size_t iterations = 10;
25
26 // 'idx' is zero indexed, just like:
27 // for (idx = 0; idx < iterations; idx++)
28
29 dispatch_apply(iterations, the_queue, ^(size_t idx) {
30 printf("%zu\\n", idx);
31 });
32 .Ed
33 .Pp
34 Like a "for (;;)" loop, the
35 .Fn dispatch_apply
36 function is synchronous.
37 If asynchronous behavior is desired, please wrap the call to
38 .Fn dispatch_apply
39 with a call to
40 .Fn dispatch_async
41 against another queue.
42 .Pp
43 Sometimes, when the block passed to
44 .Fn dispatch_apply
45 is simple, the use of striding can tune performance.
46 Calculating the optimal stride is best left to experimentation.
47 Start with a stride of one and work upwards until the desired performance is
48 achieved (perhaps using a power of two search):
49 .Bd -literal
50 #define STRIDE 3
51
52 dispatch_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
60 size_t i;
61 for (i = count - (count % STRIDE); i < count; i++) {
62 printf("%zu\\n", i);
63 }
64 .Ed
65 .Sh IMPLIED REFERENCES
66 Synchronous functions within the dispatch framework hold an implied reference
67 on the target queue. In other words, the synchronous function borrows the
68 reference of the calling function (this is valid because the calling function
69 is blocked waiting for the result of the synchronous function, and therefore
70 cannot modify the reference count of the target queue until after the
71 synchronous function has returned).
72 .Pp
73 This is in contrast to asynchronous functions which must retain both the block
74 and target queue for the duration of the asynchronous operation (as the calling
75 function may immediately release its interest in these objects).
76 .Sh FUNDAMENTALS
77 Conceptually,
78 .Fn dispatch_apply
79 is a convenient wrapper around
80 .Fn dispatch_async
81 and a semaphore to wait for completion.
82 In practice, the dispatch library optimizes this function.
83 .Pp
84 The
85 .Fn dispatch_apply
86 function is a wrapper around
87 .Fn dispatch_apply_f .
88 .Sh CAVEATS
89 Unlike
90 .Fn dispatch_async ,
91 a block submitted to
92 .Fn dispatch_apply
93 is expected to be either independent or dependent
94 .Em only
95 on work already performed in lower-indexed invocations of the block. If
96 the block's index dependency is non-linear, it is recommended to
97 use 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