Rust: Using Mutex and Arc to mutate - multithreading

I am trying to allow multiple threads to mutate the same variable using Arc and a Mutex lock, but it seems as though I am unable to get ownership of the variable, even after cloning it?
// modifed example from https://doc.rust-lang.org/beta/rust-by-example/std/arc.html
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
fn main() {
// This variable declaration is where its value is specified.
let test = Arc::new(Mutex::new(TestStruct{
counter: 0,
}));
println!("Initial Counter Value: 0");
for _ in 0..10 {
// Here there is no value specification as it is a pointer to a
// reference in the memory heap.
let test = Arc::clone(&test);
thread::spawn(move || {
// As Arc was used, threads can be spawned using the value allocated
// in the Arc variable pointer's location.
test.lock().unwrap().increment();
});
}
// Make sure all Arc instances are printed from spawned threads.
thread::sleep(Duration::from_secs(1));
println!("Final Counter Value: {:?}", test.lock().unwrap().counter);
}
#[derive(Debug)]
struct TestStruct {
// counter
counter: i32,
}
impl TestStruct {
// increment counter
fn increment(mut self) {
self.counter +=1;
}
}
I keep getting errors that say error[E0507]: cannot move out of dereference of "MutexGuard<"_, TestStruct> anywhere that I try to access the variable with test.lock().unwrap()
All I am trying to do in this example is increment a counter from multiple threads, and then check the value of this counter afterwards.
I've gotten it to work by placing the value inside of an option: Arc::new(Mutex::new(Some(TestStruct{..}))) and then taking the value from that option: test.lock().unwrap().take(), but taking the value out of the Option then replaces it with None, so it only works once.
Does anyone know what I am doing wrong / how I might be able to get this to work?
Here is a link to a playground with the code.

Since you take mut self as opposed to &mut self in increment you need to exclusively own the variable to use it.
But you can only take references to objects in Arc<Mutex<…>>.
You probably want to take self by mutable reference in increment instead:
impl TestStruct {
// increment counter
fn increment(&mut self) {
self.counter +=1;
}
}

Related

How to set the value of a struct inside a GTK event in rust?

How to set the value of a struct inside a GTK event in rust?
I'm gettting an error when trying to modify the s struct instance below.
use gtk::prelude::*;
use gio::prelude::*;
use gtk::{Application, ApplicationWindow, Button};
struct SomeStruct {
val: bool,
}
fn main() {
let mut s = SomeStruct {
val: false,
};
application.connect_activate(|app| {
let window = ApplicationWindow::new(app);
window.set_title("test");
window.set_default_size(350,70);
let button = Button::with_label("Test");
button.connect_clicked(|_|{
s.val = true; // error here
});
window.add(&button);
window.show_all();
});
application.run(&[]);
}
Error messages:
error[E0597]: `s` does not live long enough
error[E0596]: cannot borrow `s` as mutable, as it is a captured variable in a `Fn` closure
Your code has two issues:
Although s outlives the GTK application, Rust doesn't know that, whis is why it complains of s not living long enough.
ButtonExt::connect_clicked() accepts a Fn, so it's not allowed to mutate data without extra precautions.
The first issue can be fixed by allocating s on the heap and accessing it through a reference-counted pointer, which ensures that the object lives at least as long as the closure that refers to it.
The second issue is easiest to resolve through interior mutability, by wrapping SomeStruct into a RefCell. RefCell holds a value and allows the holder to mutate it through a shared reference to the RefCell. When requesting a mut reference to the inner value, RefCell will check at run-time that no other reference to the value is still live. (This could happen if your closure were to get access to the value and then, while holding the value, called another closure that does the same.)
Those two combined would lead to code like this (untested):
use std::rc::Rc;
use std::cell::RefCell;
fn main() {
let s = Rc::new(RefCell::new(SomeStruct { val: false }));
application.connect_activate(|app| {
let window = ApplicationWindow::new(app);
window.set_title("test");
window.set_default_size(350, 70);
let button = Button::with_label("Test");
// clone the handle to s and move it into the closure
let s2 = Rc::clone(&s);
button.connect_clicked(move |_| {
s2.borrow_mut().val = true;
});
window.add(&button);
window.show_all();
});
application.run(&[]);
}

What happens to the ownership of a value returned but not assigned by the calling function?

