Skip to main content

dope_runtime/shutdown/
mod.rs

1use std::{io, marker, os::fd};
2
3use dope_core::driver::settings;
4
5use crate::executor;
6
7mod wakes;
8
9pub(crate) use wakes::{Ends, Notify, Wait};
10
11#[must_use]
12pub struct Pair {
13    source: Source,
14    trigger: Trigger,
15}
16
17#[must_use]
18pub struct Source {
19    pub(crate) event: fd::OwnedFd,
20    _guard: Notify,
21}
22
23#[must_use]
24pub struct Trigger(Notify);
25
26#[must_use]
27pub struct Requested<Q = Source> {
28    _source: marker::PhantomData<fn(Q) -> Q>,
29    _thread: o3::ThreadBound,
30}
31
32const _: () = assert!(std::mem::size_of::<Requested>() == 0);
33const _: () = assert!(std::mem::size_of::<Requested<crate::process::Shutdown>>() == 0);
34
35impl Pair {
36    pub fn new() -> io::Result<Self> {
37        let (event, notify) = Ends::event()?.split();
38        let (guard, notify) = notify.fork()?;
39        Ok(Self {
40            source: Source {
41                event,
42                _guard: guard,
43            },
44            trigger: Trigger(notify),
45        })
46    }
47
48    pub fn split(self) -> (Source, Trigger) {
49        (self.source, self.trigger)
50    }
51}
52
53impl executor::Factory for Source {
54    type Shutdown = Source;
55
56    fn executor(
57        self,
58        config: settings::Config,
59    ) -> io::Result<executor::Executor<(), Self::Shutdown>> {
60        executor::Executor::new(config)?.with_shutdown(self)
61    }
62}
63
64impl Trigger {
65    pub fn fire(self) -> io::Result<()> {
66        self.0.notify()
67    }
68}
69
70impl<Q> Requested<Q> {
71    pub(crate) const fn new() -> Self {
72        use o3::ThreadBound;
73
74        Self {
75            _source: marker::PhantomData,
76            _thread: ThreadBound::NEW,
77        }
78    }
79}