pub struct SendRc<T> { /* private fields */ }Expand description
Reference-counting pointer like Rc<T>, but which is Send if T is Send.
When created, a SendRc is pinned to the current thread, and is usable only within
it. Before sending it to a different thread, you must use SendRc::pre_send() to
park all the SendRcs that point to the same value. This will make the values
temporarily inaccessible through SendRcs, but will allow safe transfer. When done
parking, you can obtain a PostSend and send it to the other thread to restore access
to the values there. For example:
// create two SendRcs pointing to a shared value
let mut r1 = SendRc::new(RefCell::new(1));
let mut r2 = SendRc::clone(&r1);
// prepare to send them to a different thread
let pre_send = SendRc::pre_send();
pre_send.park(&mut r1); // r1 and r2 cannot be dereferenced from this point
pre_send.park(&mut r2);
// ready() would panic if there were unparked SendRcs pointing to the value
let post_send = pre_send.ready();
// move everything to a different thread
std::thread::spawn(move || {
// SendRcs are still unusable until unparked
post_send.unpark();
// they're again usable from this point, and only in this thread
*r1.borrow_mut() += 1;
assert_eq!(*r2.borrow(), 2);
})This process may be repeated to send the SendRcs to another thread later.
Compared to Rc, tradeoffs of a SendRc are:
deref(),clone(), anddrop()require a check that the shared value is not parked, and a check that we’re accessing it from the correct thread.- a
SendRctakes up two machine words. - it currently doesn’t support weak pointers.
Implementations§
Source§impl<T> SendRc<T>
impl<T> SendRc<T>
Sourcepub fn new(val: T) -> Self
pub fn new(val: T) -> Self
Constructs a new SendRc<T>.
The SendRc is only usable from the current thread. To send and use it in another
thread, you must call pre_send().
Sourcepub fn pre_send() -> PreSend<T>
pub fn pre_send() -> PreSend<T>
Prepare to send SendRcs to another thread.
To move a SendRc to a different thread, you must call park()
on that pointer, as well as on all other SendRcs pointing to the same value.
let mut r1 = SendRc::new(RefCell::new(1));
let mut r2 = SendRc::clone(&r1);
let pre_send = SendRc::pre_send();
pre_send.park(&mut r1);
pre_send.park(&mut r2);
let post_send = pre_send.ready();
// post_send, r1, and r2 can now be send to a different thread, and re-enabled
// by calling post_send.unpark()Sourcepub fn strong_count(this: &Self) -> usize
pub fn strong_count(this: &Self) -> usize
Returns the number of SendRcs pointing to the value.
Panics when invoked from a different thread than the one the SendRc was created
in or last pinned to.
Sourcepub fn try_unwrap(this: Self) -> Result<T, Self>
pub fn try_unwrap(this: Self) -> Result<T, Self>
Returns the value if the SendRc has exactly one reference.
Panics when invoked from a different thread than the one the SendRc was created
in or last pinned to.