dope-net 0.14.0

The manifold runtime
Documentation
use dope_core::driver::token::{Epoch, SlotIndex, Token};
use o3::marker::ThreadBound;

enum State {
    Fresh,
    Idle,
    NeedsRearm,
    Multishoted,
    Retired,
}

pub struct Multishot {
    state: State,
    epoch: Epoch,
    _thread: ThreadBound,
}

impl Default for Multishot {
    fn default() -> Self {
        Self {
            state: State::Fresh,
            epoch: Epoch::INITIAL,
            _thread: ThreadBound::NEW,
        }
    }
}

impl Multishot {
    pub fn begin(&mut self, route: u8, slot: SlotIndex) -> Option<Token> {
        if matches!(self.state, State::Multishoted | State::Retired) {
            return None;
        }
        if !matches!(self.state, State::Fresh) {
            let Some(epoch) = self.epoch.next() else {
                self.state = State::Retired;
                return None;
            };
            self.epoch = epoch;
        }
        Some(Token::new(route, slot, self.epoch))
    }

    pub fn settle(&mut self, pushed: bool) {
        self.state = if pushed {
            State::Multishoted
        } else {
            State::NeedsRearm
        };
    }

    pub fn complete(&mut self, more: bool) {
        if !more && matches!(self.state, State::Multishoted) {
            self.state = State::NeedsRearm;
        }
    }

    pub fn epoch_match(&self, token: Token, slot: SlotIndex) -> bool {
        token.slot() == slot && token.epoch() == Some(self.epoch)
    }

    pub fn request_rearm(&mut self) {
        self.state = State::NeedsRearm;
    }

    pub fn needs_rearm(&self) -> bool {
        matches!(self.state, State::NeedsRearm)
    }

    pub fn is_armed(&self) -> bool {
        matches!(self.state, State::Multishoted)
    }

    pub fn current_epoch(&self) -> Epoch {
        self.epoch
    }

    pub fn quiesce(&mut self) {
        if !matches!(self.state, State::Fresh) {
            self.state = State::Idle;
        }
    }
}