4 stable releases
1.2.1 | Mar 27, 2024 |
---|---|
1.2.0 | Feb 18, 2023 |
1.1.0 | Jan 31, 2023 |
1.0.0 | Jan 28, 2023 |
#805 in Rust patterns
157 downloads per month
Used in handoff
26KB
264 lines
twinsies
Twinsies is a special shared pointer, similar to an Arc
, where two specific
objects (called Joint
) share joint ownership of the underlying object. The
key difference compared to an Arc
is that the underlying object is dropped
when either of the Joint
objects go out of scope.
Because a single Joint
cannot, by itself, keep the shared object alive, it
cannot be dereferenced directly like an Arc
. Instead, it must be locked
with .lock()
. While locked, the object is guaranteed to stay alive as long
as the JointLock
is alive. If the a Joint
is dropped while its partner
is locked, the object stays alive, but it dropped immediately as soon as the
other Joint
is no longer locked.
Twinsies is intended to be used for things like unbuffered channels, join
handles, and async Waker
- cases where some piece of shared state should only
be preserved as long as both halves are still interested in it.
Example
use twinsies::Joint;
use std::cell::Cell;
let (first, second) = Joint::new(Cell::new(0));
assert_eq!(first.lock().unwrap().get(), 0);
first.lock().unwrap().set(10);
assert_eq!(second.lock().unwrap().get(), 10);
drop(second);
// Once `second` is dropped, the shared value is gone
assert!(first.lock().is_none())
Locks preserve liveness
use twinsies::Joint;
use std::cell::Cell;
let (first, second) = Joint::new(Cell::new(0));
let lock = first.lock().unwrap();
lock.set(10);
assert_eq!(second.lock().unwrap().get(), 10);
second.lock().unwrap().set(20);
assert_eq!(lock.get(), 20);
drop(second);
assert_eq!(lock.get(), 20);
lock.set(30);
assert_eq!(lock.get(), 30);
// As soon as the lock is dropped, the shared value is gone, since `second`
// was dropped earlier
drop(lock);
assert!(first.lock().is_none());