genawaiter/rc/
engine.rs

1use crate::{core, core::Next};
2use std::{cell::Cell, rc::Rc};
3
4pub struct Airlock<Y, R>(Rc<Cell<Next<Y, R>>>);
5
6impl<Y, R> Default for Airlock<Y, R> {
7    fn default() -> Self {
8        Self(Rc::new(Cell::new(Next::Empty)))
9    }
10}
11
12impl<Y, R> Clone for Airlock<Y, R> {
13    fn clone(&self) -> Self {
14        Self(self.0.clone())
15    }
16}
17
18impl<Y, R> core::Airlock for Airlock<Y, R> {
19    type Yield = Y;
20    type Resume = R;
21
22    fn peek(&self) -> Next<(), ()> {
23        // Safety: `Rc` is `!Send + !Sync`, and control does not leave this function
24        // while the reference is taken, so concurrent access is not possible. The value
25        // is not modified, so no shared references elsewhere can be invalidated.
26        let inner = unsafe { &*self.0.as_ptr() };
27        inner.without_values()
28    }
29
30    fn replace(&self, next: Next<Y, R>) -> Next<Y, R> {
31        self.0.replace(next)
32    }
33}
34
35/// This object lets you yield values from the generator by calling the `yield_`
36/// method.
37///
38/// "Co" can stand for either _controller_ or _coroutine_, depending on how
39/// theoretical you are feeling.
40///
41/// [_See the module-level docs for examples._](.)
42pub type Co<Y, R = ()> = core::Co<Airlock<Y, R>>;