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>>;