I'm looking for something roughly like this take
, but atomic:
impl<T: Clone> for Arc<T> {
fn take(mut self) -> T {
Arc::make_mut(&mut self);
Arc::try_unwrap(self).unwrap()
}
}
In other words, I want Arc::make_mut
which returns the value itself, rather than a mutable reference.
'Arc' stands for 'Atomically Reference Counted'. The type Arc<T> provides shared ownership of a value of type T , allocated in the heap. Invoking clone on Arc produces a new Arc instance, which points to the same allocation on the heap as the source Arc , while increasing a reference count.
To enable multiple ownership, Rust has a type called Rc<T> . Its name is an abbreviation for reference counting, which keeps track of the number of references to a value to know whether or not a value is still in use.
Returns a copy of the value.
Rc uses non-atomic reference counting. This means that overhead is very low, but an Rc cannot be sent between threads, and consequently Rc does not implement Send . As a result, the Rust compiler will check at compile time that you are not sending Rc s between threads.
We can use the *
deref operator to address the underlying value inside of an Rc
or Arc
, and then call .clone()
to return a new owned clone of that value (assuming it's clonable).
use std::rc::Rc;
fn main() {
let rc = Rc::new("Hello".to_string());
let mut cloned = (*rc).clone();
cloned.truncate(4);
// verify that it's modified
println!("{:?}", cloned); // "Hell"
// verify that the original was not
println!("{:?}", rc); // "Hello"
}
The Rc
/Arc
semantics will prevent any mutable references from being created while your reference exists, so this operation is thread-safe; the data can't be changed while you're cloning it. You also don't need a mutable reference to the original underlying value, because you're not modifying it.
In some cases, Rust lets you omit the *
deref operator: it will implicitly dereference a non-mutable pointer type if you try to call a method that doesn't exist on the pointer, but does exist on the underlying value. However, we need to be explicit in this case because a .clone()
method does already exists on Rc
/Arc
: it's used to create a new reference to the same value. We don't want to call that, so we need to explicitly dereference to access the inner type's .clone()
instead.
We can also tell Rust which .clone()
method we want by explicitly calling it through the appropriate type, and the compiler will implicitly apply as many dereferences as necessary.
use std::rc::Rc;
fn main() {
let rc3 = Rc::new(Rc::new(Rc::new("Hello".to_string())));
let mut cloned = String::clone(&rc3);
cloned.truncate(4);
// verify that it's modified
println!("{:?}", cloned); // "Hell"
// verify that the original was not
println!("{:?}", rc3); // "Hello"
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With