try_drop/handlers/common/
global.rs1pub(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}