A versatile and easy to use defer statement for Rust. Similar to Go's or Zig's defer. Loosely based on and inspired by: https://github.com/rodrigocfd/defer-lite This crate is compatible uses `no_std`. The default features use `alloc`. To disable alloc set default-features to false in cargo.toml. This crates provides 6 macros for different use cases of deferment: 1. `defer!` simple deferment. Will execute when current scope ends. - If this is all you need then use the `defer-lite` crate! 2. `defer_move!` same as `defer!` but moves local variables into the closure. 3. `defer_guard!` Returns a guard that causes execution when its scope ends. - Execution can be canceled or preempted. 4. `defer_move_guard!` Same as `defer_guard!` but moves local variables into the closure. 5. `defer_arc!` Returns a reference counted guard than can be shared with other threads. - Execution can be canceled or preempted. - Closure must be `Send` - Target must support Arc & AtomicBool. - Target must support alloc - can be disabled with `default-features=false` in Cargo.toml 6. `defer_move_arc!` Same as `defer_arc!` but moves local variables into the closure. - All used local variables must be `Send`. # Usage Add the dependency in your `Cargo.toml`: ```toml [dependencies] defer-heavy = "0.1.0" ``` ## Examples ### Simple Defer If this is all you need use the `defer-lite` crate instead! ```rust use defer_heavy::defer; fn main() { defer! { println!("Second"); } println!("First"); } ``` ### Canceled Defer ```rust use defer_heavy::defer_guard; fn main() { let defer1 = defer_guard! { unreachable!("Wont be executed"); }; let defer2 = defer_guard! { println!("Second"); }; let defer3 = defer_guard! { println!("Fourth"); }; println!("First"); defer2.destroy(); //Same as drop(defer2); println!("Third"); defer1.cancel(); } ``` ### Reference Counted Defer ```rust use std::thread; use std::time::Duration; use defer_heavy::defer_move_arc; pub fn main() { let deferred = defer_arc! { println!("Executed in {:?}", thread::current().id());}; println!("Main thread {:?}", thread::current().id()); { let deferred = deferred.clone(); thread::spawn(move ||{ println!("Spawned thread {:?}", thread::current().id()); let _deferred = deferred.own(); thread::sleep(Duration::from_millis(2000)); //SIMULATE work }); } thread::sleep(Duration::from_millis(2000)); //SIMULATE WORK } ``` Prints: ```text Main thread Thread(1) Spawned thread Thread(2) "Executed in Thread(1)" or "Executed in Thread(2)" ``` # Order of execution Rust guarantees that the order in which the closures are dropped (and therefore executed) are in reverse order of creation. This means the last `defer!` in the scope executes first.