mirror of
https://github.com/tokio-rs/tokio.git
synced 2025-09-25 12:00:35 +00:00
117 lines
2.4 KiB
Rust
117 lines
2.4 KiB
Rust
#![deny(warnings, rust_2018_idioms)]
|
|
#![feature(async_await)]
|
|
|
|
#[path = "../src/oneshot.rs"]
|
|
#[allow(warnings)]
|
|
mod oneshot;
|
|
|
|
use loom;
|
|
use loom::future::block_on;
|
|
use loom::thread;
|
|
|
|
use futures_util::future::poll_fn;
|
|
use std::task::Poll::{Pending, Ready};
|
|
|
|
#[test]
|
|
fn smoke() {
|
|
loom::model(|| {
|
|
let (tx, rx) = oneshot::channel();
|
|
|
|
thread::spawn(move || {
|
|
tx.send(1).unwrap();
|
|
});
|
|
|
|
let value = block_on(rx).unwrap();
|
|
assert_eq!(1, value);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn changing_rx_task() {
|
|
loom::model(|| {
|
|
let (tx, mut rx) = oneshot::channel();
|
|
|
|
thread::spawn(move || {
|
|
tx.send(1).unwrap();
|
|
});
|
|
|
|
let rx = thread::spawn(move || {
|
|
let ready = block_on(poll_fn(|cx| match Pin::new(&mut rx).poll(cx) {
|
|
Ready(Ok(value)) => {
|
|
assert_eq!(1, value);
|
|
Ready(true)
|
|
}
|
|
Ready(Err(_)) => unimplemented!(),
|
|
Pending => Ready(false),
|
|
}));
|
|
|
|
if ready {
|
|
None
|
|
} else {
|
|
Some(rx)
|
|
}
|
|
})
|
|
.join()
|
|
.unwrap();
|
|
|
|
if let Some(rx) = rx {
|
|
// Previous task parked, use a new task...
|
|
let value = block_on(rx).unwrap();
|
|
assert_eq!(1, value);
|
|
}
|
|
});
|
|
}
|
|
|
|
// TODO: Move this into `oneshot` proper.
|
|
|
|
use std::future::Future;
|
|
use std::pin::Pin;
|
|
use std::task::{Context, Poll};
|
|
|
|
struct OnClose<'a> {
|
|
tx: &'a mut oneshot::Sender<i32>,
|
|
}
|
|
|
|
impl<'a> OnClose<'a> {
|
|
fn new(tx: &'a mut oneshot::Sender<i32>) -> Self {
|
|
OnClose { tx }
|
|
}
|
|
}
|
|
|
|
impl<'a> Future for OnClose<'a> {
|
|
type Output = bool;
|
|
|
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<bool> {
|
|
let res = self.get_mut().tx.poll_closed(cx);
|
|
Ready(res.is_ready())
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn changing_tx_task() {
|
|
loom::model(|| {
|
|
let (mut tx, rx) = oneshot::channel::<i32>();
|
|
|
|
thread::spawn(move || {
|
|
drop(rx);
|
|
});
|
|
|
|
let tx = thread::spawn(move || {
|
|
let t1 = block_on(OnClose::new(&mut tx));
|
|
|
|
if t1 {
|
|
None
|
|
} else {
|
|
Some(tx)
|
|
}
|
|
})
|
|
.join()
|
|
.unwrap();
|
|
|
|
if let Some(mut tx) = tx {
|
|
// Previous task parked, use a new task...
|
|
block_on(OnClose::new(&mut tx));
|
|
}
|
|
});
|
|
}
|