1 | /// Temporary data that gets initialized during a blocking operation, and is consumed by |
2 | /// `read` or `write`. |
3 | /// |
4 | /// Each field contains data associated with a specific channel flavor. |
5 | #[derive (Debug, Default)] |
6 | pub struct Token { |
7 | pub(crate) array: super::array::ArrayToken, |
8 | pub(crate) list: super::list::ListToken, |
9 | #[allow (dead_code)] |
10 | pub(crate) zero: super::zero::ZeroToken, |
11 | } |
12 | |
13 | /// Identifier associated with an operation by a specific thread on a specific channel. |
14 | #[derive (Debug, Clone, Copy, PartialEq, Eq)] |
15 | pub struct Operation(usize); |
16 | |
17 | impl Operation { |
18 | /// Creates an operation identifier from a mutable reference. |
19 | /// |
20 | /// This function essentially just turns the address of the reference into a number. The |
21 | /// reference should point to a variable that is specific to the thread and the operation, |
22 | /// and is alive for the entire duration of a blocking operation. |
23 | #[inline ] |
24 | pub fn hook<T>(r: &mut T) -> Operation { |
25 | let val: usize = r as *mut T as usize; |
26 | // Make sure that the pointer address doesn't equal the numerical representation of |
27 | // `Selected::{Waiting, Aborted, Disconnected}`. |
28 | assert!(val > 2); |
29 | Operation(val) |
30 | } |
31 | } |
32 | |
33 | /// Current state of a blocking operation. |
34 | #[derive (Debug, Clone, Copy, PartialEq, Eq)] |
35 | pub enum Selected { |
36 | /// Still waiting for an operation. |
37 | Waiting, |
38 | |
39 | /// The attempt to block the current thread has been aborted. |
40 | Aborted, |
41 | |
42 | /// An operation became ready because a channel is disconnected. |
43 | Disconnected, |
44 | |
45 | /// An operation became ready because a message can be sent or received. |
46 | Operation(Operation), |
47 | } |
48 | |
49 | impl From<usize> for Selected { |
50 | #[inline ] |
51 | fn from(val: usize) -> Selected { |
52 | match val { |
53 | 0 => Selected::Waiting, |
54 | 1 => Selected::Aborted, |
55 | 2 => Selected::Disconnected, |
56 | oper: usize => Selected::Operation(Operation(oper)), |
57 | } |
58 | } |
59 | } |
60 | |
61 | impl Into<usize> for Selected { |
62 | #[inline ] |
63 | fn into(self) -> usize { |
64 | match self { |
65 | Selected::Waiting => 0, |
66 | Selected::Aborted => 1, |
67 | Selected::Disconnected => 2, |
68 | Selected::Operation(Operation(val: usize)) => val, |
69 | } |
70 | } |
71 | } |
72 | |