diff --git a/src/lib.rs b/src/lib.rs index e69de29..2cc6c9c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -0,0 +1,6 @@ +mod args; +pub use args::Args; + +mod hashes; +mod return_channel; +pub use return_channel::ReturnChannel; diff --git a/src/return_channel.rs b/src/return_channel.rs new file mode 100644 index 0000000..4019d91 --- /dev/null +++ b/src/return_channel.rs @@ -0,0 +1,78 @@ +use std::sync::{Arc, Condvar, Mutex}; + +pub struct ReturnChannel { + value: Mutex>, + condvar: Condvar, +} + +impl ReturnChannel { + pub fn new() -> (ReturnChannelSender, ReturnChannelReceiver) { + let inner = ReturnChannel { + value: Mutex::new(None), + condvar: Condvar::new(), + }; + + let arc = Arc::new(inner); + + let ret_tx = ReturnChannelSender(arc.clone()); + let ret_rx = ReturnChannelReceiver(arc); + + (ret_tx, ret_rx) + } +} + +struct ReturnChannelReceiver(Arc>); +struct ReturnChannelSender(Arc>); + +impl ReturnChannelReceiver { + pub fn receive(self) -> T { + let mut val = self.0.value.lock().unwrap(); + + while val.is_none() { + val = self.0.condvar.wait(val).unwrap() + } + + let replace = val.take(); + + replace.unwrap() + } +} + +impl ReturnChannelSender { + pub fn send(self, val: T) { + let mut lock = self.0.value.lock().unwrap(); + + *lock = Some(val); + + self.0.condvar.notify_all(); + } +} + +#[cfg(test)] +mod test { + pub use super::*; + + #[test] + fn test_channel_single_thread() { + let (tx, rx) = ReturnChannel::new(); + + tx.send(42); + + let rx = rx.receive(); + + assert_eq!(rx, 42); + } + + #[test] + fn test_channel_multi_thread() { + let (tx, rx) = ReturnChannel::new(); + + std::thread::spawn(|| { + tx.send(42); + }); + + let rx = rx.receive(); + + assert_eq!(rx, 42); + } +}