Consider the following Rust code, slightly modified from examples in The Book.
I'm trying to understand what happens to the value in the second running of function dangle() in the main() function (see comment). I would imagine that because the value isn't assigned to any owner, it gets deallocated, but I've so far failed to find information to confirm that. Otherwise, I would think that calling dangle() repeatedly would constantly allocate more memory without deallocating it. Which is it?
fn main() {
// Ownership of dangle()'s return value is passed to the variable `thingamabob`.
let thingamabob = dangle();
// No ownership specified. Is the return value deallocated here?
dangle();
println!("Ref: {}", thingamabob);
}
fn dangle() -> String {
// Ownership specified.
let s = String::from("hello");
// Ownership is passed to calling function.
s
}
When a value has no owner (is not bound to a variable) it goes out of scope. Values that go out of scope are dropped. Dropping a value frees the resources associated with that value.
Anything less would lead to memory leaks, which would be a poor idea in a programming language.
See also:
Is it possible in Rust to delete an object before the end of scope?
How does Rust know whether to run the destructor during stack unwind?
Does Rust free up the memory of overwritten variables?
In your example, the second call creates an unnamed temporary value whose lifetime ends immediately after that one line of code, so it goes out of scope (and any resources are reclaimed) immediately.
If you bind the value to a name using let, then its lifetime extends until the end of the current lexical scope (closing curly brace).
You can explore some of this yourself by implementing the Drop trait on a simple type to see when its lifetime ends. Here's a small program I made to play with this (playground):
#[derive(Debug)]
struct Thing {
val: i32,
}
impl Thing {
fn new(val: i32) -> Self {
println!("Creating Thing #{}", val);
Thing { val }
}
fn foo(self, val: i32) -> Self {
Thing::new(val)
}
}
impl Drop for Thing {
fn drop(&mut self) {
println!("Dropping {:?}", self);
}
}
pub fn main() {
let _t1 = Thing::new(1);
Thing::new(2); // dropped immediately
{
let t3 = Thing::new(3);
Thing::new(4).foo(5).foo(6); // all are dropped, in order, as the next one is created
println!("Doing something with t3: {:?}", t3);
} // t3 is dropped here
} // _t1 is dropped last

Explain the behavior of *Rc::make_mut and why it differs compared to Mutex

