diff --git a/Cargo.lock b/Cargo.lock index 2caa857..e569c6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -890,6 +890,13 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mpsc" +version = "0.1.0" +dependencies = [ + "anyhow", +] + [[package]] name = "nom" version = "7.1.3" diff --git a/Cargo.toml b/Cargo.toml index 061bb8e..52c1ace 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,10 +14,12 @@ members = [ "members/tokio-send-sync", "members/matchmatchmatch", "members/future_stream", + "members/mpsc", ] default-members = [ ".", "members/revsqrt", + "members/mpsc", "members/criterion-demo", "members/shortc", "members/pest-demo", diff --git a/members/mpsc/Cargo.toml b/members/mpsc/Cargo.toml new file mode 100644 index 0000000..62e2f7b --- /dev/null +++ b/members/mpsc/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "mpsc" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow.workspace = true diff --git a/members/mpsc/src/main.rs b/members/mpsc/src/main.rs new file mode 100644 index 0000000..58ff9a6 --- /dev/null +++ b/members/mpsc/src/main.rs @@ -0,0 +1,60 @@ +use anyhow::Result; +use std::io::Write; +use std::str::FromStr; +use std::sync::{Arc, Barrier}; +use std::{sync::mpsc, thread}; + +#[derive(Clone, Debug)] +struct Message { + payload: String, +} + +impl std::fmt::Display for Message { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Message {{{}}}", self.payload) + } +} + +impl std::str::FromStr for Message { + type Err = std::convert::Infallible; + fn from_str(s: &str) -> std::prelude::v1::Result { + Ok(Self { + payload: s.to_string(), + }) + } +} + +fn printer(receiver: mpsc::Receiver, barrier: Arc) -> Result<()> { + let mut stdout = std::io::stdout(); + loop { + let msg = receiver.recv()?; + println!("{msg}"); + stdout.flush()?; + barrier.wait(); // wait until the main thread wants us to print + } +} + +fn main() -> Result<()> { + let (sender, receiver) = mpsc::channel(); + let barrier = Arc::new(Barrier::new(2)); + let barrier_printer = barrier.clone(); + thread::spawn(|| printer(receiver, barrier_printer).expect("printer error")); + let mut msg; + let mut buf = String::new(); + let stdin = std::io::stdin(); + let mut stdout = std::io::stdout(); + loop { + buf.clear(); + print!("> "); + stdout.flush()?; + let _ = stdin.read_line(&mut buf)?; + buf = buf.replace('\n', ""); + if buf.is_empty() { + continue; + } + msg = Message::from_str(&buf).unwrap(); + sender.send(msg)?; + barrier.wait(); // wait until the printer is done printing the message, so we dont mix + // stdout prints (we use print instead of println) + } +}