124 lines
2.5 KiB
Rust
124 lines
2.5 KiB
Rust
use notify::{Listener, Notify};
|
|
use std::{
|
|
sync::{Arc, Mutex},
|
|
time::Duration,
|
|
};
|
|
|
|
struct Sender<T> {
|
|
item: Arc<Mutex<Option<Result<T, Dropped>>>>,
|
|
notify: Notify,
|
|
}
|
|
|
|
struct Receiver<T> {
|
|
item: Arc<Mutex<Option<Result<T, Dropped>>>>,
|
|
listener: Listener,
|
|
}
|
|
|
|
struct Dropped;
|
|
|
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
jive::block_on(async move {
|
|
let (tx, rx) = oneshot();
|
|
|
|
jive::spawn(async move {
|
|
jive::time::sleep(Duration::from_secs(1)).await;
|
|
let _ = tx.send(5);
|
|
});
|
|
|
|
if let Ok(val) = rx.recv().await {
|
|
println!("Got {}", val);
|
|
}
|
|
});
|
|
|
|
let (tx, rx) = oneshot();
|
|
|
|
std::thread::spawn(move || {
|
|
std::thread::sleep(Duration::from_secs(1));
|
|
let _ = tx.send(-5);
|
|
});
|
|
|
|
if let Ok(val) = rx.recv_blocking() {
|
|
println!("Got {}", val);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn oneshot<T>() -> (Sender<T>, Receiver<T>) {
|
|
let item = Arc::new(Mutex::new(None));
|
|
let notify = Notify::new();
|
|
let listener = notify.listener();
|
|
|
|
(
|
|
Sender {
|
|
item: Arc::clone(&item),
|
|
notify,
|
|
},
|
|
Receiver { item, listener },
|
|
)
|
|
}
|
|
|
|
impl<T> Sender<T> {
|
|
pub fn send(self, item: T) -> Result<(), T> {
|
|
let mut guard = self.item.lock().unwrap();
|
|
|
|
if let Some(Err(Dropped)) = guard.take() {
|
|
return Err(item);
|
|
}
|
|
|
|
*guard = Some(Ok(item));
|
|
self.notify.notify_one();
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl<T> Receiver<T> {
|
|
pub fn try_recv(&self) -> Option<Result<T, Dropped>> {
|
|
let mut guard = self.item.lock().unwrap();
|
|
|
|
if guard.is_some() {
|
|
return guard.replace(Err(Dropped));
|
|
}
|
|
|
|
None
|
|
}
|
|
|
|
pub async fn recv(mut self) -> Result<T, Dropped> {
|
|
loop {
|
|
if let Some(res) = self.try_recv() {
|
|
return res;
|
|
}
|
|
|
|
self.listener.listen().await;
|
|
}
|
|
}
|
|
|
|
pub fn recv_blocking(self) -> Result<T, Dropped> {
|
|
loop {
|
|
if let Some(res) = self.try_recv() {
|
|
return res;
|
|
}
|
|
|
|
self.listener.listen_blocking();
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T> Drop for Sender<T> {
|
|
fn drop(&mut self) {
|
|
let mut guard = self.item.lock().unwrap();
|
|
if guard.is_none() {
|
|
*guard = Some(Err(Dropped));
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T> Drop for Receiver<T> {
|
|
fn drop(&mut self) {
|
|
let mut guard = self.item.lock().unwrap();
|
|
if guard.is_none() {
|
|
*guard = Some(Err(Dropped));
|
|
}
|
|
}
|
|
}
|