1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// concinnity-physics/src/fanout.rs
//
// How a caller lends the simulation its threads.
//
// The simulation cannot own a scheduler. It is `#![no_std]` and depends on two
// leaves, so it can neither name a thread pool nor detect that one exists. The
// work it can split is therefore offered rather than taken: a step says what it
// holds that is independent, and whoever called it decides whether that runs on
// one thread or several.
//
// The trait is generic in the item and the body rather than object safe. A step
// hands out a small fixed array of work units, so the fan-out is monomorphised
// into the step that used it and nothing is boxed or dispatched dynamically.
//
// `scope` is the second half of that, and it is what makes the first one
// affordable. Reaching a pool of sleeping workers from a thread that is not one
// of them costs far more than the handing-out does; reaching it again from
// inside costs almost nothing. So a step gathers the workers once and offers
// all three of its stages inside that, rather than paying the entry three
// times. A fan-out with nothing to gather leaves the default alone.
//
// A caller that lends nothing gets `Inline`, which runs the units in order on
// the calling thread. That is the default `Simulation::step` uses, and it is
// why a single-threaded host needs no capability check and no configuration.
/// A caller's way of running independent work at the same time.
///
/// The simulation asks for one of these rather than depending on a scheduler,
/// so the same step runs on a thread pool, on one thread, or on a host that has
/// no threads at all.
///
/// # Examples
///
/// ```
/// use concinnity_physics::{Fanout, Inline};
///
/// let mut work = [1u32, 2, 3];
/// Inline.for_each(&mut work, |item| *item *= 10);
/// assert_eq!(work, [10, 20, 30]);
/// assert_eq!(Inline.workers(), 1);
/// ```