mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-21 00:00:10 +02:00
Removes the `Send` requirement to futures passed to `Runtime::block_on`. Previously, `block_on` was implemented by sending the future to a runtime thread. In order to do this, the future must be Send. The reason why the future is sent to the pool is because we cannot guarantee, while off the pool, that a reactor / timer thread is running. This is due to a limitation in the current version of tokio-threadpool. There is a plan to fix this (#1177), but the proper fix is non trivial. In order to unblock APIs that require this, this patch updates the runtime to spawn an always running thread containing a reactor and timer. All calls to `block_on` will use that reactor and timer.
62 lines
1.5 KiB
Rust
62 lines
1.5 KiB
Rust
//! Temporary reactor + timer that runs on a background thread. This it to make
|
|
//! `block_on` work.
|
|
|
|
use tokio_current_thread::CurrentThread;
|
|
use tokio_reactor::Reactor;
|
|
use tokio_sync::oneshot;
|
|
use tokio_timer::clock::Clock;
|
|
use tokio_timer::timer::{self, Timer};
|
|
|
|
use std::{io, thread};
|
|
|
|
#[derive(Debug)]
|
|
pub struct Background {
|
|
reactor_handle: tokio_reactor::Handle,
|
|
timer_handle: timer::Handle,
|
|
shutdown_tx: Option<oneshot::Sender<()>>,
|
|
thread: Option<thread::JoinHandle<()>>,
|
|
}
|
|
|
|
pub fn spawn(clock: &Clock) -> io::Result<Background> {
|
|
let clock = clock.clone();
|
|
|
|
let reactor = Reactor::new()?;
|
|
let reactor_handle = reactor.handle();
|
|
|
|
let timer = Timer::new_with_now(reactor, clock);
|
|
let timer_handle = timer.handle();
|
|
|
|
let (shutdown_tx, shutdown_rx) = oneshot::channel();
|
|
let shutdown_tx = Some(shutdown_tx);
|
|
|
|
let thread = thread::spawn(move || {
|
|
let mut rt = CurrentThread::new_with_park(timer);
|
|
let _ = rt.block_on(shutdown_rx);
|
|
});
|
|
let thread = Some(thread);
|
|
|
|
Ok(Background {
|
|
reactor_handle,
|
|
timer_handle,
|
|
shutdown_tx,
|
|
thread,
|
|
})
|
|
}
|
|
|
|
impl Background {
|
|
pub(super) fn reactor(&self) -> &tokio_reactor::Handle {
|
|
&self.reactor_handle
|
|
}
|
|
|
|
pub(super) fn timer(&self) -> &timer::Handle {
|
|
&self.timer_handle
|
|
}
|
|
}
|
|
|
|
impl Drop for Background {
|
|
fn drop(&mut self) {
|
|
let _ = self.shutdown_tx.take().unwrap().send(());
|
|
let _ = self.thread.take().unwrap().join();
|
|
}
|
|
}
|