use std::{fmt, usize};
#[derive(Eq, PartialEq, Clone, Copy)]
pub(crate) struct State(usize);
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
#[repr(usize)]
pub(crate) enum Lifecycle {
Running = 0,
ShutdownOnIdle = 1,
ShutdownNow = 2,
}
const LIFECYCLE_MASK: usize = 0b11;
const NUM_FUTURES_MASK: usize = !LIFECYCLE_MASK;
const NUM_FUTURES_OFFSET: usize = 2;
pub(crate) const MAX_FUTURES: usize = usize::MAX >> NUM_FUTURES_OFFSET;
impl State {
#[inline]
pub fn new() -> State {
State(0)
}
pub fn num_futures(&self) -> usize {
self.0 >> NUM_FUTURES_OFFSET
}
pub fn inc_num_futures(&mut self) {
debug_assert!(self.num_futures() < MAX_FUTURES);
debug_assert!(self.lifecycle() < Lifecycle::ShutdownNow);
self.0 += 1 << NUM_FUTURES_OFFSET;
}
pub fn dec_num_futures(&mut self) {
let num_futures = self.num_futures();
if num_futures == 0 {
return;
}
self.0 -= 1 << NUM_FUTURES_OFFSET;
if self.lifecycle() == Lifecycle::ShutdownOnIdle && num_futures == 1 {
self.set_lifecycle(Lifecycle::ShutdownNow);
}
}
pub fn clear_num_futures(&mut self) {
self.0 = self.0 & LIFECYCLE_MASK;
}
pub fn lifecycle(&self) -> Lifecycle {
(self.0 & LIFECYCLE_MASK).into()
}
pub fn set_lifecycle(&mut self, val: Lifecycle) {
self.0 = (self.0 & NUM_FUTURES_MASK) | (val as usize);
}
pub fn is_terminated(&self) -> bool {
self.lifecycle() == Lifecycle::ShutdownNow && self.num_futures() == 0
}
}
impl From<usize> for State {
fn from(src: usize) -> Self {
State(src)
}
}
impl From<State> for usize {
fn from(src: State) -> Self {
src.0
}
}
impl fmt::Debug for State {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("pool::State")
.field("lifecycle", &self.lifecycle())
.field("num_futures", &self.num_futures())
.finish()
}
}
impl From<usize> for Lifecycle {
fn from(src: usize) -> Lifecycle {
use self::Lifecycle::*;
debug_assert!(
src == Running as usize
|| src == ShutdownOnIdle as usize
|| src == ShutdownNow as usize
);
unsafe { ::std::mem::transmute(src) }
}
}
impl From<Lifecycle> for usize {
fn from(src: Lifecycle) -> usize {
let v = src as usize;
debug_assert!(v & LIFECYCLE_MASK == v);
v
}
}