1 use std::{fmt, usize}; 2 3 /// ThreadPool state. 4 /// 5 /// The two least significant bits are the shutdown flags. (0 for active, 1 for 6 /// shutdown on idle, 2 for shutting down). The remaining bits represent the 7 /// number of futures that still need to complete. 8 #[derive(Eq, PartialEq, Clone, Copy)] 9 pub(crate) struct State(usize); 10 11 #[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)] 12 #[repr(usize)] 13 pub(crate) enum Lifecycle { 14 /// The thread pool is currently running 15 Running = 0, 16 17 /// The thread pool should shutdown once it reaches an idle state. 18 ShutdownOnIdle = 1, 19 20 /// The thread pool should start the process of shutting down. 21 ShutdownNow = 2, 22 } 23 24 /// Mask used to extract the number of futures from the state 25 const LIFECYCLE_MASK: usize = 0b11; 26 const NUM_FUTURES_MASK: usize = !LIFECYCLE_MASK; 27 const NUM_FUTURES_OFFSET: usize = 2; 28 29 /// Max number of futures the pool can handle. 30 pub(crate) const MAX_FUTURES: usize = usize::MAX >> NUM_FUTURES_OFFSET; 31 32 // ===== impl State ===== 33 34 impl State { 35 #[inline] new() -> State36 pub fn new() -> State { 37 State(0) 38 } 39 40 /// Returns the number of futures still pending completion. num_futures(&self) -> usize41 pub fn num_futures(&self) -> usize { 42 self.0 >> NUM_FUTURES_OFFSET 43 } 44 45 /// Increment the number of futures pending completion. 46 /// 47 /// Returns false on failure. inc_num_futures(&mut self)48 pub fn inc_num_futures(&mut self) { 49 debug_assert!(self.num_futures() < MAX_FUTURES); 50 debug_assert!(self.lifecycle() < Lifecycle::ShutdownNow); 51 52 self.0 += 1 << NUM_FUTURES_OFFSET; 53 } 54 55 /// Decrement the number of futures pending completion. dec_num_futures(&mut self)56 pub fn dec_num_futures(&mut self) { 57 let num_futures = self.num_futures(); 58 59 if num_futures == 0 { 60 // Already zero 61 return; 62 } 63 64 self.0 -= 1 << NUM_FUTURES_OFFSET; 65 66 if self.lifecycle() == Lifecycle::ShutdownOnIdle && num_futures == 1 { 67 self.set_lifecycle(Lifecycle::ShutdownNow); 68 } 69 } 70 71 /// Set the number of futures pending completion to zero clear_num_futures(&mut self)72 pub fn clear_num_futures(&mut self) { 73 self.0 = self.0 & LIFECYCLE_MASK; 74 } 75 lifecycle(&self) -> Lifecycle76 pub fn lifecycle(&self) -> Lifecycle { 77 (self.0 & LIFECYCLE_MASK).into() 78 } 79 set_lifecycle(&mut self, val: Lifecycle)80 pub fn set_lifecycle(&mut self, val: Lifecycle) { 81 self.0 = (self.0 & NUM_FUTURES_MASK) | (val as usize); 82 } 83 is_terminated(&self) -> bool84 pub fn is_terminated(&self) -> bool { 85 self.lifecycle() == Lifecycle::ShutdownNow && self.num_futures() == 0 86 } 87 } 88 89 impl From<usize> for State { from(src: usize) -> Self90 fn from(src: usize) -> Self { 91 State(src) 92 } 93 } 94 95 impl From<State> for usize { from(src: State) -> Self96 fn from(src: State) -> Self { 97 src.0 98 } 99 } 100 101 impl fmt::Debug for State { fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result102 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 103 fmt.debug_struct("pool::State") 104 .field("lifecycle", &self.lifecycle()) 105 .field("num_futures", &self.num_futures()) 106 .finish() 107 } 108 } 109 110 // ===== impl Lifecycle ===== 111 112 impl From<usize> for Lifecycle { from(src: usize) -> Lifecycle113 fn from(src: usize) -> Lifecycle { 114 use self::Lifecycle::*; 115 116 debug_assert!( 117 src == Running as usize 118 || src == ShutdownOnIdle as usize 119 || src == ShutdownNow as usize 120 ); 121 122 unsafe { ::std::mem::transmute(src) } 123 } 124 } 125 126 impl From<Lifecycle> for usize { from(src: Lifecycle) -> usize127 fn from(src: Lifecycle) -> usize { 128 let v = src as usize; 129 debug_assert!(v & LIFECYCLE_MASK == v); 130 v 131 } 132 } 133