I want to write a program with 2 threads. The first one should update data and the second one should use it. The problem is both of the threads must use the same data. As I understand I can't use mutex in this case. I tried to write a program using static and I did it well. But using static is unsafe, so I decided to found a safe solution.
As I understand in my case it's better to use atomic values. So, I've created an array of atomic values. And the code is not working now, and I can't understand why
use std::{thread, time::{Duration}, sync::{Arc, atomic::{AtomicU16, Ordering}}};
use rdev::{Key, EventType};
fn main() {
let data = Arc::new([0_u16; 6].map(|it| AtomicU16::new(it)));
write(Arc::clone(&data));
listen(data);
}
fn write(data: Arc<[AtomicU16; 6]>) {
thread::spawn(move || {
loop {
let row = data.map(|it| it.load(Ordering::Relaxed).to_string()).join(";");
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// |
// cannot move out of here
// move occurs because value has type `[AtomicU16; 6]`, which does not implement the `Copy` trait
println!("{row}");
thread::sleep(Duration::from_secs(1));
}
});
}
Could you please explain me, how can I map these values?
Do not use map directly, which consumes the array, use an iterator instead (which yields references to the inner values), then map over the iterator:
use std::{
sync::{
atomic::{AtomicU16, Ordering},
Arc,
},
thread,
time::Duration,
};
fn main() {
let data = Arc::new([0_u16; 6].map(|it| AtomicU16::new(it)));
write(Arc::clone(&data));
}
fn write(data: Arc<[AtomicU16; 6]>) {
thread::spawn(move || loop {
let row = data
.iter()
.map(|it| it.load(Ordering::Relaxed).to_string())
.collect::<Vec<String>>()
.join(";");
println!("{row}");
thread::sleep(Duration::from_secs(1));
});
}
Playground
Related
This question already has answers here:
How do I express mutually recursive data structures in safe Rust?
(4 answers)
Closed 1 year ago.
I have two structs that refer to each other. Once initialized, they are never mutated for the rest of the application's lifetime.
It's possible to wrap them in a Mutex or RwLock or something, but it'd be nice not to deal with those throughout the codebase, just to get things initialized.
Here's the example code (does not compile):
use std::sync::Arc;
struct First {
second: Option<Second>,
}
struct Second {
first: Option<Arc<First>>,
}
fn main() {
let first = Arc::new(First { second: None });
let mut second = Second { first: None };
second.first = Some(first.clone());
first.second = Some(second);
}
The problem:
error[E0594]: cannot assign to data in an `Arc`
--> src/main.rs:14:5
|
14 | first.second = Some(second);
| ^^^^^^^^^^^^ cannot assign
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Arc<First>`
It's clear what's happening here; it's not possible to assign to first, because it's inside an Arc, which does not allow interior mutability.
Changing the order of operations doesn't get around the problem.
Using Arc::get_mut() won't work, because the Arc is cloned for storage in second.first.
So, is it possible to create objects with this pattern without needing runtime locking?
You have two options, depending on if you need Sync or not.
With Sync you need some synchronization structure, a RwLock should do:
use std::borrow::BorrowMut;
use std::sync::RwLock;
use std::sync::Arc;
struct First {
second: Option<Second>,
}
struct Second {
first: Option<Arc<RwLock<First>>>,
}
fn main() {
let first = Arc::new(RwLock::new(First { second: None }));
let mut second = Second { first: None };
second.first = Some(first.clone());
let mut inner = first.write().unwrap();
inner.second = Some(second);
}
Playground
If you do not need Sync, use Rc instead of Arc and RefCell:
use std::rc::Rc;
use std::cell::RefCell;
struct First {
second: Option<Second>,
}
struct Second {
first: Option<Rc<RefCell<First>>>,
}
fn main() {
let first = Rc::new(RefCell::new(First { second: None }));
let mut second = Second { first: None };
second.first = Some(first.clone());
first.borrow_mut().second = Some(second);
}
Playground
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
}
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);
}
});
}
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.
Consider the following code example, I have a vector of JoinHandlers in which I need it iterate over to join back to the main thread, however, upon doing so I am getting the error error: cannot move out of borrowed content.
let threads = Arc::new(Mutex::new(Vec::new()));
for _x in 0..100 {
let handle = thread::spawn(move || {
//do some work
}
threads.lock().unwrap().push((handle));
}
for t in threads.lock().unwrap().iter() {
t.join();
}
Unfortunately, you can't do this directly. When Mutex consumes the data structure you fed to it, you can't get it back by value again. You can only get &mut reference to it, which won't allow moving out of it. So even into_iter() won't work - it needs self argument which it can't get from MutexGuard.
There is a workaround, however. You can use Arc<Mutex<Option<Vec<_>>>> instead of Arc<Mutex<Vec<_>>> and then just take() the value out of the mutex:
for t in threads.lock().unwrap().take().unwrap().into_iter() {
}
Then into_iter() will work just fine as the value is moved into the calling thread.
Of course, you will need to construct the vector and push to it appropriately:
let threads = Arc::new(Mutex::new(Some(Vec::new())));
...
threads.lock().unwrap().as_mut().unwrap().push(handle);
However, the best way is to just drop the Arc<Mutex<..>> layer altogether (of course, if this value is not used from other threads).
As referenced in How to take ownership of T from Arc<Mutex<T>>? this is now possible to do without any trickery in Rust using Arc::try_unwrap and Mutex.into_inner()
let threads = Arc::new(Mutex::new(Vec::new()));
for _x in 0..100 {
let handle = thread::spawn(move || {
println!("{}", _x);
});
threads.lock().unwrap().push(handle);
}
let threads_unwrapped: Vec<JoinHandle<_>> = Arc::try_unwrap(threads).unwrap().into_inner().unwrap();
for t in threads_unwrapped.into_iter() {
t.join().unwrap();
}
Play around with it in this playground to verify.
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9d5635e7f778bc744d1fb855b92db178
while the drain is a good solution, you can also do the following thing
// with a copy
let built_words: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![]));
let result: Vec<String> = built_words.lock().unwrap().clone();
// using drain
let mut locked_result = built_words.lock().unwrap();
let mut result: Vec<String> = vec![];
result.extend(locked_result.drain(..));
I would prefer to clone the data to get the original value. Not sure if it has any performance overhead.