threads3 solution

This commit is contained in:
mo8it 2024-07-01 11:23:40 +02:00
parent dfa2b44f71
commit a13e3cd07f
3 changed files with 80 additions and 15 deletions

View file

@ -1,7 +1,4 @@
use std::sync::mpsc; use std::{sync::mpsc, thread, time::Duration};
use std::sync::Arc;
use std::thread;
use std::time::Duration;
struct Queue { struct Queue {
length: u32, length: u32,
@ -11,7 +8,7 @@ struct Queue {
impl Queue { impl Queue {
fn new() -> Self { fn new() -> Self {
Queue { Self {
length: 10, length: 10,
first_half: vec![1, 2, 3, 4, 5], first_half: vec![1, 2, 3, 4, 5],
second_half: vec![6, 7, 8, 9, 10], second_half: vec![6, 7, 8, 9, 10],
@ -19,20 +16,22 @@ impl Queue {
} }
} }
fn send_tx(q: Queue, tx: mpsc::Sender<u32>) -> () { fn send_tx(q: Queue, tx: mpsc::Sender<u32>) {
// TODO: We want to send `tx` to both threads. But currently, it is moved
// into the frist thread. How could you solve this problem?
thread::spawn(move || { thread::spawn(move || {
for val in q.first_half { for val in q.first_half {
println!("sending {:?}", val); println!("Sending {val:?}");
tx.send(val).unwrap(); tx.send(val).unwrap();
thread::sleep(Duration::from_secs(1)); thread::sleep(Duration::from_millis(250));
} }
}); });
thread::spawn(move || { thread::spawn(move || {
for val in q.second_half { for val in q.second_half {
println!("sending {:?}", val); println!("Sending {val:?}");
tx.send(val).unwrap(); tx.send(val).unwrap();
thread::sleep(Duration::from_secs(1)); thread::sleep(Duration::from_millis(250));
} }
}); });
} }
@ -55,11 +54,11 @@ mod tests {
let mut total_received: u32 = 0; let mut total_received: u32 = 0;
for received in rx { for received in rx {
println!("Got: {}", received); println!("Got: {received}");
total_received += 1; total_received += 1;
} }
println!("total numbers received: {}", total_received); println!("Number of received values: {total_received}");
assert_eq!(total_received, queue_length); assert_eq!(total_received, queue_length);
} }
} }

View file

@ -1076,10 +1076,11 @@ An alternate way to handle concurrency between threads is to use an `mpsc`
With both a sending end and a receiving end, it's possible to send values in With both a sending end and a receiving end, it's possible to send values in
one thread and receive them in another. one thread and receive them in another.
Multiple producers are possible by using clone() to create a duplicate of the Multiple producers are possible by using `clone()` to create a duplicate of the
original sending end. original sending end.
See https://doc.rust-lang.org/book/ch16-02-message-passing.html for more info.""" Related section in The Book:
https://doc.rust-lang.org/book/ch16-02-message-passing.html"""
# MACROS # MACROS

View file

@ -1 +1,66 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 use std::{sync::mpsc, thread, time::Duration};
struct Queue {
length: u32,
first_half: Vec<u32>,
second_half: Vec<u32>,
}
impl Queue {
fn new() -> Self {
Self {
length: 10,
first_half: vec![1, 2, 3, 4, 5],
second_half: vec![6, 7, 8, 9, 10],
}
}
}
fn send_tx(q: Queue, tx: mpsc::Sender<u32>) {
// Clone the sender `tx` first.
let tx_clone = tx.clone();
thread::spawn(move || {
for val in q.first_half {
println!("Sending {val:?}");
// Then use the clone in the first thread. This means that
// `tx_clone` is moved to the first thread and `tx` to the second.
tx_clone.send(val).unwrap();
thread::sleep(Duration::from_millis(250));
}
});
thread::spawn(move || {
for val in q.second_half {
println!("Sending {val:?}");
tx.send(val).unwrap();
thread::sleep(Duration::from_millis(250));
}
});
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn threads3() {
let (tx, rx) = mpsc::channel();
let queue = Queue::new();
let queue_length = queue.length;
send_tx(queue, tx);
let mut total_received: u32 = 0;
for received in rx {
println!("Got: {received}");
total_received += 1;
}
println!("Number of received values: {total_received}");
assert_eq!(total_received, queue_length);
}
}