I think this is something like a pattern:
I have an helper thread that I want to control from the main program.
So I made a struct for setting something before the thread start.
When it starts it takes ownership of the struct and I would like to return an object containing an Arc of an internal struct that holds some Condvar
s, AtomicBool
s and the JoinHandle
of the thread. The problem is I can't insert the JoinHandle inside the same Arc because I need the Arc inside the same thread.
So I should use two Arc or return a couple with the Arc and the JoinHandle and give the JoinHandle to the Stop function. Every of these solutions I found not much elegant and ergonomic.
Is there a better solution I didn't see?
Let's bring some context:
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;
fn main() {
struct SharedData {
time_to_exit: AtomicBool,
}
let shared_data = Arc::new(SharedData {
time_to_exit: AtomicBool::new(false)
});
let shared_data2 = shared_data.clone();
let join_handle = thread::spawn(move || {
while !shared_data.time_to_exit.load(Ordering::SeqCst) {
thread::sleep(Duration::from_millis(100));
}
println!("thread - done");
});
shared_data2.time_to_exit.store(true, Ordering::SeqCst);
join_handle.join().unwrap();
println!("main - done");
}
SharedData
is shared data, join_handle
is join handle, join handle
belong only to the thread that start another thread, it not belong another thread,
so what sense to hold it inside SharedData
? put it near SharedData
,
if you use this patter a lot, create someting:
struct ThreadInfo {
shared_data: Arc<SharedInfo>,
join_handle: JoinHandle<()>,
}
The problem is that if I have to share the control of the thread with another thread I can't clone the JoinHandle. So I can't clone the ThreadInfo struct...
On the other hand if I return the couple (SharedData, JoinHandle) I can't simply call a stop function on one struct, but I have to pass in also the JoinHandle.
Ok, I think I found a nice solution:
I make a struct like your ThreadInfo and I impl a get_arc method that returns a clone of the internal arc, so I can call the methods of the internal SharedInfo.
In the end I have something like this:
[code]pub struct UpThread{
join_handle: JoinHandle<()>,
arc: Arc
}
pub struct UpThreadInternals {
stop: AtomicBool,
lock: Mutex,
cvar: Condvar
}
impl UpThread{
pub fn update(&self){
self.arc.update();
}
pub fn get_arc(&self) -> Arc{
self.arc.clone()
}
pub fn stop(self){
if let Ok(ut) = Arc::try_unwrap(self.arc){
ut.stop();
self.join_handle.join();
} else {
//log
}
}
}
impl UpThreadInternals{
pub fn update(&self){
let mut to_update = self.lock.lock().unwrap();
*to_update = true;
self.cvar.notify_one();
}
fn stop(self) {
self.stop.store(true, Ordering::Relaxed);
}
}
[/code]