dope_runtime/shutdown/
mod.rs1use 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}