Hello, I'm new to Rust and I'm facing some problem with a little code I'm writing.
Currently I'm doing a "WorkersHandler" which creates a channel and spawns multiple threads that writes into that channel.
This is an overview of my code (not all included to make for a more compact post)
main.rs
let mut hash_handler = authorization::HashWorkersHandler::new(1);
hash_handler.join();
authorization.rs
use std::sync::mpsc::{SyncSender, Receiver, sync_channel};
pub struct HashWorker {
id: i32,
tx_channel: SyncSender<String>,
running: Arc<AtomicBool>,
}
pub struct HashWorkersHandler {
running: Arc<AtomicBool>,
handlers: Vec<JoinHandle<()>>,
workers: Vec<HashWorker>,
tx_channel: SyncSender<String>,
}
impl HashWorkersHandler {
pub fn new(workers_n: i32) -> HashWorkersHandler {
let mut workers_handlers = vec![];
let mut workers = vec![];
let running = Arc::new( AtomicBool::new(true));
let (sync_tx, sync_rx) = sync_channel(BUFFER_SIZE);
for i in 0..workers_n {
let tx_clone = sync_tx.clone();
let running_clone = running.clone();
let mut worker = HashWorker::new(i+1, tx_clone, running_clone);
let handler = worker.run();
workers.push(worker);
workers_handlers.push(handler);
}
let ret = HashWorkersHandler {
running: running,
handlers: workers_handlers,
workers: workers,
tx_channel: sync_tx,
}
}
pub fn join(self) {
for h in self.handlers.into_iter() {
h.join().expect("Error");
}
}
}
impl HashWorker {
pub fn new(id: i32, tx_channel: SyncSender<String>, running: Arc<AtomicBool>) -> HashWorker {
HashWorker {
id: id,
tx_channel: tx_channel,
running: running,
}
}
pub fn run(self: &Self) -> JoinHandle<()> {
let id = self.id;
let running = self.running.clone();
let tx_channel = self.tx_channel.clone();
spawn( move || {
while running.load( Ordering::Relaxed ) {
//let uuid = Uuid::new_v4().to_hyphenated();
let uuid = "hello";
let hash = sha256::digest(uuid);
println!("HashWorker {} generated hash {}", id, hash);
match tx_channel.send(hash) {
Ok(msg) => println!("Hashworker {} message sent", id),
Err(x) => println!("This error occurred {}",x),
}
sleep(Duration::from_secs(1));
}
println!("HashWorker {} finished", id);
})
}
}
Each of the HashWorker
threads pushes a message every X ammount of time. Each of these workers contain a copy of the SyncSender.
The issue I'm facing is the workers are unable to send messages because it claims the channels are closed.
I'm guessing how I'm storing the sync_tx
in the struct isn't keeping it alive, hence being dropped and the channel closed.
If instead of doing this I create the channel in the main and pass it to the constructor, it works.
My questions are:
- Why is the sender being dropped?
- Is there anyway of achieving what I'm intended?
Thanks in advance to any replieas and excuse me if there's any Rust jargon I'm missing