rt: fix Runtime::reactor() as used by tokio-core (#721)

* rt: fix `Runtime::reactor()` as used by tokio-core

Up until Tokio v0.1.11, the handle returned by `Runtime::reactor()`
pointed to a reactor instance running in a background thread. The thread
was eagerly spawned.

As of v0.1.12, a reactor instance is created per runtime worker thread.
`Runtime::reactor()` was deprecated and updated to point to the reactor
for one of the worker threads.

A problem occurs when attempting to use the reactor before spawning a
task. Worker threads are spawned lazily, which means that the reactor
referenced by `Runtime::reactor()` is not yet running.

This patch changes `Runtime::reactor` back to a dedicated reactor
running on a background thread. However, the background thread is now
spawned lazily when the deprecated function is first called.

Fixes #720

* Fix comment

Co-Authored-By: carllerche <[email protected]>
This commit is contained in:
Carl Lerche
2018-10-25 11:23:54 +02:00
committed by Stjepan Glavina
parent f929576f0e
commit d011b92b9a
3 changed files with 48 additions and 8 deletions
+6 -4
View File
@@ -273,9 +273,6 @@ impl Builder {
// Get a handle to the clock for the runtime.
let clock = self.clock.clone();
// Get a handle to the first reactor.
let reactor = reactor_handles[0].clone();
let pool = self.threadpool_builder
.around_worker(move |w, enter| {
let index = w.id().to_usize();
@@ -299,9 +296,14 @@ impl Builder {
})
.build();
// To support deprecated `reactor()` function
let reactor = Reactor::new()?;
let reactor_handle = reactor.handle();
Ok(Runtime {
inner: Some(Inner {
reactor,
reactor_handle,
reactor: Mutex::new(Some(reactor)),
pool,
}),
})
+15 -4
View File
@@ -121,9 +121,10 @@ pub use self::builder::Builder;
pub use self::shutdown::Shutdown;
pub use self::task_executor::TaskExecutor;
use reactor::Handle;
use reactor::{Handle, Reactor};
use std::io;
use std::sync::Mutex;
use tokio_executor::enter;
use tokio_threadpool as threadpool;
@@ -152,8 +153,11 @@ pub struct Runtime {
#[derive(Debug)]
struct Inner {
/// A handle to one of the per-worker reactors.
reactor: Handle,
/// A handle to the reactor in the background thread.
reactor_handle: Handle,
// TODO: This should go away in 0.2
reactor: Mutex<Option<Reactor>>,
/// Task execution pool.
pool: threadpool::ThreadPool,
@@ -280,7 +284,14 @@ impl Runtime {
/// ```
#[deprecated(since = "0.1.11", note = "there is now a reactor per worker thread")]
pub fn reactor(&self) -> &Handle {
&self.inner().reactor
let mut reactor = self.inner().reactor.lock().unwrap();
if let Some(reactor) = reactor.take() {
if let Ok(background) = reactor.background() {
background.forget();
}
}
&self.inner().reactor_handle
}
/// Return a handle to the runtime's executor.