Skip to main content

dope_runtime/
shutdown.rs

1use std::{marker, os::fd};
2
3use dope_core::{
4    Errno,
5    driver::{life::creation, settings},
6};
7use o3::base::marker::ThreadBound;
8
9use crate::{
10    executor::{self, create},
11    process::{
12        failure::bus,
13        lifecycle::{self, Main},
14    },
15};
16
17pub use crate::process::Shutdown as ReadySource;
18
19#[derive(Clone, Copy, Debug, PartialEq, Eq)]
20pub enum CreateError {
21    Pair(bus::Create),
22    Duplicate(Errno),
23}
24
25#[derive(Debug)]
26pub struct FireError {
27    pub trigger: Trigger,
28    pub cause: Errno,
29}
30
31#[must_use]
32pub struct Pair {
33    source: Source,
34    trigger: Trigger,
35}
36
37#[must_use]
38pub struct Source {
39    pub(crate) event: (fd::OwnedFd, Main),
40}
41
42impl fd::AsFd for Source {
43    fn as_fd(&self) -> fd::BorrowedFd<'_> {
44        fd::AsFd::as_fd(&self.event.0)
45    }
46}
47
48#[must_use]
49#[derive(Debug)]
50pub struct Trigger(Main);
51
52type Invariant<Q> = marker::PhantomData<(fn(Q) -> Q, ThreadBound)>;
53
54#[must_use]
55pub struct Requested<Q = Source>(Invariant<Q>);
56
57impl Pair {
58    pub fn new() -> Result<Self, CreateError> {
59        let (main, event) = lifecycle::pair().map_err(CreateError::Pair)?;
60        let guard = main.duplicate().map_err(CreateError::Duplicate)?;
61        Ok(Self {
62            source: Source {
63                event: (event, guard),
64            },
65            trigger: Trigger(main),
66        })
67    }
68
69    pub fn split(self) -> (Source, Trigger) {
70        (self.source, self.trigger)
71    }
72
73    pub fn run<R>(self, execute: impl FnOnce(Source) -> R) -> R {
74        execute(self.source)
75    }
76}
77
78impl executor::Build for Source {
79    type Shutdown = Source;
80
81    fn try_build(
82        self,
83        attempt: &mut creation::Attempt,
84        config: settings::Config,
85    ) -> Result<executor::Executor<(), Self::Shutdown>, create::Error<'_>> {
86        executor::Executor::new(attempt, config)?
87            .shutdown(self)
88            .map_err(create::Error::from)
89    }
90}
91
92impl executor::Startup for Source {
93    fn installed(&self) -> Result<(), executor::InstallError> {
94        Ok(())
95    }
96}
97
98impl Trigger {
99    pub fn fire(self) -> Result<(), FireError> {
100        match self.0.request() {
101            Ok(()) => Ok(()),
102            Err(cause) => Err(FireError {
103                trigger: self,
104                cause,
105            }),
106        }
107    }
108}
109
110impl<Q> Requested<Q> {
111    pub(crate) const fn new() -> Self {
112        Self(marker::PhantomData)
113    }
114}
115
116const _: () = assert!(std::mem::size_of::<Requested>() == 0);