In Brief
Given a trait Trait and a T: Trait, any &'a T can be split into a Lich<dyn Trait + 'static> and a Soul<'a> pair such that the dyn Trait can cross 'static boundaries while tracking the lifetime 'a.
The general usage pattern of this library is:
- Choose a
Lich/Soulvariant for your use-case (see below for the tradeoffs). - Implement
Shroudfor the trait for which you want to extend the lifetime (e.g.#[shroud] trait Traitwillimpl<T: Trait> Shroud<T> for dyn Traitautomatically). - Use the corresponding
ritual::<T: Trait, dyn Trait>(value: &'a T)to produce aLich<dyn Trait + 'static>bound to aSoul<'a>. - Use the
Lich<dyn Trait>as a'staticreference to your otherwise non-'static&'a T. - Use the corresponding
redeem(Lich<T>, Soul<'a>)to guarantee that all references to&'a Tare dropped before the end of lifetime'a.
When Soul<'a> is dropped or when calling Soul::sever, it is guaranteed that the captured reference is also dropped, thus inaccessible from a remaining Lich.
Different variants exist with different tradeoffs:
phylactery::raw:- Zero-cost (wraps a pointer in a new-type).
- Does not allocate heap memory.
- Does require the
Lichto beredeemed with itsSoul(otherwise,LichandSoulwill panic on drop). - Does require some
unsafecalls (e.g.Lich::borrow). Lichcan not be cloned.- Can be sent to other threads.
- Can be used with
#[no_std].
phylactery::atomic:- Adds minimal overhead with an
AtomicU32reference counter. - Does not allocate heap memory.
- Does require an additional memory location (an
&mut u32) to create theLich/Soulpair. - If a
Lichstill exists when theSoulis dropped, the thread will block until theLichis dropped (which can lead to deadlocks). - Does not require
unsafecalls. Lichcan be cloned.- Can be sent to other threads.
- Can be used with
#[no_std].
- Adds minimal overhead with an
phylactery::cell:- Adds an indirection and minimal overhead using
Rc<RefCell>. - Does allocate heap memory.
- Allows for the use of the
Lich::severandSoul::severmethods. - If a borrow still exists when the
Soulis dropped, the thread will panic. - Does not require the
Liches to beredeemed (although it is considered good practice to do so). - Does not require
unsafecalls. Lichcan be cloned.- Can not be sent to other threads.
- Adds an indirection and minimal overhead using
phylactery::lock:- Adds an indirection and some overhead using
Arc<RwLock>. - Does allocate heap memory.
- Allows for the use of the
Lich::severandSoul::severmethods. - If a borrow still exists when the
Soulis dropped, the thread will block until the borrow expires (which can lead to deadlocks). - Does not require the
Lichto beredeemed (although it is considered good practice to do so). - Does not require
unsafecalls. Lichcan be cloned.- Can be sent to other threads.
- Adds an indirection and some overhead using
Since this library makes use of some unsafe code, all tests are run with miri to try to catch any unsoundness.
Examples
/// Trivially reimplement [`thread::scope`] in a more powerful way.
///
/// Contrary to other `scope` solutions, here, the captured reference can be
/// returned (as a [`Soul<'a>`]) while the threads continue to execute.
/// Implements a thread local scoped logger available from anywhere that can
/// borrow values that live on the stack.
See the examples and tests folder for more detailed examples.
Contribute
- If you find a bug or have a feature request, please open an issues.
phylacteryis actively maintained and pull requests are welcome.- If
phylacterywas useful to you, please consider leaving a star!