use self::tls_executor::*;
use super::*;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
#[doc(hidden)]
#[derive(Debug)]
pub struct MachineAdapter {
id: Uuid,
once: AtomicBool,
disconnected: AtomicBool,
pub key: AtomicUsize,
pub state: SharedMachineState,
task_id: AtomicUsize,
normalized_adapter: Box<dyn MachineDependentAdapter>,
}
impl MachineAdapter {
#[inline]
pub fn new(adapter: Box<dyn MachineDependentAdapter>) -> Self {
Self {
id: uuid::Uuid::new_v4(),
once: AtomicBool::new(true),
disconnected: AtomicBool::new(false),
key: AtomicUsize::new(0),
state: SharedMachineState::default(),
task_id: AtomicUsize::new(0),
normalized_adapter: adapter,
}
}
#[inline]
pub const fn get_id(&self) -> Uuid { self.id }
#[inline]
pub fn get_and_clear_once(&self) -> bool { self.once.swap(false, Ordering::SeqCst) }
#[inline]
pub fn get_key(&self) -> usize { self.key.load(Ordering::SeqCst) }
#[inline]
pub fn set_disconnected(&self) { self.disconnected.store(true, Ordering::SeqCst); }
#[inline]
pub fn is_disconnected(&self) -> bool { self.disconnected.load(Ordering::SeqCst) }
#[inline]
pub fn get_state(&self) -> MachineState { self.state.get() }
#[inline]
pub fn is_dead(&self) -> bool { self.state.get() == MachineState::Dead }
#[inline]
pub fn is_running(&self) -> bool { self.state.get() == MachineState::Running }
#[inline]
pub fn is_send_blocked(&self) -> bool { self.state.get() == MachineState::SendBlock }
#[inline]
pub fn compare_and_exchange_state(&self, current: MachineState, new: MachineState) -> Result<MachineState, MachineState> {
self.state.compare_and_exchange(current, new)
}
pub fn clear_task_id(&self, stale: usize) {
if stale != 0 && stale != self.get_task_id() {
thread::sleep(Duration::from_millis(10));
panic!("stale != current");
}
self.task_id.store(0, Ordering::SeqCst);
}
pub fn get_task_id(&self) -> usize { self.task_id.load(Ordering::SeqCst) }
pub fn set_task_id(&self, id: usize) { self.task_id.store(id, Ordering::SeqCst); }
#[inline]
pub fn is_channel_empty(&self) -> bool { self.normalized_adapter.is_channel_empty() }
#[inline]
pub fn channel_len(&self) -> usize { self.normalized_adapter.channel_len() }
#[inline]
pub fn set_state(&self, new: MachineState) { self.state.set(new); }
#[inline]
pub fn clone_state(&self) -> SharedMachineState { self.state.clone() }
#[inline]
pub fn receive_cmd(&self, machine: &ShareableMachine, drop: bool, time_slice: Duration, stats: &mut ExecutorStats) {
self.normalized_adapter
.receive_cmd(machine, self.get_and_clear_once(), drop, time_slice, stats)
}
}
#[doc(hidden)]
pub type ShareableMachine = Arc<MachineAdapter>;
pub type WeakShareableMachine = Weak<MachineAdapter>;
#[doc(hidden)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, SmartDefault)]
#[allow(dead_code)]
pub enum MachineState {
#[default]
New,
Waiting,
Ready,
Running,
SendBlock,
RecvBlock,
Dead,
}
#[doc(hidden)]
pub type SharedMachineState = SharedProtectedObject<MachineState>;
#[doc(hidden)]
pub trait MachineDependentAdapter: Send + Sync + fmt::Debug {
fn receive_cmd(&self, machine: &ShareableMachine, once: bool, drop: bool, time_slice: Duration, stats: &mut ExecutorStats);
fn is_channel_empty(&self) -> bool;
fn channel_len(&self) -> usize;
}