3 unstable releases
0.2.0 | Feb 9, 2020 |
---|---|
0.1.1 | Dec 25, 2019 |
0.1.0 | Dec 25, 2019 |
#2979 in Rust patterns
21KB
328 lines
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.
License: Apache-2.0
Dependencies
~170KB