diff --git a/src/reactor/mod.rs b/src/reactor/mod.rs index 18bd2b3c..d654dbb5 100644 --- a/src/reactor/mod.rs +++ b/src/reactor/mod.rs @@ -671,6 +671,85 @@ impl Remote { } } +/// Retrieves a `Handle` for the currently running reactor +/// +/// Having to pass `Handle`s around can be frustrating. This function will retrieve +/// a handle from the current reactor when running on the same thread. This way, you +/// won't have to pass handles around if using the `Tokio` event loop to drive your +/// futures. As such, this function should be called from inside a reactor, otherwise +/// it will return an error. This means that:- +/// +/// 1. you should call it from inside a futures combinator or `async` macros (this +/// includes `async_block`) +/// 2. you should run any future that calls this method using `Core::run()`. +/// +/// # Examples +/// +/// A simple TCP echo server: +/// +/// ```no_run +/// extern crate futures; +/// extern crate tokio_io; +/// extern crate tokio_core; +/// +/// use futures::{Future, Stream, lazy}; +/// use tokio_io::io::copy; +/// use tokio_io::AsyncRead; +/// use tokio_core::net::TcpListener; +/// use tokio_core::reactor::{self, Core}; +/// +/// fn server() -> Box> { +/// let server = lazy(|| { +/// // Get a handle to the current reactor +/// let handle = reactor::current().unwrap(); +/// +/// // Bind the server's socket +/// let addr = "127.0.0.1:12345".parse().unwrap(); +/// let listener = TcpListener::bind(&addr, &handle).unwrap(); +/// +/// // Pull out a stream of sockets for incoming connections +/// listener.incoming().for_each(move |(sock, _)| { +/// // Split up the reading and writing parts of the +/// // socket +/// let (reader, writer) = sock.split(); +/// +/// // A future that echos the data and returns how +/// // many bytes were copied... +/// let bytes_copied = copy(reader, writer); +/// +/// // ... after which we'll print what happened +/// let handle_conn = bytes_copied.map(|amt| { +/// println!("wrote {} bytes", amt.0) +/// }).map_err(|err| { +/// println!("IO error {:?}", err) +/// }); +/// +/// // Spawn the future as a concurrent task +/// handle.spawn(handle_conn); +/// +/// Ok(()) +/// }) +/// }); +/// +/// Box::new(server) +/// } +/// +/// fn main() { +/// // Create the event loop that will drive this server +/// let mut core = Core::new().unwrap(); +/// // Spin up the server on the event loop +/// core.run(server()).unwrap(); +/// } +/// ``` +pub fn current() -> io::Result { + if CURRENT_LOOP.is_set() { + CURRENT_LOOP.with(|lp| Ok(lp.handle())) + } else { + let msg = "tokio_core::reactor::current() called outside of a reactor"; + Err(io::Error::new(io::ErrorKind::Other, msg)) + } +} + impl Executor for Remote where F: Future + Send + 'static, {