moto_runtime/external/scopeguard.rs
1extern crate core as std;
2
3use std::fmt;
4use std::marker::PhantomData;
5use std::mem::ManuallyDrop;
6use std::ops::{Deref, DerefMut};
7use std::ptr;
8
9/// Controls in which cases the associated code should be run
10pub trait Strategy {
11 /// Return `true` if the guard’s associated code should run
12 /// (in the context where this method is called).
13 fn should_run() -> bool;
14}
15
16/// Always run on scope exit.
17///
18/// “Always” run: on regular exit from a scope or on unwinding from a panic.
19/// Can not run on abort, process exit, and other catastrophic events where
20/// destructors don’t run.
21#[derive(Debug)]
22pub enum Always {}
23
24impl Strategy for Always {
25 #[inline(always)]
26 fn should_run() -> bool {
27 true
28 }
29}
30
31/// Macro to create a `ScopeGuard` (always run).
32///
33/// The macro takes statements, which are the body of a closure
34/// that will run when the scope is exited.
35#[macro_export]
36macro_rules! defer {
37 ($($t:tt)*) => {
38 let _guard = $crate::external::scopeguard::guard((), |()| { $($t)* });
39 };
40}
41
42pub(crate) use defer;
43
44/// `ScopeGuard` is a scope guard that may own a protected value.
45///
46/// If you place a guard in a local variable, the closure can
47/// run regardless how you leave the scope — through regular return or panic
48/// (except if panic or other code aborts; so as long as destructors run).
49/// It is run only once.
50///
51/// The `S` parameter for [`Strategy`](trait.Strategy.html) determines if
52/// the closure actually runs.
53///
54/// The guard's closure will be called with the held value in the destructor.
55///
56/// The `ScopeGuard` implements `Deref` so that you can access the inner value.
57pub struct ScopeGuard<T, F, S = Always>
58where
59 F: FnOnce(T),
60 S: Strategy,
61{
62 value: ManuallyDrop<T>,
63 dropfn: ManuallyDrop<F>,
64 // fn(S) -> S is used, so that the S is not taken into account for auto traits.
65 strategy: PhantomData<fn(S) -> S>,
66}
67
68impl<T, F, S> ScopeGuard<T, F, S>
69where
70 F: FnOnce(T),
71 S: Strategy,
72{
73 /// Create a `ScopeGuard` that owns `v` (accessible through deref) and calls
74 /// `dropfn` when its destructor runs.
75 ///
76 /// The `Strategy` decides whether the scope guard's closure should run.
77 #[inline]
78 #[must_use]
79 pub fn with_strategy(v: T, dropfn: F) -> ScopeGuard<T, F, S> {
80 ScopeGuard {
81 value: ManuallyDrop::new(v),
82 dropfn: ManuallyDrop::new(dropfn),
83 strategy: PhantomData,
84 }
85 }
86
87 /// “Defuse” the guard and extract the value without calling the closure.
88 ///
89 /// ```
90 /// extern crate scopeguard;
91 ///
92 /// use scopeguard::{guard, ScopeGuard};
93 ///
94 /// fn conditional() -> bool { true }
95 ///
96 /// fn main() {
97 /// let mut guard = guard(Vec::new(), |mut v| v.clear());
98 /// guard.push(1);
99 ///
100 /// if conditional() {
101 /// // a condition maybe makes us decide to
102 /// // “defuse” the guard and get back its inner parts
103 /// let value = ScopeGuard::into_inner(guard);
104 /// } else {
105 /// // guard still exists in this branch
106 /// }
107 /// }
108 /// ```
109 #[inline]
110 #[allow(unused)]
111 pub fn into_inner(guard: Self) -> T {
112 // Cannot move out of `Drop`-implementing types,
113 // so `ptr::read` the value and forget the guard.
114 let mut guard = ManuallyDrop::new(guard);
115 unsafe {
116 let value = ptr::read(&*guard.value);
117 // Drop the closure after `value` has been read, so that if the
118 // closure's `drop` function panics, unwinding still tries to drop
119 // `value`.
120 ManuallyDrop::drop(&mut guard.dropfn);
121 value
122 }
123 }
124}
125
126/// Create a new `ScopeGuard` owning `v` and with deferred closure `dropfn`.
127#[inline]
128#[must_use]
129pub fn guard<T, F>(v: T, dropfn: F) -> ScopeGuard<T, F, Always>
130where
131 F: FnOnce(T),
132{
133 ScopeGuard::with_strategy(v, dropfn)
134}
135
136// ScopeGuard can be Sync even if F isn't because the closure is
137// not accessible from references.
138// The guard does not store any instance of S, so it is also irrelevant.
139unsafe impl<T, F, S> Sync for ScopeGuard<T, F, S>
140where
141 T: Sync,
142 F: FnOnce(T),
143 S: Strategy,
144{
145}
146
147impl<T, F, S> Deref for ScopeGuard<T, F, S>
148where
149 F: FnOnce(T),
150 S: Strategy,
151{
152 type Target = T;
153
154 fn deref(&self) -> &T {
155 &*self.value
156 }
157}
158
159impl<T, F, S> DerefMut for ScopeGuard<T, F, S>
160where
161 F: FnOnce(T),
162 S: Strategy,
163{
164 fn deref_mut(&mut self) -> &mut T {
165 &mut *self.value
166 }
167}
168
169impl<T, F, S> Drop for ScopeGuard<T, F, S>
170where
171 F: FnOnce(T),
172 S: Strategy,
173{
174 fn drop(&mut self) {
175 // This is OK because the fields are `ManuallyDrop`s
176 // which will not be dropped by the compiler.
177 let (value, dropfn) = unsafe { (ptr::read(&*self.value), ptr::read(&*self.dropfn)) };
178 if S::should_run() {
179 dropfn(value);
180 }
181 }
182}
183
184impl<T, F, S> fmt::Debug for ScopeGuard<T, F, S>
185where
186 T: fmt::Debug,
187 F: FnOnce(T),
188 S: Strategy,
189{
190 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191 f.debug_struct(stringify!(ScopeGuard))
192 .field("value", &*self.value)
193 .finish()
194 }
195}