]>
Commit | Line | Data |
---|---|---|
0ab74447 A |
1 | .\" Copyright (c) 2008-2009 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_concurrent_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT); | |
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 FUNDAMENTALS | |
66 | Conceptually, | |
67 | .Fn dispatch_apply | |
68 | is a convenient wrapper around | |
69 | .Fn dispatch_async | |
70 | and a semaphore to wait for completion. | |
71 | In practice, the dispatch library optimizes this function. | |
72 | .Pp | |
73 | The | |
74 | .Fn dispatch_apply | |
75 | function is a wrapper around | |
76 | .Fn dispatch_apply_f . | |
77 | .Sh SEE ALSO | |
78 | .Xr dispatch_async 3 , | |
79 | .Xr dispatch_semaphore_create 3 , | |
80 | .Xr dispatch_queue_create 3 |