use std::sync::Arc;
use std::sync::atomic::{AtomicU16, AtomicU64, Ordering};
use parking_lot::Mutex;
use crate::transport::Transport;
#[derive(Debug)]
pub(crate) struct TransportSlot {
current: Mutex<Arc<dyn Transport>>,
generation: AtomicU64,
refused: AtomicU16,
}
const REFUSED: u16 = 0x100;
impl TransportSlot {
pub(crate) fn new(transport: Arc<dyn Transport>) -> Self {
TransportSlot {
current: Mutex::new(transport),
generation: AtomicU64::new(0),
refused: AtomicU16::new(0),
}
}
pub(crate) fn current(&self) -> Arc<dyn Transport> {
Arc::clone(&self.current.lock())
}
pub(crate) fn generation(&self) -> u64 {
self.generation.load(Ordering::Acquire)
}
pub(crate) fn swap(&self, transport: Arc<dyn Transport>) {
let old = std::mem::replace(&mut *self.current.lock(), transport);
self.generation.fetch_add(1, Ordering::Release);
self.accept();
old.wake_read();
}
pub(crate) fn refuse(&self, proto: u8) {
self.refused
.store(REFUSED | u16::from(proto), Ordering::Release);
}
pub(crate) fn accept(&self) {
self.refused.store(0, Ordering::Release);
}
pub(crate) fn refused(&self) -> Option<u8> {
let r = self.refused.load(Ordering::Acquire);
(r & REFUSED != 0).then_some(r as u8)
}
}