1 #![cfg_attr(not(any(test, feature = "use_std")), no_std)]
2 #![doc(html_root_url = "https://docs.rs/scopeguard/1/")]
3 
4 //! A scope guard will run a given closure when it goes out of scope,
5 //! even if the code between panics.
6 //! (as long as panic doesn't abort)
7 //!
8 //! # Examples
9 //!
10 //! ## Hello World
11 //!
12 //! This example creates a scope guard with an example function:
13 //!
14 //! ```
15 //! extern crate scopeguard;
16 //!
17 //! fn f() {
18 //!     let _guard = scopeguard::guard((), |_| {
19 //!         println!("Hello Scope Exit!");
20 //!     });
21 //!
22 //!     // rest of the code here.
23 //!
24 //!     // Here, at the end of `_guard`'s scope, the guard's closure is called.
25 //!     // It is also called if we exit this scope through unwinding instead.
26 //! }
27 //! # fn main() {
28 //! #    f();
29 //! # }
30 //! ```
31 //!
32 //! ## `defer!`
33 //!
34 //! Use the `defer` macro to run an operation at scope exit,
35 //! either regular scope exit or during unwinding from a panic.
36 //!
37 //! ```
38 //! #[macro_use(defer)] extern crate scopeguard;
39 //!
40 //! use std::cell::Cell;
41 //!
42 //! fn main() {
43 //!     // use a cell to observe drops during and after the scope guard is active
44 //!     let drop_counter = Cell::new(0);
45 //!     {
46 //!         // Create a scope guard using `defer!` for the current scope
47 //!         defer! {
48 //!             drop_counter.set(1 + drop_counter.get());
49 //!         }
50 //!
51 //!         // Do regular operations here in the meantime.
52 //!
53 //!         // Just before scope exit: it hasn't run yet.
54 //!         assert_eq!(drop_counter.get(), 0);
55 //!
56 //!         // The following scope end is where the defer closure is called
57 //!     }
58 //!     assert_eq!(drop_counter.get(), 1);
59 //! }
60 //! ```
61 //!
62 //! ## Scope Guard with Value
63 //!
64 //! If the scope guard closure needs to access an outer value that is also
65 //! mutated outside of the scope guard, then you may want to use the scope guard
66 //! with a value. The guard works like a smart pointer, so the inner value can
67 //! be accessed by reference or by mutable reference.
68 //!
69 //! ### 1. The guard owns a file
70 //!
71 //! In this example, the scope guard owns a file and ensures pending writes are
72 //! synced at scope exit.
73 //!
74 //! ```
75 //! extern crate scopeguard;
76 //!
77 //! use std::fs::*;
78 //! use std::io::{self, Write};
79 //! # // Mock file so that we don't actually write a file
80 //! # struct MockFile;
81 //! # impl MockFile {
82 //! #     fn create(_s: &str) -> io::Result<Self> { Ok(MockFile) }
83 //! #     fn write_all(&self, _b: &[u8]) -> io::Result<()> { Ok(()) }
84 //! #     fn sync_all(&self) -> io::Result<()> { Ok(()) }
85 //! # }
86 //! # use self::MockFile as File;
87 //!
88 //! fn try_main() -> io::Result<()> {
89 //!     let f = File::create("newfile.txt")?;
90 //!     let mut file = scopeguard::guard(f, |f| {
91 //!         // ensure we flush file at return or panic
92 //!         let _ = f.sync_all();
93 //!     });
94 //!     // Access the file through the scope guard itself
95 //!     file.write_all(b"test me\n").map(|_| ())
96 //! }
97 //!
98 //! fn main() {
99 //!     try_main().unwrap();
100 //! }
101 //!
102 //! ```
103 //!
104 //! ### 2. The guard restores an invariant on scope exit
105 //!
106 //! ```
107 //! extern crate scopeguard;
108 //!
109 //! use std::mem::ManuallyDrop;
110 //! use std::ptr;
111 //!
112 //! // This function, just for this example, takes the first element
113 //! // and inserts it into the assumed sorted tail of the vector.
114 //! //
115 //! // For optimization purposes we temporarily violate an invariant of the
116 //! // Vec, that it owns all of its elements.
117 //! //
118 //! // The safe approach is to use swap, which means two writes to memory,
119 //! // the optimization is to use a “hole” which uses only one write of memory
120 //! // for each position it moves.
121 //! //
122 //! // We *must* use a scope guard to run this code safely. We
123 //! // are running arbitrary user code (comparison operators) that may panic.
124 //! // The scope guard ensures we restore the invariant after successful
125 //! // exit or during unwinding from panic.
126 //! fn insertion_sort_first<T>(v: &mut Vec<T>)
127 //!     where T: PartialOrd
128 //! {
129 //!     struct Hole<'a, T: 'a> {
130 //!         v: &'a mut Vec<T>,
131 //!         index: usize,
132 //!         value: ManuallyDrop<T>,
133 //!     }
134 //!
135 //!     unsafe {
136 //!         // Create a moved-from location in the vector, a “hole”.
137 //!         let value = ptr::read(&v[0]);
138 //!         let mut hole = Hole { v: v, index: 0, value: ManuallyDrop::new(value) };
139 //!
140 //!         // Use a scope guard with a value.
141 //!         // At scope exit, plug the hole so that the vector is fully
142 //!         // initialized again.
143 //!         // The scope guard owns the hole, but we can access it through the guard.
144 //!         let mut hole_guard = scopeguard::guard(hole, |hole| {
145 //!             // plug the hole in the vector with the value that was // taken out
146 //!             let index = hole.index;
147 //!             ptr::copy_nonoverlapping(&*hole.value, &mut hole.v[index], 1);
148 //!         });
149 //!
150 //!         // run algorithm that moves the hole in the vector here
151 //!         // move the hole until it's in a sorted position
152 //!         for i in 1..hole_guard.v.len() {
153 //!             if *hole_guard.value >= hole_guard.v[i] {
154 //!                 // move the element back and the hole forward
155 //!                 let index = hole_guard.index;
156 //!                 ptr::copy_nonoverlapping(&hole_guard.v[index + 1], &mut hole_guard.v[index], 1);
157 //!                 hole_guard.index += 1;
158 //!             } else {
159 //!                 break;
160 //!             }
161 //!         }
162 //!
163 //!         // When the scope exits here, the Vec becomes whole again!
164 //!     }
165 //! }
166 //!
167 //! fn main() {
168 //!     let string = String::from;
169 //!     let mut data = vec![string("c"), string("a"), string("b"), string("d")];
170 //!     insertion_sort_first(&mut data);
171 //!     assert_eq!(data, vec!["a", "b", "c", "d"]);
172 //! }
173 //!
174 //! ```
175 //!
176 //!
177 //! # Crate Features
178 //!
179 //! - `use_std`
180 //!   + Enabled by default. Enables the `OnUnwind` and `OnSuccess` strategies.
181 //!   + Disable to use `no_std`.
182 //!
183 //! # Rust Version
184 //!
185 //! This version of the crate requires Rust 1.20 or later.
186 //!
187 //! The scopeguard 1.x release series will use a carefully considered version
188 //! upgrade policy, where in a later 1.x version, we will raise the minimum
189 //! required Rust version.
190 
191 #[cfg(not(any(test, feature = "use_std")))]
192 extern crate core as std;
193 
194 use std::fmt;
195 use std::marker::PhantomData;
196 use std::mem::{self, ManuallyDrop};
197 use std::ops::{Deref, DerefMut};
198 use std::ptr;
199 
200 /// Controls in which cases the associated code should be run
201 pub trait Strategy {
202     /// Return `true` if the guard’s associated code should run
203     /// (in the context where this method is called).
should_run() -> bool204     fn should_run() -> bool;
205 }
206 
207 /// Always run on scope exit.
208 ///
209 /// “Always” run: on regular exit from a scope or on unwinding from a panic.
210 /// Can not run on abort, process exit, and other catastrophic events where
211 /// destructors don’t run.
212 #[derive(Debug)]
213 pub enum Always {}
214 
215 /// Run on scope exit through unwinding.
216 ///
217 /// Requires crate feature `use_std`.
218 #[cfg(feature = "use_std")]
219 #[derive(Debug)]
220 pub enum OnUnwind {}
221 
222 /// Run on regular scope exit, when not unwinding.
223 ///
224 /// Requires crate feature `use_std`.
225 #[cfg(feature = "use_std")]
226 #[derive(Debug)]
227 pub enum OnSuccess {}
228 
229 impl Strategy for Always {
230     #[inline(always)]
should_run() -> bool231     fn should_run() -> bool { true }
232 }
233 
234 #[cfg(feature = "use_std")]
235 impl Strategy for OnUnwind {
236     #[inline]
should_run() -> bool237     fn should_run() -> bool { std::thread::panicking() }
238 }
239 
240 #[cfg(feature = "use_std")]
241 impl Strategy for OnSuccess {
242     #[inline]
should_run() -> bool243     fn should_run() -> bool { !std::thread::panicking() }
244 }
245 
246 /// Macro to create a `ScopeGuard` (always run).
247 ///
248 /// The macro takes statements, which are the body of a closure
249 /// that will run when the scope is exited.
250 #[macro_export]
251 macro_rules! defer {
252     ($($t:tt)*) => {
253         let _guard = $crate::guard((), |()| { $($t)* });
254     };
255 }
256 
257 /// Macro to create a `ScopeGuard` (run on successful scope exit).
258 ///
259 /// The macro takes statements, which are the body of a closure
260 /// that will run when the scope is exited.
261 ///
262 /// Requires crate feature `use_std`.
263 #[cfg(feature = "use_std")]
264 #[macro_export]
265 macro_rules! defer_on_success {
266     ($($t:tt)*) => {
267         let _guard = $crate::guard_on_success((), |()| { $($t)* });
268     };
269 }
270 
271 /// Macro to create a `ScopeGuard` (run on unwinding from panic).
272 ///
273 /// The macro takes statements, which are the body of a closure
274 /// that will run when the scope is exited.
275 ///
276 /// Requires crate feature `use_std`.
277 #[cfg(feature = "use_std")]
278 #[macro_export]
279 macro_rules! defer_on_unwind {
280     ($($t:tt)*) => {
281         let _guard = $crate::guard_on_unwind((), |()| { $($t)* });
282     };
283 }
284 
285 /// `ScopeGuard` is a scope guard that may own a protected value.
286 ///
287 /// If you place a guard in a local variable, the closure can
288 /// run regardless how you leave the scope — through regular return or panic
289 /// (except if panic or other code aborts; so as long as destructors run).
290 /// It is run only once.
291 ///
292 /// The `S` parameter for [`Strategy`](trait.Strategy.html) determines if
293 /// the closure actually runs.
294 ///
295 /// The guard's closure will be called with the held value in the destructor.
296 ///
297 /// The `ScopeGuard` implements `Deref` so that you can access the inner value.
298 pub struct ScopeGuard<T, F, S = Always>
299     where F: FnOnce(T),
300           S: Strategy,
301 {
302     value: ManuallyDrop<T>,
303     dropfn: ManuallyDrop<F>,
304     // fn(S) -> S is used, so that the S is not taken into account for auto traits.
305     strategy: PhantomData<fn(S) -> S>,
306 }
307 
308 impl<T, F, S> ScopeGuard<T, F, S>
309     where F: FnOnce(T),
310           S: Strategy,
311 {
312     /// Create a `ScopeGuard` that owns `v` (accessible through deref) and calls
313     /// `dropfn` when its destructor runs.
314     ///
315     /// The `Strategy` decides whether the scope guard's closure should run.
316     #[inline]
with_strategy(v: T, dropfn: F) -> ScopeGuard<T, F, S>317     pub fn with_strategy(v: T, dropfn: F) -> ScopeGuard<T, F, S> {
318         ScopeGuard {
319             value: ManuallyDrop::new(v),
320             dropfn: ManuallyDrop::new(dropfn),
321             strategy: PhantomData,
322         }
323     }
324 
325     /// “Defuse” the guard and extract the value without calling the closure.
326     ///
327     /// ```
328     /// extern crate scopeguard;
329     ///
330     /// use scopeguard::{guard, ScopeGuard};
331     ///
332     /// fn conditional() -> bool { true }
333     ///
334     /// fn main() {
335     ///     let mut guard = guard(Vec::new(), |mut v| v.clear());
336     ///     guard.push(1);
337     ///
338     ///     if conditional() {
339     ///         // a condition maybe makes us decide to
340     ///         // “defuse” the guard and get back its inner parts
341     ///         let value = ScopeGuard::into_inner(guard);
342     ///     } else {
343     ///         // guard still exists in this branch
344     ///     }
345     /// }
346     /// ```
347     #[inline]
into_inner(guard: Self) -> T348     pub fn into_inner(guard: Self) -> T {
349         // Cannot move out of Drop-implementing types, so
350         // ptr::read the value and forget the guard.
351         unsafe {
352             let value = ptr::read(&*guard.value);
353             // read the closure so that it is dropped, and assign it to a local
354             // variable to ensure that it is only dropped after the guard has
355             // been forgotten. (In case the Drop impl of the closure, or that
356             // of any consumed captured variable, panics).
357             let _dropfn = ptr::read(&*guard.dropfn);
358             mem::forget(guard);
359             value
360         }
361     }
362 }
363 
364 
365 /// Create a new `ScopeGuard` owning `v` and with deferred closure `dropfn`.
366 #[inline]
guard<T, F>(v: T, dropfn: F) -> ScopeGuard<T, F, Always> where F: FnOnce(T)367 pub fn guard<T, F>(v: T, dropfn: F) -> ScopeGuard<T, F, Always>
368     where F: FnOnce(T)
369 {
370     ScopeGuard::with_strategy(v, dropfn)
371 }
372 
373 /// Create a new `ScopeGuard` owning `v` and with deferred closure `dropfn`.
374 ///
375 /// Requires crate feature `use_std`.
376 #[cfg(feature = "use_std")]
377 #[inline]
guard_on_success<T, F>(v: T, dropfn: F) -> ScopeGuard<T, F, OnSuccess> where F: FnOnce(T)378 pub fn guard_on_success<T, F>(v: T, dropfn: F) -> ScopeGuard<T, F, OnSuccess>
379     where F: FnOnce(T)
380 {
381     ScopeGuard::with_strategy(v, dropfn)
382 }
383 
384 /// Create a new `ScopeGuard` owning `v` and with deferred closure `dropfn`.
385 ///
386 /// Requires crate feature `use_std`.
387 ///
388 /// ## Examples
389 ///
390 /// For performance reasons, or to emulate “only run guard on unwind” in
391 /// no-std environments, we can also use the default guard and simply manually
392 /// defuse it at the end of scope like the following example. (The performance
393 /// reason would be if the [`OnUnwind`]'s call to [std::thread::panicking()] is
394 /// an issue.)
395 ///
396 /// ```
397 /// extern crate scopeguard;
398 ///
399 /// use scopeguard::ScopeGuard;
400 /// # fn main() {
401 /// {
402 ///     let guard = scopeguard::guard((), |_| {});
403 ///
404 ///     // rest of the code here
405 ///
406 ///     // we reached the end of scope without unwinding - defuse it
407 ///     ScopeGuard::into_inner(guard);
408 /// }
409 /// # }
410 /// ```
411 #[cfg(feature = "use_std")]
412 #[inline]
guard_on_unwind<T, F>(v: T, dropfn: F) -> ScopeGuard<T, F, OnUnwind> where F: FnOnce(T)413 pub fn guard_on_unwind<T, F>(v: T, dropfn: F) -> ScopeGuard<T, F, OnUnwind>
414     where F: FnOnce(T)
415 {
416     ScopeGuard::with_strategy(v, dropfn)
417 }
418 
419 // ScopeGuard can be Sync even if F isn't because the closure is
420 // not accessible from references.
421 // The guard does not store any instance of S, so it is also irrelevant.
422 unsafe impl<T, F, S> Sync for ScopeGuard<T, F, S>
423     where T: Sync,
424           F: FnOnce(T),
425           S: Strategy
426 {}
427 
428 impl<T, F, S> Deref for ScopeGuard<T, F, S>
429     where F: FnOnce(T),
430           S: Strategy
431 {
432     type Target = T;
433 
deref(&self) -> &T434     fn deref(&self) -> &T {
435         &*self.value
436     }
437 }
438 
439 impl<T, F, S> DerefMut for ScopeGuard<T, F, S>
440     where F: FnOnce(T),
441           S: Strategy
442 {
deref_mut(&mut self) -> &mut T443     fn deref_mut(&mut self) -> &mut T {
444         &mut *self.value
445     }
446 }
447 
448 impl<T, F, S> Drop for ScopeGuard<T, F, S>
449     where F: FnOnce(T),
450           S: Strategy
451 {
drop(&mut self)452     fn drop(&mut self) {
453         // This is OK because the fields are `ManuallyDrop`s
454         // which will not be dropped by the compiler.
455         let (value, dropfn) = unsafe {
456             (ptr::read(&*self.value), ptr::read(&*self.dropfn))
457         };
458         if S::should_run() {
459             dropfn(value);
460         }
461     }
462 }
463 
464 impl<T, F, S> fmt::Debug for ScopeGuard<T, F, S>
465     where T: fmt::Debug,
466           F: FnOnce(T),
467           S: Strategy
468 {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result469     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
470         f.debug_struct(stringify!(ScopeGuard))
471          .field("value", &*self.value)
472          .finish()
473     }
474 }
475 
476 #[cfg(test)]
477 mod tests {
478     use super::*;
479     use std::cell::Cell;
480     use std::panic::catch_unwind;
481     use std::panic::AssertUnwindSafe;
482 
483     #[test]
test_defer()484     fn test_defer() {
485         let drops = Cell::new(0);
486         defer!(drops.set(1000));
487         assert_eq!(drops.get(), 0);
488     }
489 
490     #[cfg(feature = "use_std")]
491     #[test]
test_defer_success_1()492     fn test_defer_success_1() {
493         let drops = Cell::new(0);
494         {
495             defer_on_success!(drops.set(1));
496             assert_eq!(drops.get(), 0);
497         }
498         assert_eq!(drops.get(), 1);
499     }
500 
501     #[cfg(feature = "use_std")]
502     #[test]
test_defer_success_2()503     fn test_defer_success_2() {
504         let drops = Cell::new(0);
505         let _ = catch_unwind(AssertUnwindSafe(|| {
506             defer_on_success!(drops.set(1));
507             panic!("failure")
508         }));
509         assert_eq!(drops.get(), 0);
510     }
511 
512     #[cfg(feature = "use_std")]
513     #[test]
test_defer_unwind_1()514     fn test_defer_unwind_1() {
515         let drops = Cell::new(0);
516         let _ = catch_unwind(AssertUnwindSafe(|| {
517             defer_on_unwind!(drops.set(1));
518             assert_eq!(drops.get(), 0);
519             panic!("failure")
520         }));
521         assert_eq!(drops.get(), 1);
522     }
523 
524     #[cfg(feature = "use_std")]
525     #[test]
test_defer_unwind_2()526     fn test_defer_unwind_2() {
527         let drops = Cell::new(0);
528         {
529             defer_on_unwind!(drops.set(1));
530         }
531         assert_eq!(drops.get(), 0);
532     }
533 
534     #[test]
test_only_dropped_by_closure_when_run()535     fn test_only_dropped_by_closure_when_run() {
536         let value_drops = Cell::new(0);
537         let value = guard((), |()| value_drops.set(1 + value_drops.get()));
538         let closure_drops = Cell::new(0);
539         let guard = guard(value, |_| closure_drops.set(1 + closure_drops.get()));
540         assert_eq!(value_drops.get(), 0);
541         assert_eq!(closure_drops.get(), 0);
542         drop(guard);
543         assert_eq!(value_drops.get(), 1);
544         assert_eq!(closure_drops.get(), 1);
545     }
546 
547     #[cfg(feature = "use_std")]
548     #[test]
test_dropped_once_when_not_run()549     fn test_dropped_once_when_not_run() {
550         let value_drops = Cell::new(0);
551         let value = guard((), |()| value_drops.set(1 + value_drops.get()));
552         let captured_drops = Cell::new(0);
553         let captured = guard((), |()| captured_drops.set(1 + captured_drops.get()));
554         let closure_drops = Cell::new(0);
555         let guard = guard_on_unwind(value, |value| {
556             drop(value);
557             drop(captured);
558             closure_drops.set(1 + closure_drops.get())
559         });
560         assert_eq!(value_drops.get(), 0);
561         assert_eq!(captured_drops.get(), 0);
562         assert_eq!(closure_drops.get(), 0);
563         drop(guard);
564         assert_eq!(value_drops.get(), 1);
565         assert_eq!(captured_drops.get(), 1);
566         assert_eq!(closure_drops.get(), 0);
567     }
568 
569     #[test]
test_into_inner()570     fn test_into_inner() {
571         let dropped = Cell::new(false);
572         let value = guard(42, |_| dropped.set(true));
573         let guard = guard(value, |_| dropped.set(true));
574         let inner = ScopeGuard::into_inner(guard);
575         assert_eq!(dropped.get(), false);
576         assert_eq!(*inner, 42);
577     }
578 }
579