diff --git a/Cargo.lock b/Cargo.lock index 86cd9619..f52e83ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -111,62 +111,6 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" -[[package]] -name = "crossbeam" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" - [[package]] name = "crossterm" version = "0.29.0" @@ -771,7 +715,6 @@ version = "0.50.0" dependencies = [ "arboard", "chrono", - "crossbeam", "crossterm", "fd-lock", "gethostname", diff --git a/Cargo.toml b/Cargo.toml index 1816b420..c939dd02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,6 @@ chrono = { version = "0.4.19", default-features = false, features = [ "clock", "serde", ] } -crossbeam = { version = "0.8.2", optional = true } crossterm = { version = "0.29.0", features = ["serde"] } fd-lock = "4.0.2" itertools = "0.15.0" @@ -45,7 +44,7 @@ tempfile = "3.3.0" [features] default = ["helix"] bashisms = [] -external_printer = ["crossbeam"] +external_printer = [] idle_callback = [] helix = [] sqlite = ["rusqlite/bundled", "serde_json"] diff --git a/examples/external_printer.rs b/examples/external_printer.rs index 9c31e238..001dacc7 100644 --- a/examples/external_printer.rs +++ b/examples/external_printer.rs @@ -12,18 +12,18 @@ use { fn main() { let printer = ExternalPrinter::default(); - // make a clone to use it in a different thread - let p_clone = printer.clone(); - // get the Sender to have full sending control - let p_sender = printer.sender(); + + // grab a sender per producer thread; only the engine holds the receiving end + let p_sender_slow = printer.sender(); + let p_sender_fast = printer.sender(); // external printer that prints a message every second thread::spawn(move || { let mut i = 1; loop { sleep(Duration::from_secs(1)); - assert!(p_clone - .print(format!("Message {i} delivered.\nWith two lines!")) + assert!(p_sender_slow + .send(format!("Message {i} delivered.\nWith two lines!")) .is_ok()); i += 1; } @@ -34,7 +34,7 @@ fn main() { sleep(Duration::from_secs(3)); for _ in 0..10 { sleep(Duration::from_millis(1)); - assert!(p_sender.send("Fast Hello !".to_string()).is_ok()); + assert!(p_sender_fast.send("Fast Hello !".to_string()).is_ok()); } }); diff --git a/src/engine.rs b/src/engine.rs index f66b69bf..840462b3 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -12,8 +12,8 @@ use crate::{ #[cfg(feature = "external_printer")] use { crate::external_printer::ExternalPrinter, - crossbeam::channel::TryRecvError, std::io::{Error, ErrorKind}, + std::sync::mpsc::TryRecvError, }; use { crate::{ diff --git a/src/external_printer.rs b/src/external_printer.rs index 1b6c5d2e..8c93de92 100644 --- a/src/external_printer.rs +++ b/src/external_printer.rs @@ -6,9 +6,9 @@ //! cargo run --example external_printer --features=external_printer //! ``` #[cfg(feature = "external_printer")] -use { - crossbeam::channel::{bounded, Receiver, SendError, Sender}, - std::fmt::Display, +use std::{ + fmt::Display, + sync::mpsc::{sync_channel, Receiver, SendError, SyncSender}, }; #[cfg(feature = "external_printer")] @@ -21,12 +21,12 @@ pub const EXTERNAL_PRINTER_DEFAULT_CAPACITY: usize = 20; /// ## Required feature: /// `external_printer` #[cfg(feature = "external_printer")] -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct ExternalPrinter where T: Display, { - sender: Sender, + sender: SyncSender, receiver: Receiver, } @@ -37,11 +37,11 @@ where { /// Creates an ExternalPrinter to store lines with a max_cap pub fn new(max_cap: usize) -> Self { - let (sender, receiver) = bounded::(max_cap); + let (sender, receiver) = sync_channel::(max_cap); Self { sender, receiver } } - /// Gets a Sender to use the printer externally by sending lines to it - pub fn sender(&self) -> Sender { + /// Gets a `SyncSender` to use the printer externally by sending lines to it + pub fn sender(&self) -> SyncSender { self.sender.clone() } /// Receiver to get messages if any @@ -49,8 +49,7 @@ where &self.receiver } - /// Convenience method if the whole Printer is cloned, blocks if max_cap is reached. - /// + /// Send a line through the printer's own sender; blocks if `max_cap` is reached. pub fn print(&self, line: T) -> Result<(), SendError> { self.sender.send(line) } @@ -70,3 +69,26 @@ where Self::new(EXTERNAL_PRINTER_DEFAULT_CAPACITY) } } + +#[cfg(all(test, feature = "external_printer"))] +mod tests { + use super::*; + + #[test] + fn line_sent_from_another_thread_is_received() { + let printer = ExternalPrinter::::new(2); + let sender = printer.sender(); + std::thread::spawn(move || sender.send("hello".to_string()).unwrap()) + .join() + .unwrap(); + assert_eq!(printer.get_line().as_deref(), Some("hello")); + assert_eq!(printer.get_line(), None); + } + + #[test] + fn print_goes_through_the_same_channel() { + let printer = ExternalPrinter::::new(1); + printer.print("via print".to_string()).unwrap(); + assert_eq!(printer.get_line().as_deref(), Some("via print")); + } +}