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}