try_drop/handlers/fallback/
shim.rs

1//! Manage the shim fallback handler.
2
3#[cfg(feature = "ds-panic")]
4mod imp {
5    use super::ShimFallbackHandler;
6    use crate::drop_strategies::PanicDropStrategy;
7    use crate::handlers::common::handler::CommonHandler;
8    use crate::handlers::common::shim::UseDefaultOnUninitShim;
9    use crate::handlers::common::Fallback;
10    use crate::TryDropStrategy;
11    use once_cell::sync::Lazy;
12
13    /// The default thing to do when both the primary and fallback handlers are uninitialized,
14    /// that is to use the inner cache to handle the error instead.
15    pub type DefaultOnUninit = UseDefaultOnUninitShim<Fallback>;
16
17    impl ShimFallbackHandler<UseDefaultOnUninitShim<Fallback>> {
18        /// See [`Self::use_default_on_uninit`].
19        pub const USE_DEFAULT_ON_UNINIT: Self = Self {
20            global: CommonHandler::FLAG_ON_UNINIT,
21            thread_local: CommonHandler::FLAG_ON_UNINIT,
22            extra_data: Lazy::new(|| PanicDropStrategy::DEFAULT),
23        };
24
25        /// If both the primary and fallback handlers are uninitialized, use the inner cache to
26        /// handle the error instead.
27        pub const fn use_default_on_uninit() -> Self {
28            Self::USE_DEFAULT_ON_UNINIT
29        }
30
31        fn cache(&self) -> &PanicDropStrategy {
32            &self.extra_data
33        }
34    }
35
36    impl ShimFallbackHandler<DefaultOnUninit> {
37        /// The default thing to do when both the primary and fallback handlers are uninitialized.
38        pub const DEFAULT: Self = Self::USE_DEFAULT_ON_UNINIT;
39    }
40
41    impl TryDropStrategy for ShimFallbackHandler<UseDefaultOnUninitShim<Fallback>> {
42        fn handle_error(&self, error: crate::Error) {
43            self.on_all_uninit(error, |error| self.cache().handle_error(error.into()))
44        }
45    }
46}
47#[cfg(not(feature = "ds-panic"))]
48mod imp {
49    use super::ShimFallbackHandler;
50    use crate::handlers::on_uninit::PanicOnUninit;
51
52    /// The default thing to do when the primary and fallback handlers are uninitialized, that is to
53    /// panic.
54    pub type DefaultOnUninit = PanicOnUninit;
55
56    impl ShimFallbackHandler<DefaultOnUninit> {
57        /// The default thing to do when the primary and fallback handlers are uninitialized.
58        pub const DEFAULT: Self = Self::PANIC_ON_UNINIT;
59    }
60}
61
62use crate::adapters::ArcError;
63use crate::handlers::common::handler::CommonShimHandler;
64use crate::handlers::common::shim::OnUninitShim;
65use crate::handlers::common::Fallback;
66use crate::handlers::on_uninit::{DoNothingOnUninit, FlagOnUninit, PanicOnUninit};
67use crate::TryDropStrategy;
68pub use imp::DefaultOnUninit;
69
70/// A fallback handler which uses both the global and thread-local scopes, with the thread-local
71/// scope taking precedence.
72pub type ShimFallbackHandler<OU = DefaultOnUninit> = CommonShimHandler<OU, Fallback>;
73
74/// The default shim fallback handler.
75pub static DEFAULT_SHIM_FALLBACK_HANDLER: ShimFallbackHandler = ShimFallbackHandler::DEFAULT;
76
77impl<OU: OnUninitShim> ShimFallbackHandler<OU> {
78    fn on_all_uninit(&self, error: anyhow::Error, f: impl FnOnce(ArcError)) {
79        let error = ArcError::new(error);
80        self.thread_local
81            .handle_error(ArcError::clone(&error).into());
82
83        if self.thread_local.last_drop_failed() {
84            self.global.handle_error(ArcError::clone(&error).into());
85
86            if self.global.last_drop_failed() {
87                f(error)
88            }
89        }
90    }
91}
92
93impl TryDropStrategy for ShimFallbackHandler<PanicOnUninit> {
94    fn handle_error(&self, error: crate::Error) {
95        self.on_all_uninit(
96            error,
97            |error| panic!("neither the fallback thread local nor the fallback global handlers are initialized (but here's the drop error anyway: {error})")
98        )
99    }
100}
101
102impl TryDropStrategy for ShimFallbackHandler<DoNothingOnUninit> {
103    fn handle_error(&self, error: crate::Error) {
104        self.on_all_uninit(error, |_| ())
105    }
106}
107
108impl TryDropStrategy for ShimFallbackHandler<FlagOnUninit> {
109    fn handle_error(&self, error: crate::Error) {
110        let mut last_drop_failed = false;
111        self.on_all_uninit(error, |_| last_drop_failed = true);
112        self.set_last_drop_failed(last_drop_failed);
113    }
114}