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 SendRc
s that point to the same value. This will make the values
temporarily inaccessible through SendRc
s, 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 SendRc
s 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
SendRc
takes 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 SendRc
s to another thread.
To move a SendRc
to a different thread, you must call park()
on that pointer, as well as on all other SendRc
s 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 SendRc
s 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.