/// Temporary data that gets initialized during a blocking operation, and is consumed by /// `read` or `write`. /// /// Each field contains data associated with a specific channel flavor. #[derive(Debug, Default)] pub struct Token { pub(crate) array: super::array::ArrayToken, pub(crate) list: super::list::ListToken, #[allow(dead_code)] pub(crate) zero: super::zero::ZeroToken, } /// Identifier associated with an operation by a specific thread on a specific channel. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Operation(usize); impl Operation { /// Creates an operation identifier from a mutable reference. /// /// This function essentially just turns the address of the reference into a number. The /// reference should point to a variable that is specific to the thread and the operation, /// and is alive for the entire duration of a blocking operation. #[inline] pub fn hook(r: &mut T) -> Operation { let val = r as *mut T as usize; // Make sure that the pointer address doesn't equal the numerical representation of // `Selected::{Waiting, Aborted, Disconnected}`. assert!(val > 2); Operation(val) } } /// Current state of a blocking operation. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Selected { /// Still waiting for an operation. Waiting, /// The attempt to block the current thread has been aborted. Aborted, /// An operation became ready because a channel is disconnected. Disconnected, /// An operation became ready because a message can be sent or received. Operation(Operation), } impl From for Selected { #[inline] fn from(val: usize) -> Selected { match val { 0 => Selected::Waiting, 1 => Selected::Aborted, 2 => Selected::Disconnected, oper => Selected::Operation(Operation(oper)), } } } impl Into for Selected { #[inline] fn into(self) -> usize { match self { Selected::Waiting => 0, Selected::Aborted => 1, Selected::Disconnected => 2, Selected::Operation(Operation(val)) => val, } } }