I needed to pass a resource between several functions which use a closure as an argument. And within these the data was handled, but it looked for that the changes that were realized to a variable will be reflected in the rest.
The first thing I thought was to use Rc. I had previously used Arc to handle the data between different threads, but since these functions aren't running in different threads I chose Rc instead.
The most simplified code that I have, to show my doubts:
The use of RefCell was because maybe I had to see that this syntax will not work as I expected:
*Rc::make_mut(&mut rc_pref_temp)...
use std::sync::Arc;
use std::rc::Rc;
use std::sync::Mutex;
use std::cell::RefCell;
use std::cell::Cell;
fn main() {
test2();
println!("---");
test();
}
#[derive(Debug, Clone)]
struct Prefe {
name_test: RefCell<u64>,
}
impl Prefe {
fn new() -> Prefe {
Prefe {
name_test: RefCell::new(3 as u64),
}
}
}
fn test2(){
let mut prefe: Prefe = Prefe::new();
let mut rc_pref = Rc::new(Mutex::new(prefe));
println!("rc_pref Mutex: {:?}", rc_pref.lock().unwrap().name_test);
let mut rc_pref_temp = rc_pref.clone();
*rc_pref_temp.lock().unwrap().name_test.get_mut() += 1;
println!("rc_pref_clone Mutex: {:?}", rc_pref_temp.lock().unwrap().name_test);
*rc_pref_temp.lock().unwrap().name_test.get_mut() += 1;
println!("rc_pref_clone Mutex: {:?}", rc_pref_temp.lock().unwrap().name_test);
println!("rc_pref Mutex: {:?}", rc_pref.lock().unwrap().name_test);
}
fn test(){
let mut prefe: Prefe = Prefe::new();
let mut rc_pref = Rc::new(prefe);
println!("rc_pref: {:?}", rc_pref.name_test);
let mut rc_pref_temp = rc_pref.clone();
*((*Rc::make_mut(&mut rc_pref_temp)).name_test).get_mut() += 1;
println!("rc_pref_clone: {:?}", rc_pref_temp.name_test);
*((*Rc::make_mut(&mut rc_pref_temp)).name_test).get_mut() += 1;
println!("rc_pref_clone: {:?}", rc_pref_temp.name_test);
println!("rc_pref: {:?}", rc_pref.name_test);
}
The code is simplified, the scenario where it is used is totally different. I note this to avoid comments like "you can lend a value to the function", because what interests me is to know why the cases exposed work in this way.
stdout:
rc_pref Mutex : RefCell { value: 3 }
rc_pref_clone Mutex : RefCell { value: 4 }
rc_pref_clone Mutex : RefCell { value: 5 }
rc_pref Mutex : RefCell { value: 5 }
---
rc_pref : RefCell { value: 3 }
rc_pref_clone : RefCell { value: 4 }
rc_pref_clone : RefCell { value: 5 }
rc_pref : RefCell { value: 3 }
About test()
I'm new to Rust so I don't know if this crazy syntax is the right way.
*((*Rc::make_mut(&mut rc_pref_temp)).name_test).get_mut() += 1;
When running test() you can see that the previous syntax works, because it increases the value, but this increase does not affect the clones. I expected that with the use of *Rc::make_mut(& mut rc_pref_temp)... that the clones of a shared reference would reflect the same values.
If Rc has references to the same object, why do the changes to an object not apply to the rest of the clones? Why does this work this way? Am I doing something wrong?
Note: I use RefCell because in some tests I thought that maybe I had something to do.
About test2()
I've got it working as expected using Mutex with Rc, but I do not know if this is the correct way. I have some ideas of how Mutex and Arc works, but after using this syntax:
*Rc::make_mut(&mut rc_pref_temp)...
With the use of Mutex in test2(), I wonder if Mutex is not only responsible for changing the data in but also the one in charge of reflecting the changes in all the cloned references.
Do the shared references actually point to the same object? I want to think they do, but with the above code where the changes are not reflected without the use of Mutex, I have some doubts.
You need to read and understand the documentation for functions you use before you use them. Rc::make_mut says, emphasis mine:
Makes a mutable reference into the given Rc.
If there are other Rc or Weak pointers to the same value, then
make_mut will invoke clone on the inner value to ensure unique
ownership. This is also referred to as clone-on-write.
See also get_mut, which will fail rather than cloning.
You have multiple Rc pointers because you called rc_pref.clone(). Thus, when you call make_mut, the inner value will be cloned and the Rc pointers will now be disassociated from each other:
use std::rc::Rc;
fn main() {
let counter = Rc::new(100);
let mut counter_clone = counter.clone();
println!("{}", Rc::strong_count(&counter)); // 2
println!("{}", Rc::strong_count(&counter_clone)); // 2
*Rc::make_mut(&mut counter_clone) += 50;
println!("{}", Rc::strong_count(&counter)); // 1
println!("{}", Rc::strong_count(&counter_clone)); // 1
println!("{}", counter); // 100
println!("{}", counter_clone); // 150
}
The version with the Mutex works because it's completely different. You aren't calling a function which clones the inner value anymore. Of course, it doesn't make sense to use a Mutex when you don't have threads. The single-threaded equivalent of a Mutex is... RefCell!
I honestly don't know how you found Rc::make_mut; I've never even heard of it before. The module documentation for cell doesn't mention it, nor does the module documentation for rc.
I'd highly encourage you to take a step back and re-read through the documentation. The second edition of The Rust Programming Language has a chapter on smart pointers, including Rc and RefCell. Read the module-level documentation for rc and cell as well.
Here's what your code should look like. Note the usage of borrow_mut.
fn main() {
let prefe = Rc::new(Prefe::new());
println!("prefe: {:?}", prefe.name_test); // 3
let prefe_clone = prefe.clone();
*prefe_clone.name_test.borrow_mut() += 1;
println!("prefe_clone: {:?}", prefe_clone.name_test); // 4
*prefe_clone.name_test.borrow_mut() += 1;
println!("prefe_clone: {:?}", prefe_clone.name_test); // 5
println!("prefe: {:?}", prefe.name_test); // 5
}

How do I emulate a timer inside an object that will periodically mutate the object?

