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