try_drop/drop_strategies/adhoc/fn_mut/
thread_unsafe.rs

1use crate::{FallibleTryDropStrategy, TryDropStrategy};
2use anyhow::Error;
3use std::cell::RefCell;
4
5/// A drop strategy which uses a function to handle errors. This is less flexible than its thread
6/// safe counterpart however there is less overhead.
7#[cfg_attr(
8    feature = "derives",
9    derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)
10)]
11pub struct ThreadUnsafeAdHocMutDropStrategy<F: FnMut(crate::Error)>(pub RefCell<F>);
12
13impl<F: FnMut(crate::Error)> ThreadUnsafeAdHocMutDropStrategy<F> {
14    /// Create a new thread unsafe adhoc mut drop strategy.
15    pub fn new(f: F) -> Self {
16        Self(RefCell::new(f))
17    }
18}
19
20impl<F: FnMut(crate::Error)> TryDropStrategy for ThreadUnsafeAdHocMutDropStrategy<F> {
21    fn handle_error(&self, error: crate::Error) {
22        self.0.borrow_mut()(error)
23    }
24}
25
26/// Turn this type into a [`ThreadUnsafeAdHocMutDropStrategy`].
27pub trait IntoThreadUnsafeAdHocMutDropStrategy: FnMut(crate::Error) + Sized {
28    /// Turn this type into a [`ThreadUnsafeAdHocMutDropStrategy`].
29    fn into_drop_strategy(self) -> ThreadUnsafeAdHocMutDropStrategy<Self> {
30        ThreadUnsafeAdHocMutDropStrategy::new(self)
31    }
32}
33
34impl<F: FnMut(crate::Error)> IntoThreadUnsafeAdHocMutDropStrategy for F {}
35
36/// A fallible drop strategy which uses a function to handle errors. This is less flexible than its
37/// thread safe counterpart however there is less overhead.
38#[cfg_attr(
39    feature = "derives",
40    derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)
41)]
42pub struct ThreadUnsafeAdHocMutFallibleDropStrategy<F, E>(pub RefCell<F>)
43where
44    F: FnMut(crate::Error) -> Result<(), E>,
45    E: Into<crate::Error>;
46
47impl<F, E> ThreadUnsafeAdHocMutFallibleDropStrategy<F, E>
48where
49    F: FnMut(crate::Error) -> Result<(), E>,
50    E: Into<crate::Error>,
51{
52    /// Create a new thread unsafe adhoc mut fallible drop strategy.
53    pub fn new(f: F) -> Self {
54        Self(RefCell::new(f))
55    }
56}
57
58impl<F, E> FallibleTryDropStrategy for ThreadUnsafeAdHocMutFallibleDropStrategy<F, E>
59where
60    F: FnMut(crate::Error) -> Result<(), E>,
61    E: Into<crate::Error>,
62{
63    type Error = E;
64
65    fn try_handle_error(&self, error: Error) -> Result<(), Self::Error> {
66        self.0.borrow_mut()(error)
67    }
68}
69
70/// Turn this type into a [`ThreadUnsafeAdHocMutFallibleDropStrategy`].
71pub trait IntoThreadUnsafeAdHocMutFallibleDropStrategy<E: Into<anyhow::Error>>:
72    FnMut(crate::Error) -> Result<(), E> + Sized
73{
74    /// Turn this type into a [`ThreadUnsafeAdHocMutFallibleDropStrategy`].
75    fn into_drop_strategy(self) -> ThreadUnsafeAdHocMutFallibleDropStrategy<Self, E> {
76        ThreadUnsafeAdHocMutFallibleDropStrategy::new(self)
77    }
78}
79
80impl<T, E> IntoThreadUnsafeAdHocMutFallibleDropStrategy<E> for T
81where
82    T: FnMut(crate::Error) -> Result<(), E>,
83    E: Into<crate::Error>,
84{}
85
86#[cfg(test)]
87mod tests {
88    use std::cell::Cell;
89    use std::rc::Rc;
90    use crate::drop_strategies::PanicDropStrategy;
91    use crate::test_utils::fallible;
92    use super::*;
93
94    #[test]
95    fn test_thread_unsafe_adhoc_mut_drop_strategy() {
96        let works = Rc::new(Cell::new(false));
97        let w = Rc::clone(&works);
98        let strategy = ThreadUnsafeAdHocMutDropStrategy::new(move |_| w.set(true));
99        crate::install_thread_local_handlers(strategy, PanicDropStrategy::DEFAULT);
100        drop(fallible());
101        assert!(works.get());
102    }
103
104    #[test]
105    fn test_into_thread_unsafe_adhoc_mut_drop_strategy() {
106        let works = Rc::new(Cell::new(false));
107        let w = Rc::clone(&works);
108        let strategy = move |_| w.set(true);
109        let strategy = IntoThreadUnsafeAdHocMutDropStrategy::into_drop_strategy(strategy);
110        crate::install_thread_local_handlers(strategy, PanicDropStrategy::DEFAULT);
111        drop(fallible());
112        assert!(works.get());
113    }
114
115    #[test]
116    fn test_thread_unsafe_adhoc_mut_fallible_drop_strategy() {
117        let works = Rc::new(Cell::new(false));
118        let w = Rc::clone(&works);
119        let strategy = ThreadUnsafeAdHocMutFallibleDropStrategy::<_, crate::Error>::new(move |_| {
120            w.set(true);
121            Ok(())
122        });
123        crate::install_thread_local_handlers(strategy, PanicDropStrategy::DEFAULT);
124        drop(fallible());
125        assert!(works.get());
126    }
127
128    #[test]
129    fn test_into_thread_unsafe_adhoc_mut_fallible_drop_strategy() {
130        let works = Rc::new(Cell::new(false));
131        let w = Rc::clone(&works);
132        let strategy = move |_| {
133            w.set(true);
134            Ok::<_, crate::Error>(())
135        };
136        let strategy = IntoThreadUnsafeAdHocMutFallibleDropStrategy::into_drop_strategy(strategy);
137        crate::install_thread_local_handlers(strategy, PanicDropStrategy::DEFAULT);
138        drop(fallible());
139        assert!(works.get());
140    }
141}