genawaiter/stack/
engine.rs

1use crate::{core, core::Next};
2use std::{cell::UnsafeCell, ptr};
3
4/// This type holds the value that is pending being returned from the generator.
5///
6/// # Safety
7///
8/// This type is `!Sync` (so, single-thread), never exposed to user-land code,
9/// and never borrowed across a function call, so safety can be verified locally
10/// at each use site.
11pub struct Airlock<Y, R>(UnsafeCell<Next<Y, R>>);
12
13impl<Y, R> Default for Airlock<Y, R> {
14    fn default() -> Self {
15        Self(UnsafeCell::new(Next::Empty))
16    }
17}
18
19impl<'s, Y, R> core::Airlock for &'s Airlock<Y, R> {
20    type Yield = Y;
21    type Resume = R;
22
23    fn peek(&self) -> Next<(), ()> {
24        // Safety: This follows the safety rules above.
25        let inner = unsafe { &*self.0.get() };
26        inner.without_values()
27    }
28
29    fn replace(
30        &self,
31        next: Next<Self::Yield, Self::Resume>,
32    ) -> Next<Self::Yield, Self::Resume> {
33        // Safety: This follows the safety rules above.
34        unsafe { ptr::replace(self.0.get(), next) }
35    }
36}
37
38/// This object lets you yield values from the generator by calling the `yield_`
39/// method.
40///
41/// "Co" can stand for either _controller_ or _coroutine_, depending on how
42/// theoretical you are feeling.
43///
44/// [_See the module-level docs for examples._](.)
45pub type Co<'y, Y, R = ()> = core::Co<&'y Airlock<Y, R>>;