use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
use super::AcceptedTurnInput;
#[cfg(doc)]
use super::InProcessRuntime;
#[derive(Clone, Debug)]
pub struct TurnSteering {
state: Arc<Mutex<TurnSteeringState>>,
}
#[derive(Debug)]
pub enum TurnSteeringPushError {
Closed(Box<AcceptedTurnInput>),
Full(Box<AcceptedTurnInput>),
}
const TURN_STEERING_CAPACITY: usize = 256;
#[derive(Debug, Default)]
struct TurnSteeringState {
open: bool,
inputs: VecDeque<AcceptedTurnInput>,
}
impl TurnSteering {
pub fn new() -> Self {
Self {
state: Arc::new(Mutex::new(TurnSteeringState {
open: true,
inputs: VecDeque::new(),
})),
}
}
pub fn try_push(
&self,
input: AcceptedTurnInput,
) -> std::result::Result<(), TurnSteeringPushError> {
let mut state = self.state.lock().expect("turn steering lock poisoned");
if !state.open {
return Err(TurnSteeringPushError::Closed(Box::new(input)));
}
if state.inputs.len() >= TURN_STEERING_CAPACITY {
return Err(TurnSteeringPushError::Full(Box::new(input)));
}
state.inputs.push_back(input);
Ok(())
}
pub(super) fn drain(&self) -> Vec<AcceptedTurnInput> {
let mut state = self.state.lock().expect("turn steering lock poisoned");
state.inputs.drain(..).collect()
}
pub(super) fn drain_or_close(&self) -> Vec<AcceptedTurnInput> {
let mut state = self.state.lock().expect("turn steering lock poisoned");
if state.inputs.is_empty() {
state.open = false;
return vec![];
}
state.inputs.drain(..).collect()
}
pub fn close(&self) {
self.state.lock().expect("turn steering lock poisoned").open = false;
}
pub fn close_and_drain(&self) -> Vec<AcceptedTurnInput> {
let mut state = self.state.lock().expect("turn steering lock poisoned");
state.open = false;
state.inputs.drain(..).collect()
}
}
impl Default for TurnSteering {
fn default() -> Self {
Self::new()
}
}