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
//! Work items, and the envelope the runtime stamps around them.
use crate;
use ClassId;
use Duration;
/// The latency-bound half of the conventional two-class split.
///
/// A class is an index into the per-class in-flight budgets and ready rings, and
/// a runtime can carry as many as it wants. Two covers most deployments: work
/// that spends its time waiting on something else, and work that spends its time
/// burning a core. Separating them is what stops a batch of the second from
/// delaying the first.
///
/// These are named here so that every crate downstream stops redeclaring them.
/// A workload that needs a different split should define its own constants and
/// pass its own `CLASSES`; nothing in the runtime privileges these values beyond
/// [`CLASSES`] being what every `CLASSES` parameter defaults to.
pub const IO: ClassId = 0;
/// The CPU-bound half of the conventional two-class split. See [`IO`].
pub const COMPUTE: ClassId = 1;
/// The number of classes in the [`IO`] plus [`COMPUTE`] split.
///
/// Every `CLASSES` parameter in this crate defaults to this, so the common case
/// never has to name it. `Runtime<P>`, `Router<W>`, `ShardConfig` and
/// `ShardStats` all mean the two-class versions when the argument is left off,
/// and the first two default their clock to
/// [`SystemClock`](crate::clock::SystemClock) as well.
pub const CLASSES: usize = 2;
/// A unit of work routed to the shard owning its affine key.
///
/// Work crosses a thread boundary exactly once — from whoever submitted it to
/// the shard that owns its key — which is why it must be `Send`. Nothing else
/// in the pipeline is: per-key state and the futures processing it stay on the
/// shard's own core and are free to be `!Send`.
///
/// Each of these methods is called exactly once, at submission, and the answer
/// is stamped into the envelope. The scheduler never asks again, so an
/// implementation that answered differently on a second call cannot corrupt
/// anything.
/// A work item plus the scheduling metadata stamped at submission.
/// What a shard's scheduler stores: the work, when it was submitted so
/// queue-wait latency can be measured at dispatch, and its idempotency key so
/// the coalescing index can be cleared when the item leaves.
pub