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 //!                 hole_guard.v.swap(index, 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::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 {
232         true
233     }
234 }
235 
236 #[cfg(feature = "use_std")]
237 impl Strategy for OnUnwind {
238     #[inline]
should_run() -> bool239     fn should_run() -> bool {
240         std::thread::panicking()
241     }
242 }
243 
244 #[cfg(feature = "use_std")]
245 impl Strategy for OnSuccess {
246     #[inline]
should_run() -> bool247     fn should_run() -> bool {
248         !std::thread::panicking()
249     }
250 }
251 
252 /// Macro to create a `ScopeGuard` (always run).
253 ///
254 /// The macro takes statements, which are the body of a closure
255 /// that will run when the scope is exited.
256 #[macro_export]
257 macro_rules! defer {
258     ($($t:tt)*) => {
259         let _guard = $crate::guard((), |()| { $($t)* });
260     };
261 }
262 
263 /// Macro to create a `ScopeGuard` (run on successful scope exit).
264 ///
265 /// The macro takes statements, which are the body of a closure
266 /// that will run when the scope is exited.
267 ///
268 /// Requires crate feature `use_std`.
269 #[cfg(feature = "use_std")]
270 #[macro_export]
271 macro_rules! defer_on_success {
272     ($($t:tt)*) => {
273         let _guard = $crate::guard_on_success((), |()| { $($t)* });
274     };
275 }
276 
277 /// Macro to create a `ScopeGuard` (run on unwinding from panic).
278 ///
279 /// The macro takes statements, which are the body of a closure
280 /// that will run when the scope is exited.
281 ///
282 /// Requires crate feature `use_std`.
283 #[cfg(feature = "use_std")]
284 #[macro_export]
285 macro_rules! defer_on_unwind {
286     ($($t:tt)*) => {
287         let _guard = $crate::guard_on_unwind((), |()| { $($t)* });
288     };
289 }
290 
291 /// `ScopeGuard` is a scope guard that may own a protected value.
292 ///
293 /// If you place a guard in a local variable, the closure can
294 /// run regardless how you leave the scope — through regular return or panic
295 /// (except if panic or other code aborts; so as long as destructors run).
296 /// It is run only once.
297 ///
298 /// The `S` parameter for [`Strategy`](trait.Strategy.html) determines if
299 /// the closure actually runs.
300 ///
301 /// The guard's closure will be called with the held value in the destructor.
302 ///
303 /// The `ScopeGuard` implements `Deref` so that you can access the inner value.
304 pub struct ScopeGuard<T, F, S = Always>
305 where
306     F: FnOnce(T),
307     S: Strategy,
308 {
309     value: ManuallyDrop<T>,
310     dropfn: ManuallyDrop<F>,
311     // fn(S) -> S is used, so that the S is not taken into account for auto traits.
312     strategy: PhantomData<fn(S) -> S>,
313 }
314 
315 impl<T, F, S> ScopeGuard<T, F, S>
316 where
317     F: FnOnce(T),
318     S: Strategy,
319 {
320     /// Create a `ScopeGuard` that owns `v` (accessible through deref) and calls
321     /// `dropfn` when its destructor runs.
322     ///
323     /// The `Strategy` decides whether the scope guard's closure should run.
324     #[inline]
325     #[must_use]
with_strategy(v: T, dropfn: F) -> ScopeGuard<T, F, S>326     pub fn with_strategy(v: T, dropfn: F) -> ScopeGuard<T, F, S> {
327         ScopeGuard {
328             value: ManuallyDrop::new(v),
329             dropfn: ManuallyDrop::new(dropfn),
330             strategy: PhantomData,
331         }
332     }
333 
334     /// “Defuse” the guard and extract the value without calling the closure.
335     ///
336     /// ```
337     /// extern crate scopeguard;
338     ///
339     /// use scopeguard::{guard, ScopeGuard};
340     ///
341     /// fn conditional() -> bool { true }
342     ///
343     /// fn main() {
344     ///     let mut guard = guard(Vec::new(), |mut v| v.clear());
345     ///     guard.push(1);
346     ///
347     ///     if conditional() {
348     ///         // a condition maybe makes us decide to
349     ///         // “defuse” the guard and get back its inner parts
350     ///         let value = ScopeGuard::into_inner(guard);
351     ///     } else {
352     ///         // guard still exists in this branch
353     ///     }
354     /// }
355     /// ```
356     #[inline]
into_inner(guard: Self) -> T357     pub fn into_inner(guard: Self) -> T {
358         // Cannot move out of `Drop`-implementing types,
359         // so `ptr::read` the value and forget the guard.
360         let mut guard = ManuallyDrop::new(guard);
361         unsafe {
362             let value = ptr::read(&*guard.value);
363             // Drop the closure after `value` has been read, so that if the
364             // closure's `drop` function panics, unwinding still tries to drop
365             // `value`.
366             ManuallyDrop::drop(&mut guard.dropfn);
367             value
368         }
369     }
370 }
371 
372 /// Create a new `ScopeGuard` owning `v` and with deferred closure `dropfn`.
373 #[inline]
374 #[must_use]
guard<T, F>(v: T, dropfn: F) -> ScopeGuard<T, F, Always> where F: FnOnce(T),375 pub fn guard<T, F>(v: T, dropfn: F) -> ScopeGuard<T, F, Always>
376 where
377     F: FnOnce(T),
378 {
379     ScopeGuard::with_strategy(v, dropfn)
380 }
381 
382 /// Create a new `ScopeGuard` owning `v` and with deferred closure `dropfn`.
383 ///
384 /// Requires crate feature `use_std`.
385 #[cfg(feature = "use_std")]
386 #[inline]
387 #[must_use]
guard_on_success<T, F>(v: T, dropfn: F) -> ScopeGuard<T, F, OnSuccess> where F: FnOnce(T),388 pub fn guard_on_success<T, F>(v: T, dropfn: F) -> ScopeGuard<T, F, OnSuccess>
389 where
390     F: FnOnce(T),
391 {
392     ScopeGuard::with_strategy(v, dropfn)
393 }
394 
395 /// Create a new `ScopeGuard` owning `v` and with deferred closure `dropfn`.
396 ///
397 /// Requires crate feature `use_std`.
398 ///
399 /// ## Examples
400 ///
401 /// For performance reasons, or to emulate “only run guard on unwind” in
402 /// no-std environments, we can also use the default guard and simply manually
403 /// defuse it at the end of scope like the following example. (The performance
404 /// reason would be if the [`OnUnwind`]'s call to [std::thread::panicking()] is
405 /// an issue.)
406 ///
407 /// ```
408 /// extern crate scopeguard;
409 ///
410 /// use scopeguard::ScopeGuard;
411 /// # fn main() {
412 /// {
413 ///     let guard = scopeguard::guard((), |_| {});
414 ///
415 ///     // rest of the code here
416 ///
417 ///     // we reached the end of scope without unwinding - defuse it
418 ///     ScopeGuard::into_inner(guard);
419 /// }
420 /// # }
421 /// ```
422 #[cfg(feature = "use_std")]
423 #[inline]
424 #[must_use]
guard_on_unwind<T, F>(v: T, dropfn: F) -> ScopeGuard<T, F, OnUnwind> where F: FnOnce(T),425 pub fn guard_on_unwind<T, F>(v: T, dropfn: F) -> ScopeGuard<T, F, OnUnwind>
426 where
427     F: FnOnce(T),
428 {
429     ScopeGuard::with_strategy(v, dropfn)
430 }
431 
432 // ScopeGuard can be Sync even if F isn't because the closure is
433 // not accessible from references.
434 // The guard does not store any instance of S, so it is also irrelevant.
435 unsafe impl<T, F, S> Sync for ScopeGuard<T, F, S>
436 where
437     T: Sync,
438     F: FnOnce(T),
439     S: Strategy,
440 {
441 }
442 
443 impl<T, F, S> Deref for ScopeGuard<T, F, S>
444 where
445     F: FnOnce(T),
446     S: Strategy,
447 {
448     type Target = T;
449 
deref(&self) -> &T450     fn deref(&self) -> &T {
451         &*self.value
452     }
453 }
454 
455 impl<T, F, S> DerefMut for ScopeGuard<T, F, S>
456 where
457     F: FnOnce(T),
458     S: Strategy,
459 {
deref_mut(&mut self) -> &mut T460     fn deref_mut(&mut self) -> &mut T {
461         &mut *self.value
462     }
463 }
464 
465 impl<T, F, S> Drop for ScopeGuard<T, F, S>
466 where
467     F: FnOnce(T),
468     S: Strategy,
469 {
drop(&mut self)470     fn drop(&mut self) {
471         // This is OK because the fields are `ManuallyDrop`s
472         // which will not be dropped by the compiler.
473         let (value, dropfn) = unsafe { (ptr::read(&*self.value), ptr::read(&*self.dropfn)) };
474         if S::should_run() {
475             dropfn(value);
476         }
477     }
478 }
479 
480 impl<T, F, S> fmt::Debug for ScopeGuard<T, F, S>
481 where
482     T: fmt::Debug,
483     F: FnOnce(T),
484     S: Strategy,
485 {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result486     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
487         f.debug_struct(stringify!(ScopeGuard))
488             .field("value", &*self.value)
489             .finish()
490     }
491 }
492 
493 #[cfg(test)]
494 mod tests {
495     use super::*;
496     use std::cell::Cell;
497     use std::panic::catch_unwind;
498     use std::panic::AssertUnwindSafe;
499 
500     #[test]
test_defer()501     fn test_defer() {
502         let drops = Cell::new(0);
503         defer!(drops.set(1000));
504         assert_eq!(drops.get(), 0);
505     }
506 
507     #[cfg(feature = "use_std")]
508     #[test]
test_defer_success_1()509     fn test_defer_success_1() {
510         let drops = Cell::new(0);
511         {
512             defer_on_success!(drops.set(1));
513             assert_eq!(drops.get(), 0);
514         }
515         assert_eq!(drops.get(), 1);
516     }
517 
518     #[cfg(feature = "use_std")]
519     #[test]
520     #[ignore = "Android uses panic_abort"]
test_defer_success_2()521     fn test_defer_success_2() {
522         let drops = Cell::new(0);
523         let _ = catch_unwind(AssertUnwindSafe(|| {
524             defer_on_success!(drops.set(1));
525             panic!("failure")
526         }));
527         assert_eq!(drops.get(), 0);
528     }
529 
530     #[cfg(feature = "use_std")]
531     #[test]
532     #[ignore = "Android uses panic_abort"]
test_defer_unwind_1()533     fn test_defer_unwind_1() {
534         let drops = Cell::new(0);
535         let _ = catch_unwind(AssertUnwindSafe(|| {
536             defer_on_unwind!(drops.set(1));
537             assert_eq!(drops.get(), 0);
538             panic!("failure")
539         }));
540         assert_eq!(drops.get(), 1);
541     }
542 
543     #[cfg(feature = "use_std")]
544     #[test]
test_defer_unwind_2()545     fn test_defer_unwind_2() {
546         let drops = Cell::new(0);
547         {
548             defer_on_unwind!(drops.set(1));
549         }
550         assert_eq!(drops.get(), 0);
551     }
552 
553     #[test]
test_only_dropped_by_closure_when_run()554     fn test_only_dropped_by_closure_when_run() {
555         let value_drops = Cell::new(0);
556         let value = guard((), |()| value_drops.set(1 + value_drops.get()));
557         let closure_drops = Cell::new(0);
558         let guard = guard(value, |_| closure_drops.set(1 + closure_drops.get()));
559         assert_eq!(value_drops.get(), 0);
560         assert_eq!(closure_drops.get(), 0);
561         drop(guard);
562         assert_eq!(value_drops.get(), 1);
563         assert_eq!(closure_drops.get(), 1);
564     }
565 
566     #[cfg(feature = "use_std")]
567     #[test]
test_dropped_once_when_not_run()568     fn test_dropped_once_when_not_run() {
569         let value_drops = Cell::new(0);
570         let value = guard((), |()| value_drops.set(1 + value_drops.get()));
571         let captured_drops = Cell::new(0);
572         let captured = guard((), |()| captured_drops.set(1 + captured_drops.get()));
573         let closure_drops = Cell::new(0);
574         let guard = guard_on_unwind(value, |value| {
575             drop(value);
576             drop(captured);
577             closure_drops.set(1 + closure_drops.get())
578         });
579         assert_eq!(value_drops.get(), 0);
580         assert_eq!(captured_drops.get(), 0);
581         assert_eq!(closure_drops.get(), 0);
582         drop(guard);
583         assert_eq!(value_drops.get(), 1);
584         assert_eq!(captured_drops.get(), 1);
585         assert_eq!(closure_drops.get(), 0);
586     }
587 
588     #[test]
test_into_inner()589     fn test_into_inner() {
590         let dropped = Cell::new(false);
591         let value = guard(42, |_| dropped.set(true));
592         let guard = guard(value, |_| dropped.set(true));
593         let inner = ScopeGuard::into_inner(guard);
594         assert_eq!(dropped.get(), false);
595         assert_eq!(*inner, 42);
596     }
597 }
598