try_drop/handlers/common/
global.rs

1pub(crate) mod imports {}
2
3use crate::handlers::common::Handler;
4use crate::handlers::UninitializedError;
5use parking_lot::{
6    MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, RwLockWriteGuard,
7};
8use std::marker::PhantomData;
9
10pub trait GlobalDefinition: Handler {
11    const UNINITIALIZED_ERROR: &'static str;
12    type Global: 'static;
13
14    fn global() -> &'static RwLock<Option<Self::Global>>;
15}
16
17pub trait DefaultGlobalDefinition: GlobalDefinition {
18    fn default() -> Self::Global;
19}
20
21pub struct Global<T: GlobalDefinition>(PhantomData<T>);
22
23impl<T: GlobalDefinition> Global<T> {
24    pub fn install_dyn(strategy: T::Global) {
25        T::global().write().replace(strategy);
26    }
27
28    pub fn install(strategy: impl Into<T::Global>) {
29        Self::install_dyn(strategy.into())
30    }
31
32    pub fn try_read() -> Result<MappedRwLockReadGuard<'static, T::Global>, UninitializedError> {
33        let global = T::global().read();
34
35        if global.is_some() {
36            Ok(RwLockReadGuard::map(global, |global| {
37                global.as_ref().unwrap()
38            }))
39        } else {
40            Err(UninitializedError(()))
41        }
42    }
43
44    pub fn read() -> MappedRwLockReadGuard<'static, T::Global> {
45        Self::try_read().expect(T::UNINITIALIZED_ERROR)
46    }
47
48    pub fn try_write() -> Result<MappedRwLockWriteGuard<'static, T::Global>, UninitializedError> {
49        let global = T::global().write();
50
51        if global.is_some() {
52            Ok(RwLockWriteGuard::map(global, |global| {
53                global.as_mut().unwrap()
54            }))
55        } else {
56            Err(UninitializedError(()))
57        }
58    }
59
60    pub fn write() -> MappedRwLockWriteGuard<'static, T::Global> {
61        Self::try_write().expect(T::UNINITIALIZED_ERROR)
62    }
63
64    pub fn uninstall() {
65        *T::global().write() = None
66    }
67}
68
69impl<T: DefaultGlobalDefinition> Global<T> {
70    pub fn read_or_default() -> MappedRwLockReadGuard<'static, T::Global> {
71        drop(Self::write_or_default());
72        Self::read()
73    }
74
75    pub fn write_or_default() -> MappedRwLockWriteGuard<'static, T::Global> {
76        RwLockWriteGuard::map(T::global().write(), |drop_strategy| {
77            drop_strategy.get_or_insert_with(T::default)
78        })
79    }
80}
81
82macro_rules! global_methods {
83    (
84        Global = $global:ident;
85        GenericStrategy = $generic_strategy:ident;
86        DynStrategy = $dyn_strategy:ident;
87        feature = $feature:literal;
88
89        $(#[$($install_dyn_tt:tt)*])*
90        install_dyn;
91
92        $(#[$($install_tt:tt)*])*
93        install;
94
95        $(#[$($try_read_tt:tt)*])*
96        try_read;
97
98        $(#[$($read_tt:tt)*])*
99        read;
100
101        $(#[$($try_write_tt:tt)*])*
102        try_write;
103
104        $(#[$($write_tt:tt)*])*
105        write;
106
107        $(#[$($uninstall_tt:tt)*])*
108        uninstall;
109
110        $(#[$($read_or_default_tt:tt)*])*
111        read_or_default;
112
113        $(#[$($write_or_default_tt:tt)*])*
114        write_or_default;
115    ) => {
116        #[allow(unused_imports)]
117        use $crate::handlers::common::global::imports::*;
118
119        $(#[$($install_dyn_tt)*])*
120        pub fn install_dyn(strategy: $dyn_strategy) {
121            $global::install_dyn(strategy)
122        }
123
124        $(#[$($install_tt)*])*
125        pub fn install(strategy: impl $generic_strategy) {
126            $global::install(strategy)
127        }
128
129        $(#[$($try_read_tt)*])*
130        pub fn try_read() -> Result<MappedRwLockReadGuard<'static, $dyn_strategy>, UninitializedError> {
131            $global::try_read()
132        }
133
134        $(#[$($read_tt)*])*
135        pub fn read() -> MappedRwLockReadGuard<'static, $dyn_strategy> {
136            $global::read()
137        }
138
139        $(#[$($try_write_tt)*])*
140        pub fn try_write() -> Result<MappedRwLockWriteGuard<'static, $dyn_strategy>, UninitializedError> {
141            $global::try_write()
142        }
143
144        $(#[$($write_tt)*])*
145        pub fn write() -> MappedRwLockWriteGuard<'static, $dyn_strategy> {
146            $global::write()
147        }
148
149        $(#[$($uninstall_tt)*])*
150        pub fn uninstall() {
151            $global::uninstall()
152        }
153
154        $(#[$($read_or_default_tt)*])*
155        #[cfg(feature = $feature)]
156        pub fn read_or_default() -> MappedRwLockReadGuard<'static, $dyn_strategy> {
157            $global::read_or_default()
158        }
159
160        $(#[$($write_or_default_tt)*])*
161        #[cfg(feature = $feature)]
162        pub fn write_or_default() -> MappedRwLockWriteGuard<'static, $dyn_strategy> {
163            $global::write_or_default()
164        }
165    };
166}