use crate::tii_builder::ThreadAdapterJoinHandle;
use crate::tii_server::ConnectionStreamMetadata;
use std::any::Any;
use std::fmt::{Display, Formatter};
use std::sync::atomic::Ordering::SeqCst;
use std::sync::atomic::{AtomicBool, AtomicUsize};
use std::sync::{Arc, Condvar, Mutex};
use std::time::Duration;
pub(crate) const CONNECTOR_SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(5);
pub(crate) const CONNECTOR_SHUTDOWN_FLAG_POLLING_INTERVAL: Duration = Duration::from_secs(1);
pub trait Connector {
fn shutdown(&self);
fn is_marked_for_shutdown(&self) -> bool;
fn is_shutting_down(&self) -> bool;
fn is_shutdown(&self) -> bool;
fn shutdown_and_join(&self, timeout: Option<Duration>) -> bool;
fn join(&self, timeout: Option<Duration>) -> bool;
}
#[non_exhaustive]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum ConnectorMeta {
Tcp,
#[cfg(feature = "tls")]
TlsTcp,
#[cfg(unix)]
Unix,
#[cfg(unix)]
#[cfg(feature = "tls")]
TlsUnix,
}
impl ConnectionStreamMetadata for ConnectorMeta {
fn as_any(&self) -> &dyn Any {
self
}
}
impl Display for ConnectorMeta {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self, f)
}
}
#[derive(Debug)]
pub(crate) struct ActiveConnection {
pub(crate) id: u128,
pub(crate) hdl: Option<ThreadAdapterJoinHandle>,
pub(crate) done_flag: Arc<AtomicBool>,
}
#[derive(Debug)]
pub(crate) struct ConnWait {
mutex: Mutex<()>,
value: AtomicUsize,
await_cond: Condvar,
}
impl Default for ConnWait {
fn default() -> Self {
ConnWait { mutex: Mutex::new(()), value: AtomicUsize::new(0), await_cond: Condvar::new() }
}
}
impl ConnWait {
pub fn signal(&self, value: usize) {
self.value.store(value, SeqCst);
if let Ok(guard) = self.mutex.lock() {
self.await_cond.notify_all();
drop(guard);
}
}
pub fn is_done(&self, value: usize) -> bool {
self.value.load(SeqCst) >= value
}
fn wait_forever(&self, value: usize) -> bool {
if self.is_done(value) {
return true;
}
let Ok(mut guard) = self.mutex.lock() else {
return false;
};
loop {
if self.is_done(value) {
return true;
}
guard = match self.await_cond.wait(guard) {
Ok(guard) => guard,
Err(_) => {
return false;
}
}
}
}
pub fn wait(&self, value: usize, timeout: Option<Duration>) -> bool {
let Some(timeout) = timeout else {
return self.wait_forever(value);
};
if self.is_done(value) {
return true;
}
let Ok(mut guard) = self.mutex.lock() else {
return false;
};
loop {
if self.is_done(value) {
return true;
}
guard = match self.await_cond.wait_timeout(guard, timeout) {
Ok((guard, tm)) => {
if tm.timed_out() {
return false;
}
guard
}
Err(_) => {
return false;
}
}
}
}
}