try_drop/handlers/primary/
thread_local.rs

1//! Manage the thread local primary handler.
2
3use super::{Abstracter, DefaultOnUninit};
4use crate::handlers::common::handler::CommonHandler;
5use crate::handlers::common::thread_local::{
6    scope_guard::ScopeGuard as GenericScopeGuard, ThreadLocal as GenericThreadLocal,
7    ThreadLocalDefinition,
8};
9use crate::handlers::common::Primary;
10use crate::handlers::common::ThreadLocal as ThreadLocalScope;
11use crate::handlers::on_uninit::{ErrorOnUninit, FlagOnUninit, PanicOnUninit};
12use crate::handlers::uninit_error::UninitializedError;
13use crate::FallibleTryDropStrategy;
14use std::boxed::Box;
15use std::cell::{Cell, RefCell};
16
17use std::thread::LocalKey;
18use std::{convert, thread_local};
19
20#[cfg(feature = "ds-write")]
21use crate::handlers::common::thread_local::DefaultThreadLocalDefinition;
22
23#[cfg(feature = "ds-write")]
24use crate::handlers::on_uninit::UseDefaultOnUninit;
25
26/// A primary handler that uses the thread local scope.
27pub type ThreadLocalPrimaryHandler<OU = DefaultOnUninit> =
28    CommonHandler<OU, ThreadLocalScope, Primary>;
29
30/// The default thread local primary handler.
31pub static DEFAULT_THREAD_LOCAL_PRIMARY_HANDLER: ThreadLocalPrimaryHandler =
32    ThreadLocalPrimaryHandler::DEFAULT;
33
34impl_fallible_try_drop_strategy_for!(ThreadLocalPrimaryHandler
35where
36    Scope: ThreadLocalScope,
37    Definition: ThreadLocalDefinition
38);
39
40thread_local! {
41    static PRIMARY_HANDLER: RefCell<Option<Box<dyn ThreadLocalFallibleTryDropStrategy>>> = RefCell::new(None);
42    static LOCKED: Cell<bool> = Cell::new(false);
43}
44
45impl ThreadLocalDefinition for Primary {
46    const UNINITIALIZED_ERROR: &'static str =
47        "the thread local primary handler is not initialized yet";
48    const DYN: &'static str = "ThreadLocalFallibleTryDropStrategy";
49    type ThreadLocal = Box<dyn ThreadLocalFallibleTryDropStrategy>;
50
51    fn thread_local() -> &'static LocalKey<RefCell<Option<Self::ThreadLocal>>> {
52        &PRIMARY_HANDLER
53    }
54
55    fn locked() -> &'static LocalKey<Cell<bool>> {
56        &LOCKED
57    }
58}
59
60#[cfg(feature = "ds-write")]
61impl DefaultThreadLocalDefinition for Primary {
62    fn default() -> Self::ThreadLocal {
63        let mut strategy = crate::drop_strategies::WriteDropStrategy::stderr();
64        strategy.prelude("error: ");
65        Box::new(strategy)
66    }
67}
68
69impl<T: ThreadLocalFallibleTryDropStrategy> From<T>
70    for Box<dyn ThreadLocalFallibleTryDropStrategy>
71{
72    fn from(strategy: T) -> Self {
73        Box::new(strategy)
74    }
75}
76
77type ThreadLocal = GenericThreadLocal<Primary>;
78
79/// A scope guard for the thread local primary handler. It is used to set the thread local primary
80/// handler for the duration of the scope.
81pub type ScopeGuard = GenericScopeGuard<Primary>;
82
83/// Handy type alias to `Box<dyn ThreadLocalFallibleTryDropStrategy>`.
84pub type BoxDynFallibleTryDropStrategy = Box<dyn ThreadLocalFallibleTryDropStrategy>;
85
86thread_local_methods! {
87    ThreadLocal = ThreadLocal;
88    ScopeGuard = ScopeGuard;
89    GenericStrategy = ThreadLocalFallibleTryDropStrategy;
90    DynStrategy = BoxDynFallibleTryDropStrategy;
91    feature = "ds-write";
92
93    /// Install a new thread local primary handler.
94    install;
95
96    /// Install a new thread local primary handler. Must be a dynamic trait object.
97    install_dyn;
98
99    /// Get a reference to the current thread local primary handler.
100    ///
101    /// # Panics
102    /// If the thread local primary handler is not initialized yet, this function will panic.
103    read;
104
105    /// Try and get a reference to the current thread local primary handler.
106    ///
107    /// # Errors
108    /// If the thread local primary handler is not initialized yet, this function will return an
109    /// error.
110    try_read;
111
112    /// Get a reference to the current thread local primary handler.
113    ///
114    /// If the current thread local primary handler is not initialized yet, this function will
115    /// set it to the default primary handler.
116    read_or_default;
117
118    /// Get a mutable reference to the current thread local primary handler.
119    ///
120    /// # Panics
121    /// If the thread local primary handler is not initialized yet, this function will panic.
122    write;
123
124    /// Try and get a mutable reference to the current thread local primary handler.
125    ///
126    /// # Errors
127    /// If the thread local primary handler is not initialized yet, this function will return an
128    try_write;
129
130    /// Get a mutable reference to the current thread local primary handler.
131    ///
132    /// If the current thread local primary handler is not initialized yet, this function will
133    /// set it to the default primary handler.
134    write_or_default;
135
136    /// Uninstall the current thread local primary handler.
137    uninstall;
138
139    /// Take the current thread local primary handler, if there is any initalized.
140    take;
141
142    /// Replace the current thread local primary handler with the given one, returning the old one
143    /// if any.
144    replace;
145
146    /// Replace the current thread local primary handler with the given one, returning the old one
147    /// if any. Must be a dynamic trait object.
148    replace_dyn;
149
150    /// Sets the thread local primary handler to the given one for the duration of the given scope.
151    /// For more advanced usage, see the [`ScopeGuard`] type.
152    scope;
153
154    /// Sets the thread local primary handler to the given one for the duration of the given scope.
155    /// For more advanced usage, see the [`ScopeGuard`] type. Must be a dynamic trait object.
156    scope_dyn;
157}