mod thread_unsafe;
use crate::{FallibleTryDropStrategy, TryDropStrategy};
use anyhow::Error;
use parking_lot::Mutex;
use std::marker::PhantomData;
pub use thread_unsafe::*;
#[cfg_attr(feature = "derives", derive(Debug, Default))]
pub struct AdHocMutDropStrategy<F: FnMut(crate::Error)>(pub Mutex<F>);
impl<F: FnMut(crate::Error)> AdHocMutDropStrategy<F> {
pub fn new(f: F) -> Self {
Self(Mutex::new(f))
}
}
impl<F: FnMut(crate::Error)> TryDropStrategy for AdHocMutDropStrategy<F> {
fn handle_error(&self, error: crate::Error) {
self.0.lock()(error)
}
}
impl<F: FnMut(crate::Error)> From<F> for AdHocMutDropStrategy<F> {
fn from(f: F) -> Self {
Self::new(f)
}
}
pub trait IntoAdHocMutDropStrategy: FnMut(crate::Error) + Sized {
fn into_drop_strategy(self) -> AdHocMutDropStrategy<Self> {
AdHocMutDropStrategy::new(self)
}
}
impl<T: FnMut(crate::Error)> IntoAdHocMutDropStrategy for T {}
#[cfg_attr(feature = "derives", derive(Debug, Default))]
pub struct AdHocMutFallibleDropStrategy<F, E>
where
F: FnMut(crate::Error) -> Result<(), E>,
E: Into<anyhow::Error>,
{
pub f: Mutex<F>,
_error: PhantomData<E>,
}
impl<F, E> AdHocMutFallibleDropStrategy<F, E>
where
F: FnMut(crate::Error) -> Result<(), E>,
E: Into<anyhow::Error>,
{
pub fn new(f: F) -> Self {
Self {
f: Mutex::new(f),
_error: PhantomData,
}
}
}
impl<F, E> FallibleTryDropStrategy for AdHocMutFallibleDropStrategy<F, E>
where
F: FnMut(crate::Error) -> Result<(), E>,
E: Into<anyhow::Error>,
{
type Error = E;
fn try_handle_error(&self, error: Error) -> Result<(), Self::Error> {
self.f.lock()(error)
}
}
impl<F, E> From<F> for AdHocMutFallibleDropStrategy<F, E>
where
F: FnMut(crate::Error) -> Result<(), E>,
E: Into<anyhow::Error>,
{
fn from(f: F) -> Self {
Self::new(f)
}
}
pub trait IntoAdHocMutFallibleDropStrategy<E: Into<anyhow::Error>>:
FnMut(crate::Error) -> Result<(), E> + Sized
{
fn into_drop_strategy(self) -> AdHocMutFallibleDropStrategy<Self, E> {
AdHocMutFallibleDropStrategy::new(self)
}
}
impl<T, E> IntoAdHocMutFallibleDropStrategy<E> for T
where
T: FnMut(crate::Error) -> Result<(), E>,
E: Into<anyhow::Error>,
{}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use crate::drop_strategies::PanicDropStrategy;
use crate::{LOAD_ORDERING, STORE_ORDERING};
use crate::test_utils::fallible;
use super::*;
static LOCK: Mutex<()> = parking_lot::const_mutex(());
#[test]
fn test_adhoc_mut_drop_strategy() {
let _lock = LOCK.lock();
let works = Arc::new(AtomicBool::new(false));
let w = Arc::clone(&works);
let strategy = AdHocMutDropStrategy::new(move |_| w.store(true, STORE_ORDERING));
crate::install_global_handlers(strategy, PanicDropStrategy::DEFAULT);
drop(fallible());
assert!(works.load(LOAD_ORDERING));
}
#[test]
fn test_into_adhoc_mut_drop_strategy() {
let _lock = LOCK.lock();
let works = Arc::new(AtomicBool::new(false));
let w = Arc::clone(&works);
let strategy = move |_| w.store(true, STORE_ORDERING);
let strategy = IntoAdHocMutDropStrategy::into_drop_strategy(strategy);
crate::install_global_handlers(strategy, PanicDropStrategy::DEFAULT);
drop(fallible());
assert!(works.load(LOAD_ORDERING));
}
#[test]
fn test_adhoc_mut_fallible_drop_strategy() {
let _lock = LOCK.lock();
let works = Arc::new(AtomicBool::new(false));
let w = Arc::clone(&works);
let strategy = AdHocMutFallibleDropStrategy::<_, crate::Error>::new(move |_| {
w.store(true, STORE_ORDERING);
Ok(())
});
crate::install_global_handlers(strategy, PanicDropStrategy::DEFAULT);
drop(fallible());
assert!(works.load(LOAD_ORDERING));
}
#[test]
fn test_into_adhoc_mut_fallible_drop_strategy() {
let _lock = LOCK.lock();
let works = Arc::new(AtomicBool::new(false));
let w = Arc::clone(&works);
let strategy = move |_| {
w.store(true, STORE_ORDERING);
Ok::<_, crate::Error>(())
};
let strategy = IntoAdHocMutFallibleDropStrategy::into_drop_strategy(strategy);
crate::install_global_handlers(strategy, PanicDropStrategy::DEFAULT);
drop(fallible());
assert!(works.load(LOAD_ORDERING));
}
}