Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 0 additions & 57 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"]
Expand Down
14 changes: 7 additions & 7 deletions examples/external_printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> 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;
}
Expand All @@ -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());
}
});

Expand Down
2 changes: 1 addition & 1 deletion src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down
42 changes: 32 additions & 10 deletions src/external_printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand All @@ -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<T>
where
T: Display,
{
sender: Sender<T>,
sender: SyncSender<T>,
receiver: Receiver<T>,
}

Expand All @@ -37,20 +37,19 @@ where
{
/// Creates an ExternalPrinter to store lines with a max_cap
pub fn new(max_cap: usize) -> Self {
let (sender, receiver) = bounded::<T>(max_cap);
let (sender, receiver) = sync_channel::<T>(max_cap);
Self { sender, receiver }
}
/// Gets a Sender to use the printer externally by sending lines to it
pub fn sender(&self) -> Sender<T> {
/// Gets a `SyncSender` to use the printer externally by sending lines to it
pub fn sender(&self) -> SyncSender<T> {
self.sender.clone()
}
/// Receiver to get messages if any
pub fn receiver(&self) -> &Receiver<T> {
&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<T>> {
self.sender.send(line)
}
Expand All @@ -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::<String>::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::<String>::new(1);
printer.print("via print".to_string()).unwrap();
assert_eq!(printer.get_line().as_deref(), Some("via print"));
}
}
Loading