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