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