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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
//! Nuclei's runtime-independent synchronization primitives: locks, a
//! semaphore, events, a barrier, once-cells and channels that never block a
//! thread.
//!
//! Every wait in this module is a [`Future`] built from
//! futures and wakers only: async code awaits it, and any executor polls it
//! with its own [`Waker`](core::task::Waker). Every primitive also has
//! `try_` forms that never wait. The core of this module makes no system
//! call: no futex, no thread park, no sleep and no clock read. The one
//! exception is inside the lock-free queues the primitives use, which recycle
//! waiter nodes and yield the thread when they meet contention. The other
//! exception is the
//! `blocking_*` methods, which exist for threads that may block and park
//! the calling thread until their wait is over. Called on a nuclei shard
//! (inside one of its tasks) they run a nested `block_on` instead, so the
//! shard keeps running its other tasks; called inside another runtime's task
//! they block the thread that task runs on.
//!
//! # Names and signatures
//!
//! [`Mutex`](crate::sync::Mutex), [`RwLock`](crate::sync::RwLock), [`Semaphore`](crate::sync::Semaphore), [`Notify`](crate::sync::Notify), [`Barrier`](crate::sync::Barrier),
//! [`OnceCell`](crate::sync::OnceCell) and [`SetOnce`](crate::sync::SetOnce) take the names, signatures, error types and
//! documented behavior of the established async `sync` API, so code
//! written against that API compiles against these. The
//! guards and errors sit at the same paths under `nuclei::sync`, and the
//! waits are named futures (`Lock`, `Read`, `Acquire`, and so on) rather
//! than opaque ones. A semaphore holds at most [`Semaphore::MAX_PERMITS`](crate::sync::Semaphore::MAX_PERMITS)
//! permits, which is `usize::MAX >> 7`. What this module adds is the
//! [`Event`](crate::sync::Event), the [`Latch`](crate::sync::Latch), the [`Lazy`](crate::sync::Lazy) value, the upgradable read of the
//! [`RwLock`](crate::sync::RwLock), the reentrant locks and `OnceCell::get_or_init_racy`.
//! The [`mpsc`](crate::sync::mpsc) channels follow the same rule for the established channel API,
//! with their own progress notes.
//! The [`local`](crate::sync::local) module adds single-shard twins of the
//! channels, the semaphore and the mutex, with no atomic instruction on any
//! path, and [`mesh`](crate::sync::mesh) a full mesh of bounded channels
//! between a fixed number of parties.
//!
//! # What every primitive guarantees
//!
//! - **No runtime.** A contended acquire queues a waiter, registers the
//! caller's `Waker` and returns `Pending`. What a wake does belongs to
//! the caller's executor. Within one poll, a contended acquire of a lock
//! or a semaphore may first spin for a short while (up to the lock's
//! spin budget, a count of pause instructions it adapts to how long holds
//! last, about 5 microseconds at most on the cores it was tuned on):
//! before it queues, and again after a retry it lost. The spin makes no
//! system call, reads no clock, and ends in the same queueing or the same
//! `Pending` as before. Locks whose holders keep them across long waits
//! of their own do not spin, and their contended callers queue at once:
//! the once-cell's initializer turn, for example.
//! - **Fast under contention.** The locks and the semaphore let a caller
//! take what is free even while others wait, so a release never waits
//! for a suspended task to run: the thread that released takes the lock
//! straight back.
//! - **Bounded bypass.** A release wakes the oldest waiters it could
//! serve to compete again. One that loses [`MAX_BYPASS`](crate::sync::MAX_BYPASS) times is owed a
//! handoff: nobody gets in ahead of it, and the next release hands it
//! what it waits for directly. Fairness is counted, never timed.
//! - **Cancellation-safe.** Dropping a pending future withdraws its
//! waiter. If something was handed to it concurrently, the drop passes
//! it on. No wakeup is lost. (A [`Barrier`](crate::sync::Barrier) wait is the one exception: an
//! arrival that was counted stays counted.)
//! - **Cooperative on a nuclei shard.** In a task on a nuclei shard (or in
//! `block_on`'s own future), a receive of [`mpsc`](crate::sync::mpsc),
//! [`oneshot`](crate::sync::oneshot), [`broadcast`](crate::sync::broadcast)
//! or [`watch`](crate::sync::watch) that completes spends one operation of
//! the task's cooperative budget, as IO does
//! ([`task::coop`]), and so does an acquire of a
//! semaphore, a lock (the reentrant ones too) or a bounded send that
//! completes at its first attempt. When the budget is spent the call
//! completes nothing, wakes its task and returns `Pending`, so a loop on a
//! channel or a lock that is always ready yields to the shard's other
//! tasks. A wait that queued and was granted spends nothing: giving the
//! grant back would cost it its place. The `try_` forms never spend, and
//! off a nuclei shard there is no budget. The events, latches, barriers,
//! once-cells and `Notify` keep no budget.
//! - **Reentrancy by [`Owner`](crate::sync::Owner).** The reentrant locks are keyed by an
//! owner token rather than a thread, because a task can move between
//! threads and many tasks can share one.
//! - **Every target.** State lives in word-sized atomics (in plain cells
//! in [`local`](crate::sync::local), whose types stay on one thread). On
//! single-threaded wasm the same code runs on one thread, where only
//! interleaved tasks contend. The fast paths allocate nothing; a waiter
//! node comes from a per-primitive free list and reaches the allocator
//! only when that list is empty.
//!
//! # How a wait works
//!
//! Each primitive keeps one state word, a lock-free stack of arriving
//! waiters and a FIFO of the waiters already sorted. Uncontended calls
//! touch the state word only, one atomic read-modify-write each. Anything
//! that can make a waiter runnable (a release, a new waiter, a
//! cancellation) takes the drain role with one compare-and-swap, or, when
//! another thread holds it, leaves a mark for the holder and returns, so
//! no call ever waits for another. The holder wakes what the state allows
//! (or, while a handoff is owed, grants it in queue order), rechecks until
//! nothing changed while it worked, and calls the wakers after it has
//! given the role up.
//!
//! # Progress
//!
//! Every operation is lock-free, not wait-free. No call waits for another
//! thread, and some call always completes; but a call may do work on
//! behalf of others, and how much depends on them.
//!
//! - Uncontended, an acquire and a release are one atomic
//! read-modify-write each.
//! - A call that can make a waiter runnable (a release with waiters, a new
//! waiter, a cancellation, a notification, a semaphore's `close`, a write
//! guard's `downgrade`, `add_permits`) may serve the queue itself. It
//! returns after one pass over the queue, plus at most one more pass for
//! each of these that lands while it works: a waiter that queues, a
//! waiter that withdraws, a waiter that claims the handoff it is owed, and
//! a release that finds a node queued.
//! - `forget_permits` wakes nobody: it is a compare-and-swap loop on the
//! state word, which retries only when another call changed the word
//! first. A barrier's arrival is one `fetch_add`, followed, for the
//! arrival that completes a group, by the pass that wakes the group.
//! - A release over an empty queue earns no pass; a release that finds a
//! node queued earns one. So releases alone never keep a thread at work.
//! Waiters that keep queueing or withdrawing can, one pass each: every
//! such pass is another thread's own operation getting done, which is
//! what lock-free means, and there is no cap on the passes of one call.
//!
//! Besides the primitives, this module re-exports a lock-free map
//! ([`HopscotchMap`](crate::sync::HopscotchMap)), queues
//! ([`SegQueue`](crate::sync::SegQueue), [`ArrayQueue`](crate::sync::ArrayQueue)) and
//! [`Atom`](crate::sync::Atom), so one module holds every synchronization structure.
/// Defines a constructor as a `const fn` in an ordinary build and as a
/// plain `fn` under `--cfg loom`, whose instrumented atomics cannot be
/// built in a constant context.
;
}
pub
pub
pub
// See the note on its re-export below.
pub
pub use ;
pub use ;
pub use MAX_BYPASS;
pub use ;
pub use ;
pub use Lazy;
pub use ;
pub use ;
pub use ;
// vertexia: the owner-named lock has no consumer in this crate yet; its
// tests run in `owned_lock`. Trim it if it stays unused.
pub use between_take_and_grant;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
/// Named future types, at the conventional `sync::futures` path.
// These four are the kovan crates' own types, re-exported as they are: their
// API and its changes are kovan's, and code that names them through this
// module follows kovan's versions, which nuclei's own semver does not cover.
/// An atomically swapped value, from the kovan crate: see its docs.
pub use Atom;
/// A concurrent hash map, from the kovan-map crate: see its docs.
pub use HopscotchMap;
/// A bounded lock-free queue, from the kovan-queue crate: see its docs.
pub use ArrayQueue;
/// An unbounded lock-free queue and its pop error, from the kovan-queue
/// crate: see its docs.
pub use ;