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.
In Brief
The general usage pattern of this library is:
- Choose a
Lich<T>/Soul<'a>variant for your use-case (see below for the tradeoffs). - Implement
Shroudfor the trait for which you want to extend the lifetime (a simple call toshroud!(Trait)is often all it takes). - 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<T>.
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
Lich<T>to beredeemed with itsSoul<'a>(otherwise,Lich<T>andSoul<'a>will panic on drop). - Does require some
unsafecalls (Lich<T>::borrow). Lich<T>can 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<T>/Soul<'a>pair. - If a
Lich<T>still exists when theSoul<'a>is dropped, the thread will block until theLich<T>is dropped (which can lead to dead locks). - Does not require
unsafecalls. Lich<T>can 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<T>/Soul<'a>::severmethods. - If a borrow still exists when the
Soul<'a>is dropped, the thread will panic. - Does not require the
Lich<T>es to beredeemed (although it is considered good practice to do so). - Does not require
unsafecalls. Lich<T>can 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<T>/Soul<'a>::severmethods. - If a borrow still exists when the
Soul<'a>is dropped, the thread will block until the borrow expires (which can lead to dead locks). - Does not require the
Lich<T>to beredeemed (although it is considered good practice to do so). - Does not require
unsafecalls. Lich<T>can 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.
///
/// Contrarily 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!