In my project I need to do something like:
use std::thread;
use std::time::Duration;
struct A {
pub ints: Vec<u8>,
}
impl A {
fn new() -> A {
let mut a = A {
ints: vec![1, 5, 6, 2, 3, 4],
};
a.timer();
a
}
fn timer(&mut self) {
thread::spawn(move || {
loop {
thread::sleep(Duration::from_millis(1));
self.ints.remove(0);
}
});
}
}
fn main() {
let a = A::new();
loop {
println!("Remaining elements: {:?}", a.ints);
}
}
The idea is that some struct contains a vector of elements. These elements should be removed from the vector after some period of time. Think of it as a periodic timer that checks something and performs an action on mutable object (removes an element). This thread also needs to be dropped if the object on which it is working on is deleted. So I guess it should be a member of a struct of which it is manipulating.
The problem with the code above is that it has a lot of borrow errors and I don't understand how to do that.
I have seen few questions like this but each of them was about manipulating scalar in a thread. The reason why I can't apply it here is because the thread should be something that is inside A struct and it should call remove on a vector that is a member of that struct.
I guess I should use Arc or something like that but don't really understand how to use it here.
I guess I should use Arc or something like that but don't really understand how to use it here.
Indeed that is the simplest solution:
You can wrap the ints field in an Arc, but then you wouldn't be able to modify the Vec, so you also wrap it in a Mutex:
struct A {
pub ints: Arc<Mutex<Vec<u8>>>,
}
Then you can clone the Arc to receive a second handle to the same memory.
fn timer(&mut self) {
let ints = self.ints.clone();
thread::spawn(move || {
loop {
thread::sleep(Duration::from_millis(1));
Instead of directly accessing the Vec, you then need to lock the Mutex, which can fail if another thread panicked while accessing the Mutex.
ints.lock().unwrap().remove(0);
}
});
}

How do I share a mutable object between threads using Arc?

I'm trying to share a mutable object between threads in Rust using Arc, but I get this error:
error[E0596]: cannot borrow data in a `&` reference as mutable
--> src/main.rs:11:13
|
11 | shared_stats_clone.add_stats();
| ^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
This is the sample code:
use std::{sync::Arc, thread};
fn main() {
let total_stats = Stats::new();
let shared_stats = Arc::new(total_stats);
let threads = 5;
for _ in 0..threads {
let mut shared_stats_clone = shared_stats.clone();
thread::spawn(move || {
shared_stats_clone.add_stats();
});
}
}
struct Stats {
hello: u32,
}
impl Stats {
pub fn new() -> Stats {
Stats { hello: 0 }
}
pub fn add_stats(&mut self) {
self.hello += 1;
}
}
What can I do?
Arc's documentation says:
Shared references in Rust disallow mutation by default, and Arc is no exception: you cannot generally obtain a mutable reference to something inside an Arc. If you need to mutate through an Arc, use Mutex, RwLock, or one of the Atomic types.
You will likely want a Mutex combined with an Arc:
use std::{
sync::{Arc, Mutex},
thread,
};
struct Stats;
impl Stats {
fn add_stats(&mut self, _other: &Stats) {}
}
fn main() {
let shared_stats = Arc::new(Mutex::new(Stats));
let threads = 5;
for _ in 0..threads {
let my_stats = shared_stats.clone();
thread::spawn(move || {
let mut shared = my_stats.lock().unwrap();
shared.add_stats(&Stats);
});
// Note: Immediately joining, no multithreading happening!
// THIS WAS A LIE, see below
}
}
This is largely cribbed from the Mutex documentation.
How can I use shared_stats after the for? (I'm talking about the Stats object). It seems that the shared_stats cannot be easily converted to Stats.
As of Rust 1.15, it's possible to get the value back. See my additional answer for another solution as well.
[A comment in the example] says that there is no multithreading. Why?
Because I got confused! :-)
In the example code, the result of thread::spawn (a JoinHandle) is immediately dropped because it's not stored anywhere. When the handle is dropped, the thread is detached and may or may not ever finish. I was confusing it with JoinGuard, a old, removed API that joined when it is dropped. Sorry for the confusion!
For a bit of editorial, I suggest avoiding mutability completely:
use std::{ops::Add, thread};
#[derive(Debug)]
struct Stats(u64);
// Implement addition on our type
impl Add for Stats {
type Output = Stats;
fn add(self, other: Stats) -> Stats {
Stats(self.0 + other.0)
}
}
fn main() {
let threads = 5;
// Start threads to do computation
let threads: Vec<_> = (0..threads).map(|_| thread::spawn(|| Stats(4))).collect();
// Join all the threads, fail if any of them failed
let result: Result<Vec<_>, _> = threads.into_iter().map(|t| t.join()).collect();
let result = result.unwrap();
// Add up all the results
let sum = result.into_iter().fold(Stats(0), |i, sum| sum + i);
println!("{:?}", sum);
}
Here, we keep a reference to the JoinHandle and then wait for all the threads to finish. We then collect the results and add them all up. This is the common map-reduce pattern. Note that no thread needs any mutability, it all happens in the master thread.

Resources