use std::sync::{Arc, Barrier};
#[must_use = "Not making sure that the diconnection happens before process exit is bad"]
pub struct DisconnectionHandle {
barrier: Option<Arc<Barrier>>,
waited_for: bool,
}
impl DisconnectionHandle {
pub(crate) fn with_barrier(barrier: Arc<Barrier>) -> DisconnectionHandle {
DisconnectionHandle {
barrier: Some(barrier),
waited_for: false,
}
}
pub(crate) fn without_barrier() -> DisconnectionHandle {
DisconnectionHandle {
barrier: None,
waited_for: false,
}
}
pub fn wait_for_proper_disconnection(mut self) {
Self::check_that_we_are_on_the_main_thread();
self.actually_wait_for_proper_disconnection();
}
pub fn wait_for_proper_disconnection_while_not_on_the_main_thread(mut self) {
self.actually_wait_for_proper_disconnection();
}
fn actually_wait_for_proper_disconnection(&mut self) {
if let Some(barrier) = &self.barrier {
barrier.wait();
}
self.waited_for = true;
}
fn check_that_we_are_on_the_main_thread() {
if let Some(is_main_thread_answer) = is_main_thread::is_main_thread() {
if is_main_thread_answer {
} else {
println!(
"Warning: `ClientDisconnectionHandle::wait_for_proper_disconnection` \
should be called in the main thread, see documentation as to why"
)
}
}
}
}
impl Drop for DisconnectionHandle {
fn drop(&mut self) {
if !self.waited_for {
if cfg!(feature = "forbid_handle_drop") {
if !std::thread::panicking() {
panic!(
"`ClientDisconnectionHandle` dropped \
instead of being intentionally waited for"
);
}
} else {
println!(
"Warning: `ClientDisconnectionHandle` dropped \
instead of being intentionally waited for"
);
Self::check_that_we_are_on_the_main_thread();
self.actually_wait_for_proper_disconnection();
}
}
}
}