nuclei 0.5.2

Proactive IO & runtime system
Documentation
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
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
//! What a step under a side's guard leaves for once the guard is let go
//! ([`After`]): the wakes and drops that may run code of their own, parked
//! while a non-owning view of a source is live and the thread unwinds
//! ([`Unwound`]); and the wakers of the tasks waiting on a side ([`Wakers`]).

use core::mem::MaybeUninit;
use core::task::Waker;

use crate::buf::PoolBuf;

/// What a step leaves for once no guard is held: wakers to wake, wakers and
/// buffers to drop (either may run code that reaches a source), and what
/// the source must do next.
///
/// Almost every step leaves nothing, so the slots start empty and unwritten,
/// and `held` says which of them hold a value and which flags are raised: a
/// step that left nothing is made with one store and settled with one look.
pub(crate) struct After {
    /// `WAKE`, `DROP`, `MORE`, `KICK`: the slot holds a value; `STARVED`,
    /// `REGISTER`: the flag is raised.
    held: u8,
    /// The first waker to wake: almost every step wakes one task at most.
    wake: MaybeUninit<Waker>,
    /// The first buffer to drop: almost every step drops one at most.
    drop_one: MaybeUninit<PoolBuf>,
    more: MaybeUninit<Box<More>>,
    /// A side of a ring source wants an operation the ring's thread, the
    /// one of this shard, must submit.
    #[cfg(ring)]
    kick: MaybeUninit<std::sync::Arc<crate::rt::shard::Shared>>,
}

/// `After::held`: the slots that hold a value.
const WAKE: u8 = 1;
const DROP: u8 = 2;
const MORE: u8 = 4;
#[cfg(ring)]
const KICK: u8 = 8;
/// `After::held`: a side found the pool empty and must hear when a buffer
/// comes back.
const STARVED: u8 = 16;
/// `After::held`: work was left to the driver, so the source must be
/// registered.
const REGISTER: u8 = 32;

#[cfg(ring)]
const SLOTS: u8 = WAKE | DROP | MORE | KICK;
#[cfg(not(ring))]
const SLOTS: u8 = WAKE | DROP | MORE;

impl Default for After {
    #[inline(always)]
    fn default() -> Self {
        Self {
            held: 0,
            wake: MaybeUninit::uninit(),
            drop_one: MaybeUninit::uninit(),
            more: MaybeUninit::uninit(),
            #[cfg(ring)]
            kick: MaybeUninit::uninit(),
        }
    }
}

/// What a step leaves beyond one waker and one buffer, allocated only when
/// a step has more.
#[derive(Default)]
struct More {
    wake: Vec<Waker>,
    forget: Wakers,
    bufs: Vec<PoolBuf>,
}

impl After {
    fn more(&mut self) -> &mut More {
        if self.held & MORE == 0 {
            self.more.write(Box::default());
            self.held |= MORE;
        }
        // SAFETY: `MORE` says the slot holds a value.
        unsafe { self.more.assume_init_mut() }
    }

    /// Whether a side found the pool empty: the source must hear when a
    /// buffer comes back.
    #[inline(always)]
    pub(crate) fn starved(&self) -> bool {
        self.held & STARVED != 0
    }

    /// A side found the pool empty (see [`starved`](Self::starved)).
    #[inline(always)]
    pub(crate) fn set_starved(&mut self) {
        self.held |= STARVED;
    }

    /// Whether work was left to the driver, so the source must be registered.
    #[inline(always)]
    pub(crate) fn must_register(&self) -> bool {
        self.held & REGISTER != 0
    }

    /// Work was left to the driver (see [`must_register`](Self::must_register)).
    #[inline(always)]
    pub(crate) fn set_must_register(&mut self) {
        self.held |= REGISTER;
    }

    /// The shard whose ring thread must submit what a side wants, in place
    /// of the one asked before.
    #[cfg(ring)]
    pub(crate) fn set_kick(&mut self, home: Option<std::sync::Arc<crate::rt::shard::Shared>>) {
        drop(self.take_kick());
        if let Some(home) = home {
            self.kick.write(home);
            self.held |= KICK;
        }
    }

    /// Takes the shard [`set_kick`](Self::set_kick) asked.
    #[cfg(ring)]
    #[inline(always)]
    pub(crate) fn take_kick(&mut self) -> Option<std::sync::Arc<crate::rt::shard::Shared>> {
        if self.held & KICK == 0 {
            return None;
        }
        self.held &= !KICK;
        // SAFETY: `KICK` said the slot holds a value, and it is cleared: the
        // value is read out once.
        Some(unsafe { self.kick.assume_init_read() })
    }

