Requires Rust 1.34.0 or later.
This crate provides a cell-like type Cryo
that is similar to RefCell
except that it constrains the lifetime of its borrowed value
through a runtime check mechanism, erasing the compile-time lifetime
information. The lock guard CryoRef
created from Cryo
is
'static
and therefore can be used in various situations that require
'static
types, including:
CryoRef
temporarily in a std::any::Any
-compatible container.This works by, when a Cryo
is dropped, not letting the current thread's
execution move forward (at least¹) until all references to the expiring
Cryo
are dropped so that none of them can outlive the Cryo
.
This is implemented by [readers-writer locks] under the hood.
¹ SyncLock
blocks the current thread's execution on lock failure.
LocalLock
, on the other hand, panics because it's designed for
single-thread use cases and would deadlock otherwise.
with_cryo
, Cryo
, and LocalLock
(single-thread lock
implementation, used by default):
```rust use std::{thread::spawn, pin::Pin};
let cell: usize = 42;
// with_cryo
uses LocalLock
by default
withcryo(&cell, |cryo: Pin<&Cryo<', usize, >>| {
// Borrow cryo
and move it into a 'static
closure.
let borrow: CryoRef
// Compile-time lifetime works as well.
assert_eq!(*cryo.get(), 42);
// When `cryo` is dropped, it will block until there are no other
// references to `cryo`. In this case, the program will leave
// this block immediately because `CryoRef` has already been dropped.
}); ```
with_cryo
, Cryo
, and SyncLock
(thread-safe lock implementation):
```rust use std::{thread::spawn, pin::Pin};
let cell: usize = 42;
// This time we are specifying the lock implementation
withcryo((&cell, lockty::cryo
and move it into a 'static
closure.
// CryoRef
can be sent to another thread because
// SyncLock
is thread-safe.
let borrow: CryoRef
// Compile-time lifetime works as well.
assert_eq!(*cryo.get(), 42);
// When `cryo` is dropped, it will block until there are no other
// references to `cryo`. In this case, the program will not leave
// this block until the thread we just spawned completes execution.
}); ```
with_cryo
, CryoMut
, and SyncLock
:
``rust
with_cryo((&mut cell, lock_ty::<SyncLock>()), |cryo_mut| {
// Borrow
cryomutand move it into a
'static` closure.
let mut borrow: CryoMutWriteGuard
// When `cryo_mut` is dropped, it will block until there are no other
// references to `cryo_mut`. In this case, the program will not leave
// this block until the thread we just spawned completes execution
}); assert_eq!(cell, 1); ```
Don't do these:
rust
// The following statement will DEADLOCK because it attempts to drop
// `Cryo` while a `CryoRef` is still referencing it, and `Cryo`'s
// destructor will wait for the `CryoRef` to be dropped first (which
// will never happen)
let borrow = with_cryo((&cell, lock_ty::<SyncLock>()), |cryo| cryo.borrow());
rust
// The following statement will ABORT because it attempts to drop
// `Cryo` while a `CryoRef` is still referencing it, and `Cryo`'s
// destructor will panic, knowing no amount of waiting would cause
// the `CryoRef` to be dropped
let borrow = with_cryo(&cell, |cryo| cryo.borrow());
&'a NonStaticType<'b>
is supplied to Cryo
's constructor, the
borrowed type is CryoRef<NonStaticType<'b>>
, which is still partially
bound to the original lifetime.std
(enabled by default) enables SyncLock
.
lock_api
enables the blanket implementation of Lock
on
all types implementing lock_api::RawRwLock
, such as
spin::RawRwLock
and parking_lot::RawRwLock
.
atomic
(enabled by default) enables features that require full atomics,
which is not supported by some targets (detecting such targets is still
unstable ([#32976])). This feature will be deprecated after the
stabilization of #32976.
spin::RawRwLock
: https://docs.rs/spin/0.9.0/spin/type.RwLock.html
parking_lot::RawRwLock
: https://docs.rs/parkinglot/0.11.1/parkinglot/struct.RawRwLock.html
Cryo<T, SyncLock>
's creation, destruction, borrowing, and unborrowing
each take one or two atomic operations in the best cases.
Neither of SyncLock
and LocalLock
require dynamic memory allocation.
From cryopreservation.
License: MIT/Apache-2.0