body_image_futio/
blocking.rs

1
2/// All possible states of a [`BlockingArbiter`].
3#[derive(Debug, PartialEq, Copy, Clone)]
4pub enum Blocking {
5    // Not requested nor allowed
6    Void,
7    // Requested Once
8    Pending,
9    // One blocking operation granted
10    Once,
11    // Any/all blocking operations perpetually granted
12    Always,
13}
14
15/// Trait for arbitration of where blocking operations are acceptable to the
16/// runtime.
17pub trait BlockingArbiter {
18    /// Return true if blocking is allowed.
19    ///
20    /// This may record the need to block and/or consume any one-time blocking
21    /// allowance.
22    fn can_block(&mut self) -> bool;
23
24    /// Return the current blocking state, without making any change.
25    fn state(&self) -> Blocking;
26}
27
28/// A lenient arbiter that always allows blocking.
29#[derive(Debug, Default)]
30pub struct LenientArbiter;
31
32impl BlockingArbiter for LenientArbiter {
33
34    /// Return true if blocking is allowed.
35    ///
36    /// This implementation always returns true.
37    fn can_block(&mut self) -> bool {
38        true
39    }
40
41    fn state(&self) -> Blocking {
42        Blocking::Always
43    }
44}
45
46/// A stateful arbiter that records the need to block and grants one-time
47/// allowances.
48#[derive(Debug)]
49pub struct StatefulArbiter {
50    state: Blocking
51}
52
53impl Default for StatefulArbiter {
54    fn default() -> Self {
55        StatefulArbiter { state: Blocking::Void }
56    }
57}
58
59impl StatefulArbiter {
60    pub(crate) fn set(&mut self, state: Blocking) {
61        self.state = state;
62    }
63}
64
65impl BlockingArbiter for StatefulArbiter {
66    /// Return true if blocking is allowed, consuming any one-time allowance.
67    /// Otherwise records that blocking has been requested.
68    fn can_block(&mut self) -> bool {
69        match self.state {
70            Blocking::Void => {
71                self.state = Blocking::Pending;
72                false
73            }
74            Blocking::Pending => {
75                false
76            }
77            Blocking::Once => {
78                self.state = Blocking::Void;
79                true
80            }
81            Blocking::Always => {
82                true
83            }
84        }
85    }
86
87    fn state(&self) -> Blocking {
88        self.state
89    }
90}