    /// Takes the first waker.
    #[inline(always)]
    fn take_wake(&mut self) -> Option<Waker> {
        if self.held & WAKE == 0 {
            return None;
        }
        self.held &= !WAKE;
        // SAFETY: as in `take_kick`.
        Some(unsafe { self.wake.assume_init_read() })
    }

    /// Takes the first buffer.
    #[inline(always)]
    fn take_drop(&mut self) -> Option<PoolBuf> {
        if self.held & DROP == 0 {
            return None;
        }
        self.held &= !DROP;
        // SAFETY: as in `take_kick`.
        Some(unsafe { self.drop_one.assume_init_read() })
    }

    /// Takes what goes beyond the first waker and buffer.
    #[inline(always)]
    fn take_more(&mut self) -> Option<Box<More>> {
        if self.held & MORE == 0 {
            return None;
        }
        self.held &= !MORE;
        // SAFETY: as in `take_kick`.
        Some(unsafe { self.more.assume_init_read() })
    }

    #[inline]
    pub(crate) fn wake(&mut self, wakers: &mut Wakers) {
        if let Some(w) = wakers.first.take() {
            self.wake_one(w);
        }
        if !wakers.rest.is_empty() {
            self.wake_rest(wakers);
        }
    }

    #[cold]
    #[inline(never)]
    fn wake_rest(&mut self, wakers: &mut Wakers) {
        self.more().wake.append(&mut wakers.rest);
    }

    /// Drops `wakers` without waking them.
    pub(crate) fn forget(&mut self, wakers: &mut Wakers) {
        if !wakers.is_empty() {
            self.more().forget.append(wakers);
        }
    }

    /// Wakes the one task of `waker`.
    #[inline]
    pub(crate) fn wake_one(&mut self, waker: Waker) {
        if self.held & WAKE == 0 {
            self.wake.write(waker);
            self.held |= WAKE;
        } else {
            self.wake_more(waker);
        }
    }

    #[cold]
    #[inline(never)]
    fn wake_more(&mut self, waker: Waker) {
        self.more().wake.push(waker);
    }

    /// Drops `waker` without waking it.
    pub(crate) fn forget_one(&mut self, waker: Waker) {
        self.more().forget.push(waker);
    }

    pub(crate) fn drop_buf(&mut self, buf: PoolBuf) {
        if self.held & DROP == 0 {
            self.drop_one.write(buf);
            self.held |= DROP;
        } else {
            self.more().bufs.push(buf);
        }
    }

    /// Wakes and drops; call with no guard held. Once: it consumes the step,
    /// so its drop finds nothing left to do.
    #[inline]
    pub(crate) fn run(mut self) {
        if self.held & SLOTS != 0 {
            self.run_held();
        }
        core::mem::forget(self);
    }

    /// [`run`](Self::run) of a step that left a value.
    #[inline(never)]
    fn run_held(&mut self) {
        self.flush();
        #[cfg(ring)]
        drop(self.take_kick());
    }

    #[inline]
    fn flush(&mut self) {
        drop(self.take_drop());
        match self.take_more() {
            None => {
                if let Some(w) = self.take_wake() {
                    w.wake();
                }
            }
            Some(more) => self.flush_more(*more),
        }
    }

    /// [`flush`](Self::flush) of a step that left more than one waker or buffer.
    #[inline(never)]
    fn flush_more(&mut self, more: More) {
        let More { wake, forget, bufs } = more;
        drop(bufs);
        drop(forget);
        if let Some(w) = self.take_wake() {
            w.wake();
        }
        wake.into_iter().for_each(Waker::wake);
    }
}

impl Drop for After {
    fn drop(&mut self) {
        if parking() {
            self.park();
        } else {
            self.flush();
        }
        #[cfg(ring)]
        drop(self.take_kick());
    }
}

impl After {
    /// Consumes a step that left nothing to do, without the work of settling it: `Err` gives
    /// back one that did.
    #[inline(always)]
    pub(crate) fn forget_if_nothing(self) -> Result<(), Self> {
        if self.held == 0 {
            // Nothing is owned: no waker, no buffer, no allocation, so there is nothing to drop.
            core::mem::forget(self);
            Ok(())
        } else {
            Err(self)
        }
    }

