1use std::{
2 io,
3 sync::{Arc, Weak},
4};
5
6use mio::Token;
7
8use crate::{InterestHandler, InterestType, InterestWakerMap, Selector};
9
10#[derive(Debug)]
11#[must_use = "Leaking token guards will break the IO subsystem"]
12pub struct InterestGuard {
13 selector: Weak<Selector>,
14 pub(crate) token: Token,
15}
16impl Drop for InterestGuard {
17 fn drop(&mut self) {
18 self.drop_internal();
19 }
20}
21impl InterestGuard {
22 pub fn new(
23 selector: &Arc<Selector>,
24 handler: Box<dyn InterestHandler + Send + Sync>,
25 source: &mut dyn mio::event::Source,
26 interest: mio::Interest,
27 ) -> io::Result<InterestGuard> {
28 let token = selector.add(handler, source, interest)?;
29 Ok(Self {
30 selector: Arc::downgrade(selector),
31 token,
32 })
33 }
34
35 pub fn unregister(&mut self, source: &mut dyn mio::event::Source) -> io::Result<()> {
36 if let Some(selector) = self.selector.upgrade() {
37 selector.remove(self.token, Some(source))?;
38 }
39 Ok(())
40 }
41
42 pub fn replace_handler(
43 &mut self,
44 handler: Box<dyn InterestHandler + Send + Sync>,
45 ) -> Result<(), Box<dyn InterestHandler + Send + Sync>> {
46 match self.selector.upgrade() {
47 Some(selector) => {
48 selector.replace(self.token, handler);
49 Ok(())
50 }
51 _ => Err(handler),
52 }
53 }
54
55 pub fn interest(&mut self, interest: InterestType) {
56 if let Some(selector) = self.selector.upgrade() {
57 selector.push_interest(self.token, interest);
58 }
59 }
60
61 fn drop_internal(&mut self) {
62 if let Some(selector) = self.selector.upgrade() {
63 selector.remove(self.token, None).ok();
64 }
65 }
66}
67
68#[derive(Debug)]
69pub enum HandlerGuardState {
70 None,
71 ExternalHandler(InterestGuard),
72 WakerMap(InterestGuard, InterestWakerMap),
73}
74
75pub fn state_as_waker_map<'a>(
76 state: &'a mut HandlerGuardState,
77 selector: &'_ Arc<Selector>,
78 source: &'_ mut dyn mio::event::Source,
79) -> io::Result<&'a mut InterestWakerMap> {
80 if !matches!(state, HandlerGuardState::WakerMap(_, _)) {
81 let waker_map = InterestWakerMap::default();
82 *state = HandlerGuardState::WakerMap(
83 InterestGuard::new(
84 selector,
85 Box::new(waker_map.clone()),
86 source,
87 mio::Interest::READABLE | mio::Interest::WRITABLE,
88 )?,
89 waker_map,
90 );
91 }
92 Ok(match state {
93 HandlerGuardState::WakerMap(_, map) => map,
94 _ => unreachable!(),
95 })
96}