[−][src]Crate scoped_callback
Allows registering scoped functions with local borrows with code that expect
functions taking 'static
lifetimes.
Motivating example:
/// Function for registering a callback with a `'static` lifetime. fn register(callback: Box<dyn FnMut(i32)>) -> Box<dyn FnMut(i32)> { callback } /// Function for de-registering the handle returned by `register`, /// in this case the callback itself. fn deregister(_callback: Box<dyn FnMut(i32)>) {} /// Variable that can be borrowed from inside the callback closure let a = 42; /// After returning from the closure, `scope` guarantees that any callbacks /// that have not yet been de-registered are de-registered. scope(|scope| { /// Register the given closure, which can borrow from the stack outside `scope` /// using the `register` and `deregister` functions declared above. /// The returned handle will cause a de-register when dropped. let _registered = scope.register( |_| { let b = a * a; println!("{}", b); }, register, deregister, ); });
See scope_async and scope_async_local
as well for versions that work with async
scopes.
How is this safe?
There are three important concepts in this implementation:
- register returns a Registered instance, which when Drop-ed causes the callback to be de-registered using the provided function.
- In case the Registered instance is not
Drop-ed, for example by calling
std::mem::forget
(which is notunsafe
!) the de-registering using the provided function will instead happen after leaving the closure passed to scope. - In case the given de-register function doesn't actually de-register the callback,
and for some reason the callback given to the register
function is called after the closure passed to scope, the call will cause a
panic!
.
no_std
This crate supports no_std
by disabling its std
feature.
Structs
Registered | A handle returned by Scope::register. When this handle is dropped, the callback is de-registered. |
Scope | A |
Functions
scope | Call |
scope_async | Same as scope but also allow |
scope_async_local | Same as scope_async but here |