mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-24 00:00:11 +02:00
67 lines
1.4 KiB
Rust
67 lines
1.4 KiB
Rust
use tokio_sync::oneshot;
|
|||
|
|
|
||
|
|
use std::cell::RefCell;
|
||
|
|
use std::collections::VecDeque;
|
||
|
|
use std::future::Future;
|
||
|
|
use std::io;
|
||
|
|
use std::pin::Pin;
|
||
|
|
use std::task::{Context, Poll};
|
||
|
|
|
||
|
|
thread_local! {
|
||
|
|
static QUEUE: RefCell<VecDeque<Box<dyn FnOnce() + Send>>> = RefCell::new(VecDeque::new())
|
||
|
|
}
|
||
|
|
|
||
|
|
#[derive(Debug)]
|
||
|
|
pub(crate) struct Blocking<T> {
|
||
|
|
rx: oneshot::Receiver<T>,
|
||
|
|
}
|
||
|
|
|
||
|
|
pub(crate) fn run<F, R>(f: F) -> Blocking<R>
|
||
|
|
where
|
||
|
|
F: FnOnce() -> R + Send + 'static,
|
||
|
|
R: Send + 'static,
|
||
|
|
{
|
||
|
|
let (tx, rx) = oneshot::channel();
|
||
|
|
let task = Box::new(move || {
|
||
|
|
let _ = tx.send(f());
|
||
|
|
});
|
||
|
|
|
||
|
|
QUEUE.with(|cell| cell.borrow_mut().push_back(task));
|
||
|
|
|
||
|
|
Blocking { rx }
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<T> Future for Blocking<T> {
|
||
|
|
type Output = T;
|
||
|
|
|
||
|
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||
|
|
use std::task::Poll::*;
|
||
|
|
|
||
|
|
match Pin::new(&mut self.rx).poll(cx) {
|
||
|
|
Ready(Ok(v)) => Ready(v),
|
||
|
|
Ready(Err(e)) => panic!("error = {:?}", e),
|
||
|
|
Pending => Pending,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub(crate) async fn asyncify<F, T>(f: F) -> io::Result<T>
|
||
|
|
where
|
||
|
|
F: FnOnce() -> io::Result<T> + Send + 'static,
|
||
|
|
T: Send + 'static,
|
||
|
|
{
|
||
|
|
run(f).await
|
||
|
|
}
|
||
|
|
|
||
|
|
pub(crate) fn len() -> usize {
|
||
|
|
QUEUE.with(|cell| cell.borrow().len())
|
||
|
|
}
|
||
|
|
|
||
|
|
pub(crate) fn run_one() {
|
||
|
|
let task = QUEUE
|
||
|
|
.with(|cell| cell.borrow_mut().pop_front())
|
||
|
|
.expect("expected task to run, but none ready");
|
||
|
|
|
||
|
|
task();
|
||
|
|
}
|