use std::sync::{Condvar, Mutex, PoisonError};
use crate::errors::Error;
use crate::transport::common::{lock, SessionState};
#[derive(Debug)]
pub(crate) struct ConnectionSignal {
state: Mutex<SessionState>,
changed: Condvar,
}
impl Default for ConnectionSignal {
fn default() -> Self {
Self {
state: Mutex::new(SessionState::Connected),
changed: Condvar::new(),
}
}
}
impl ConnectionSignal {
pub(crate) fn is_connected(&self) -> bool {
*lock(&self.state) == SessionState::Connected
}
pub(crate) fn set_connected(&self) {
self.set(SessionState::Connected);
}
pub(crate) fn set_disconnected(&self) {
self.set(SessionState::Disconnected);
}
pub(crate) fn shutdown(&self) {
self.set(SessionState::ShutDown);
}
pub(crate) fn fail(&self) {
self.set(SessionState::Failed);
}
pub(crate) fn check_ended(&self) -> Result<(), Error> {
lock(&self.state).check_ended()
}
pub(crate) fn check(&self) -> Result<(), Error> {
lock(&self.state).check()
}
pub(crate) fn wait_connected(&self) -> Result<(), Error> {
let mut state = lock(&self.state);
while *state == SessionState::Disconnected {
state = self.changed.wait(state).unwrap_or_else(PoisonError::into_inner);
}
state.check()
}
fn set(&self, new_state: SessionState) {
let mut state = lock(&self.state);
if state.is_terminal() {
return;
}
*state = new_state;
self.changed.notify_all();
}
}
#[cfg(test)]
#[path = "connection_signal_tests.rs"]
mod tests;