Crate scoped_callback

Source
Expand description

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 not unsafe!) 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 Scope is used to register callbacks. See Scope::register.

Functions§

scope
Call scope to receive a Scope instance that can be used to register functions. See Scope::register.
scope_async
Same as scope but also allow async borrows.
scope_async_local
Same as scope_async but here f returns a LocalBoxFuture instead.