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")))]
192extern crate core as std;
193
194use std::fmt;
195use std::marker::PhantomData;
196use std::mem::ManuallyDrop;
197use std::ops::{Deref, DerefMut};
198use std::ptr;
199
200/// Controls in which cases the associated code should be run
201pub trait Strategy {
202 /// Return `true` if the guard’s associated code should run
203 /// (in the context where this method is called).
204 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)]
213pub 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)]
220pub 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)]
227pub enum OnSuccess {}
228
229impl Strategy for Always {
230 #[inline(always)]
231 fn should_run() -> bool {
232 true
233 }
234}
235
236#[cfg(feature = "use_std")]
237impl Strategy for OnUnwind {
238 #[inline]
239 fn should_run() -> bool {
240 std::thread::panicking()
241 }
242}
243
244#[cfg(feature = "use_std")]
245impl Strategy for OnSuccess {
246 #[inline]
247 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]
257macro_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]
271macro_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]
285macro_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.
304pub struct ScopeGuard<T, F, S = Always>
305where
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
315impl<T, F, S> ScopeGuard<T, F, S>
316where
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]
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]
357 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]
375pub fn guard<T, F>(v: T, dropfn: F) -> ScopeGuard<T, F, Always>
376where
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]
388pub fn guard_on_success<T, F>(v: T, dropfn: F) -> ScopeGuard<T, F, OnSuccess>
389where
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]
425pub fn guard_on_unwind<T, F>(v: T, dropfn: F) -> ScopeGuard<T, F, OnUnwind>
426where
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.
435unsafe impl<T, F, S> Sync for ScopeGuard<T, F, S>
436where
437 T: Sync,
438 F: FnOnce(T),
439 S: Strategy,
440{
441}
442
443impl<T, F, S> Deref for ScopeGuard<T, F, S>
444where
445 F: FnOnce(T),
446 S: Strategy,
447{
448 type Target = T;
449
450 fn deref(&self) -> &T {
451 &*self.value
452 }
453}
454
455impl<T, F, S> DerefMut for ScopeGuard<T, F, S>
456where
457 F: FnOnce(T),
458 S: Strategy,
459{
460 fn deref_mut(&mut self) -> &mut T {
461 &mut *self.value
462 }
463}
464
465impl<T, F, S> Drop for ScopeGuard<T, F, S>
466where
467 F: FnOnce(T),
468 S: Strategy,
469{
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
480impl<T, F, S> fmt::Debug for ScopeGuard<T, F, S>
481where
482 T: fmt::Debug,
483 F: FnOnce(T),
484 S: Strategy,
485{
486 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)]
494mod tests {
495 use super::*;
496 use std::cell::Cell;
497 use std::panic::catch_unwind;
498 use std::panic::AssertUnwindSafe;
499
500 #[test]
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]
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 fn test_defer_success_2() {
521 let drops = Cell::new(0);
522 let _ = catch_unwind(AssertUnwindSafe(|| {
523 defer_on_success!(drops.set(1));
524 panic!("failure")
525 }));
526 assert_eq!(drops.get(), 0);
527 }
528
529 #[cfg(feature = "use_std")]
530 #[test]
531 fn test_defer_unwind_1() {
532 let drops = Cell::new(0);
533 let _ = catch_unwind(AssertUnwindSafe(|| {
534 defer_on_unwind!(drops.set(1));
535 assert_eq!(drops.get(), 0);
536 panic!("failure")
537 }));
538 assert_eq!(drops.get(), 1);
539 }
540
541 #[cfg(feature = "use_std")]
542 #[test]
543 fn test_defer_unwind_2() {
544 let drops = Cell::new(0);
545 {
546 defer_on_unwind!(drops.set(1));
547 }
548 assert_eq!(drops.get(), 0);
549 }
550
551 #[test]
552 fn test_only_dropped_by_closure_when_run() {
553 let value_drops = Cell::new(0);
554 let value = guard((), |()| value_drops.set(1 + value_drops.get()));
555 let closure_drops = Cell::new(0);
556 let guard = guard(value, |_| closure_drops.set(1 + closure_drops.get()));
557 assert_eq!(value_drops.get(), 0);
558 assert_eq!(closure_drops.get(), 0);
559 drop(guard);
560 assert_eq!(value_drops.get(), 1);
561 assert_eq!(closure_drops.get(), 1);
562 }
563
564 #[cfg(feature = "use_std")]
565 #[test]
566 fn test_dropped_once_when_not_run() {
567 let value_drops = Cell::new(0);
568 let value = guard((), |()| value_drops.set(1 + value_drops.get()));
569 let captured_drops = Cell::new(0);
570 let captured = guard((), |()| captured_drops.set(1 + captured_drops.get()));
571 let closure_drops = Cell::new(0);
572 let guard = guard_on_unwind(value, |value| {
573 drop(value);
574 drop(captured);
575 closure_drops.set(1 + closure_drops.get())
576 });
577 assert_eq!(value_drops.get(), 0);
578 assert_eq!(captured_drops.get(), 0);
579 assert_eq!(closure_drops.get(), 0);
580 drop(guard);
581 assert_eq!(value_drops.get(), 1);
582 assert_eq!(captured_drops.get(), 1);
583 assert_eq!(closure_drops.get(), 0);
584 }
585
586 #[test]
587 fn test_into_inner() {
588 let dropped = Cell::new(false);
589 let value = guard(42, |_| dropped.set(true));
590 let guard = guard(value, |_| dropped.set(true));
591 let inner = ScopeGuard::into_inner(guard);
592 assert_eq!(dropped.get(), false);
593 assert_eq!(*inner, 42);
594 }
595}
596