    #[inline(always)]
    fn is_empty(&self) -> bool {
        self.held & SLOTS == 0
    }

    /// Unwinding: the work goes to the thread's list for [`Unwound`] or the
    /// end of the poll to run, else (the list gone, at thread exit) runs now.
    #[cold]
    fn park(&mut self) {
        if self.is_empty() {
            return;
        }
        let mut work = core::mem::take(self);
        let parked = UNWOUND.try_with(|list| match list.try_borrow_mut() {
            Ok(mut list) => {
                list.push(core::mem::take(&mut work));
                true
            }
            Err(_) => false,
        });
        if parked != Ok(true) {
            work.flush();
            #[cfg(ring)]
            drop(work.take_kick());
        }
    }
}

/// Whether an `After` dropped now is parked: the thread is unwinding with an
/// [`Unwound`] guard alive.
#[cfg(any(ring, test))]
fn parking() -> bool {
    view_live().get() && std::thread::panicking()
}

#[cfg(not(any(ring, test)))]
fn parking() -> bool {
    false
}

#[cfg(any(ring, test))]
thread_local! {
    /// A non-owning view of a source is live on this thread (see [`Unwound`]).
    static VIEW_LIVE: core::cell::Cell<bool> = const { core::cell::Cell::new(false) };
}

/// This thread's [`VIEW_LIVE`], reached with an inlined access: only its address comes out of
/// `with`, whose closure is then too small not to be inlined.
#[cfg(any(ring, test))]
#[inline(always)]
fn view_live() -> &'static core::cell::Cell<bool> {
    // SAFETY: the cell has no destructor, so it lives as long as the thread; it is a `Cell`,
    // which is not `Sync`, so the reference stays on this thread.
    unsafe { &*VIEW_LIVE.with(core::ptr::from_ref) }
}

thread_local! {
    /// What [`After`]s dropped during unwinding left to run.
    static UNWOUND: core::cell::RefCell<Vec<After>> = const { core::cell::RefCell::new(Vec::new()) };
}

/// Runs what unwinding steps left in this thread's list.
#[cfg(any(ring, test))]
pub(crate) fn run_unwound() {
    let Ok(work) = UNWOUND.try_with(|list| core::mem::take(&mut *list.borrow_mut())) else {
        return;
    };
    work.into_iter().for_each(After::run);
}

/// Declared before a non-owning view of a source, so that it drops after it:
/// while it lives, an `After` dropped by unwinding is parked, and when it
/// drops by unwinding it runs what was parked.
#[cfg(any(ring, test))]
pub(crate) struct Unwound {
    outer: bool,
}

#[cfg(any(ring, test))]
impl Unwound {
    pub(crate) fn enter() -> Self {
        Self {
            outer: view_live().replace(true),
        }
    }
}

#[cfg(any(ring, test))]
impl Drop for Unwound {
    fn drop(&mut self) {
        view_live().set(self.outer);
        if std::thread::panicking() {
            run_unwound();
        }
    }
}

/// The wakers of the tasks waiting on a side. A waker of a task already
/// registered is not added again, so the list holds one waker per task.
#[derive(Default)]
pub(crate) struct Wakers {
    first: Option<Waker>,
    rest: Vec<Waker>,
}

impl Wakers {
    #[inline(always)]
    pub(crate) fn register(&mut self, waker: &Waker) {
        let known = self.first.as_ref().is_some_and(|w| w.will_wake(waker))
            || self.rest.iter().any(|w| w.will_wake(waker));
        if known {
            return;
        }
        self.push(waker.clone());
    }

    /// Adds `waker`, known or not.
    #[inline(always)]
    fn push(&mut self, waker: Waker) {
        if self.first.is_none() {
            self.first = Some(waker);
        } else {
            self.push_rest(waker);
        }
    }

    #[cold]
    #[inline(never)]
    fn push_rest(&mut self, waker: Waker) {
        self.rest.push(waker);
    }

    pub(crate) fn is_empty(&self) -> bool {
        self.first.is_none()
    }

    /// How many tasks wait.
    #[cfg(any(readiness, test))]
    pub(crate) fn len(&self) -> usize {
        usize::from(self.first.is_some()) + self.rest.len()
    }

    /// Moves every waker of `other` here.
    fn append(&mut self, other: &mut Wakers) {
        if let Some(w) = other.first.take() {
            self.push(w);
        }
        self.rest.append(&mut other.rest);
    }
}