Files
tokio/src/reactor/mod.rs
T

895 lines
28 KiB
Rust
Raw Normal View History

2016-09-02 11:07:52 -07:00
//! The core reactor driving all I/O
//!
//! This module contains the `Core` type which is the reactor for all I/O
//! happening in `tokio-core`. This reactor (or event loop) is used to run
//! futures, schedule tasks, issue I/O requests, etc.
2016-08-20 23:23:16 -07:00
use std::cell::RefCell;
use std::cmp;
2017-03-06 12:15:29 -08:00
use std::fmt;
2016-08-20 23:23:16 -07:00
use std::io::{self, ErrorKind};
use std::mem;
2016-09-02 11:07:52 -07:00
use std::rc::{Rc, Weak};
2016-08-20 23:23:16 -07:00
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use std::time::{Instant, Duration};
2017-02-05 17:06:57 -08:00
use futures::{Future, IntoFuture, Async};
2017-05-16 08:56:30 -07:00
use futures::future::{self, Executor, ExecuteError};
use futures::executor::{self, Spawn, Notify};
2017-01-10 00:02:53 -08:00
use futures::sync::mpsc;
2017-01-05 20:41:36 +05:30
use futures::task::Task;
2016-08-20 23:23:16 -07:00
use mio;
2017-02-05 17:06:57 -08:00
use mio::event::Evented;
2016-08-20 23:23:16 -07:00
use slab::Slab;
2016-09-07 23:59:51 -07:00
use heap::{Heap, Slot};
2016-08-20 23:23:16 -07:00
2016-09-02 11:07:52 -07:00
mod io_token;
mod timeout_token;
2016-08-20 23:23:16 -07:00
2016-09-02 11:07:52 -07:00
mod poll_evented;
mod timeout;
2016-10-06 01:59:26 +03:00
mod interval;
2016-09-07 16:11:19 -07:00
pub use self::poll_evented::PollEvented;
pub use self::timeout::Timeout;
2016-10-06 01:59:26 +03:00
pub use self::interval::Interval;
2016-09-02 11:07:52 -07:00
2016-08-20 23:23:16 -07:00
static NEXT_LOOP_ID: AtomicUsize = ATOMIC_USIZE_INIT;
2016-09-02 11:07:52 -07:00
scoped_thread_local!(static CURRENT_LOOP: Core);
2016-08-20 23:23:16 -07:00
/// An event loop.
///
/// The event loop is the main source of blocking in an application which drives
/// all other I/O events and notifications happening. Each event loop can have
/// multiple handles pointing to it, each of which can then be used to create
/// various I/O objects to interact with the event loop in interesting ways.
// TODO: expand this
2016-09-02 11:07:52 -07:00
pub struct Core {
2016-08-20 23:23:16 -07:00
events: mio::Events,
2017-01-10 00:02:53 -08:00
tx: mpsc::UnboundedSender<Message>,
rx: RefCell<Spawn<mpsc::UnboundedReceiver<Message>>>,
_rx_registration: mio::Registration,
rx_readiness: Arc<MySetReadiness>,
2016-09-07 16:11:19 -07:00
inner: Rc<RefCell<Inner>>,
2016-08-31 00:19:29 -07:00
// Used for determining when the future passed to `run` is ready. Once the
// registration is passed to `io` above we never touch it again, just keep
// it alive.
2016-08-20 23:23:16 -07:00
_future_registration: mio::Registration,
2016-08-31 00:19:29 -07:00
future_readiness: Arc<MySetReadiness>,
2016-09-07 16:11:19 -07:00
}
struct Inner {
id: usize,
io: mio::Poll,
// Dispatch slabs for I/O and futures events
io_dispatch: Slab<ScheduledIo>,
task_dispatch: Slab<ScheduledTask>,
2016-08-20 23:23:16 -07:00
// Timer wheel keeping track of all timeouts. The `usize` stored in the
// timer wheel is an index into the slab below.
//
// The slab below keeps track of the timeouts themselves as well as the
// state of the timeout itself. The `TimeoutToken` type is an index into the
// `timeouts` slab.
2016-09-07 23:59:51 -07:00
timer_heap: Heap<(Instant, usize)>,
2016-09-08 07:46:47 -07:00
timeouts: Slab<(Option<Slot>, TimeoutState)>,
2016-08-20 23:23:16 -07:00
}
2017-01-15 15:15:37 +01:00
/// An unique ID for a Core
///
/// An ID by which different cores may be distinguished. Can be compared and used as an index in
/// a `HashMap`.
///
/// The ID is globally unique and never reused.
#[derive(Clone,Copy,Eq,PartialEq,Hash,Debug)]
pub struct CoreId(usize);
2016-08-20 23:23:16 -07:00
/// Handle to an event loop, used to construct I/O objects, send messages, and
/// otherwise interact indirectly with the event loop itself.
///
/// Handles can be cloned, and when cloned they will still refer to the
/// same underlying event loop.
#[derive(Clone)]
2016-09-07 16:11:19 -07:00
pub struct Remote {
2016-08-20 23:23:16 -07:00
id: usize,
2017-01-10 00:02:53 -08:00
tx: mpsc::UnboundedSender<Message>,
2016-08-20 23:23:16 -07:00
}
/// A non-sendable handle to an event loop, useful for manufacturing instances
/// of `LoopData`.
#[derive(Clone)]
2016-09-07 16:11:19 -07:00
pub struct Handle {
remote: Remote,
inner: Weak<RefCell<Inner>>,
2016-08-20 23:23:16 -07:00
}
2016-08-31 00:19:29 -07:00
struct ScheduledIo {
2016-08-20 23:23:16 -07:00
readiness: Arc<AtomicUsize>,
2016-08-31 00:19:29 -07:00
reader: Option<Task>,
writer: Option<Task>,
}
struct ScheduledTask {
_registration: mio::Registration,
spawn: Option<Spawn<Box<Future<Item=(), Error=()>>>>,
2017-05-16 08:56:30 -07:00
wake: Option<Arc<MySetReadiness>>,
2016-08-31 00:19:29 -07:00
}
2016-08-20 23:23:16 -07:00
enum TimeoutState {
NotFired,
Fired,
2016-08-31 00:19:29 -07:00
Waiting(Task),
2016-08-20 23:23:16 -07:00
}
enum Direction {
Read,
Write,
}
enum Message {
DropSource(usize),
2016-08-31 00:19:29 -07:00
Schedule(usize, Task, Direction),
UpdateTimeout(usize, Task),
2016-10-06 01:59:26 +03:00
ResetTimeout(usize, Instant),
2016-08-20 23:23:16 -07:00
CancelTimeout(usize),
2016-08-31 00:19:29 -07:00
Run(Box<FnBox>),
2016-08-20 23:23:16 -07:00
}
2016-08-31 00:19:29 -07:00
const TOKEN_MESSAGES: mio::Token = mio::Token(0);
const TOKEN_FUTURE: mio::Token = mio::Token(1);
2016-09-07 16:11:19 -07:00
const TOKEN_START: usize = 2;
2016-08-31 00:19:29 -07:00
2016-09-02 11:07:52 -07:00
impl Core {
2016-08-20 23:23:16 -07:00
/// Creates a new event loop, returning any error that happened during the
/// creation.
2016-09-02 11:07:52 -07:00
pub fn new() -> io::Result<Core> {
2016-08-20 23:23:16 -07:00
let io = try!(mio::Poll::new());
2017-02-05 17:06:57 -08:00
let future_pair = mio::Registration::new2();
try!(io.register(&future_pair.0,
TOKEN_FUTURE,
mio::Ready::readable(),
mio::PollOpt::level()));
2017-01-10 00:02:53 -08:00
let (tx, rx) = mpsc::unbounded();
2017-02-05 17:06:57 -08:00
let channel_pair = mio::Registration::new2();
try!(io.register(&channel_pair.0,
TOKEN_MESSAGES,
mio::Ready::readable(),
mio::PollOpt::level()));
2017-01-10 00:02:53 -08:00
let rx_readiness = Arc::new(MySetReadiness(channel_pair.1));
2017-05-16 08:56:30 -07:00
rx_readiness.notify(0);
2017-01-10 00:02:53 -08:00
2016-09-02 11:07:52 -07:00
Ok(Core {
2016-08-30 14:45:29 -07:00
events: mio::Events::with_capacity(1024),
2016-09-02 11:07:52 -07:00
tx: tx,
2017-01-10 00:02:53 -08:00
rx: RefCell::new(executor::spawn(rx)),
_rx_registration: channel_pair.0,
rx_readiness: rx_readiness,
2016-08-31 00:19:29 -07:00
_future_registration: future_pair.0,
future_readiness: Arc::new(MySetReadiness(future_pair.1)),
2016-09-07 16:11:19 -07:00
inner: Rc::new(RefCell::new(Inner {
id: NEXT_LOOP_ID.fetch_add(1, Ordering::Relaxed),
io: io,
2016-12-16 13:37:59 -05:00
io_dispatch: Slab::with_capacity(1),
task_dispatch: Slab::with_capacity(1),
timeouts: Slab::with_capacity(1),
2016-09-07 23:59:51 -07:00
timer_heap: Heap::new(),
2016-09-07 16:11:19 -07:00
})),
2016-08-20 23:23:16 -07:00
})
}
2016-09-07 16:11:19 -07:00
/// Returns a handle to this event loop which cannot be sent across threads
/// but can be used as a proxy to the event loop itself.
2016-08-20 23:23:16 -07:00
///
2016-09-07 16:11:19 -07:00
/// Handles are cloneable and clones always refer to the same event loop.
/// This handle is typically passed into functions that create I/O objects
/// to bind them to this event loop.
2016-09-02 11:07:52 -07:00
pub fn handle(&self) -> Handle {
Handle {
2016-09-07 16:11:19 -07:00
remote: self.remote(),
inner: Rc::downgrade(&self.inner),
2016-08-20 23:23:16 -07:00
}
}
2016-09-07 16:11:19 -07:00
/// Generates a remote handle to this event loop which can be used to spawn
/// tasks from other threads into this event loop.
pub fn remote(&self) -> Remote {
Remote {
id: self.inner.borrow().id,
tx: self.tx.clone(),
2016-08-20 23:23:16 -07:00
}
}
/// Runs a future until completion, driving the event loop while we're
/// otherwise waiting for the future to complete.
///
/// This function will begin executing the event loop and will finish once
2017-02-27 11:07:19 +01:00
/// the provided future is resolved. Note that the future argument here
2016-08-20 23:23:16 -07:00
/// crucially does not require the `'static` nor `Send` bounds. As a result
/// the future will be "pinned" to not only this thread but also this stack
/// frame.
///
2017-03-03 18:38:56 +00:00
/// This function will return the value that the future resolves to once
2016-08-20 23:23:16 -07:00
/// the future has finished. If the future never resolves then this function
/// will never return.
///
/// # Panics
///
/// This method will **not** catch panics from polling the future `f`. If
/// the future panics then it's the responsibility of the caller to catch
/// that panic and handle it as appropriate.
2016-08-31 00:19:29 -07:00
pub fn run<F>(&mut self, f: F) -> Result<F::Item, F::Error>
2016-08-20 23:23:16 -07:00
where F: Future,
{
2017-01-05 20:41:36 +05:30
let mut task = executor::spawn(f);
2016-11-11 14:27:49 -08:00
let mut future_fired = true;
loop {
if future_fired {
let res = try!(CURRENT_LOOP.set(self, || {
2017-05-16 08:56:30 -07:00
task.poll_future_notify(&self.future_readiness, 0)
2016-11-11 14:27:49 -08:00
}));
if let Async::Ready(e) = res {
return Ok(e)
}
2016-08-20 23:23:16 -07:00
}
2016-11-11 14:27:49 -08:00
future_fired = self.poll(None);
}
2016-08-20 23:23:16 -07:00
}
/// Performs one iteration of the event loop, blocking on waiting for events
/// for at most `max_wait` (forever if `None`).
///
/// It only makes sense to call this method if you've previously spawned
/// a future onto this event loop.
///
/// `loop { lp.turn(None) }` is equivalent to calling `run` with an
/// empty future (one that never finishes).
pub fn turn(&mut self, max_wait: Option<Duration>) {
2016-11-11 14:27:49 -08:00
self.poll(max_wait);
}
2016-11-11 14:27:49 -08:00
fn poll(&mut self, max_wait: Option<Duration>) -> bool {
// Given the `max_wait` variable specified, figure out the actual
// timeout that we're going to pass to `poll`. This involves taking a
// look at active timers on our heap as well.
let start = Instant::now();
2016-11-11 14:27:49 -08:00
let timeout = self.inner.borrow_mut().timer_heap.peek().map(|t| {
if t.0 < start {
Duration::new(0, 0)
} else {
2016-11-11 14:27:49 -08:00
t.0 - start
2016-08-20 23:23:16 -07:00
}
2016-11-11 14:27:49 -08:00
});
let timeout = match (max_wait, timeout) {
(Some(d1), Some(d2)) => Some(cmp::min(d1, d2)),
(max_wait, timeout) => max_wait.or(timeout),
};
// Block waiting for an event to happen, peeling out how many events
// happened.
let amt = match self.inner.borrow_mut().io.poll(&mut self.events, timeout) {
Ok(a) => a,
Err(ref e) if e.kind() == ErrorKind::Interrupted => return false,
Err(e) => panic!("error in poll: {}", e),
};
let after_poll = Instant::now();
debug!("loop poll - {:?}", after_poll - start);
debug!("loop time - {:?}", after_poll);
// Process all timeouts that may have just occurred, updating the
// current time since
self.consume_timeouts(after_poll);
// Process all the events that came in, dispatching appropriately
let mut fired = false;
for i in 0..self.events.len() {
let event = self.events.get(i).unwrap();
let token = event.token();
2017-02-05 17:06:57 -08:00
trace!("event {:?} {:?}", event.readiness(), event.token());
if token == TOKEN_MESSAGES {
2017-02-05 17:06:57 -08:00
self.rx_readiness.0.set_readiness(mio::Ready::empty()).unwrap();
CURRENT_LOOP.set(&self, || self.consume_queue());
} else if token == TOKEN_FUTURE {
2017-02-05 17:06:57 -08:00
self.future_readiness.0.set_readiness(mio::Ready::empty()).unwrap();
2016-11-11 14:27:49 -08:00
fired = true;
} else {
2017-02-05 17:06:57 -08:00
self.dispatch(token, event.readiness());
}
2016-08-20 23:23:16 -07:00
}
2016-11-11 14:27:49 -08:00
debug!("loop process - {} events, {:?}", amt, after_poll.elapsed());
return fired
2016-08-20 23:23:16 -07:00
}
2016-09-07 16:11:19 -07:00
fn dispatch(&mut self, token: mio::Token, ready: mio::Ready) {
2016-08-31 00:19:29 -07:00
let token = usize::from(token) - TOKEN_START;
if token % 2 == 0 {
self.dispatch_io(token / 2, ready)
} else {
self.dispatch_task(token / 2)
}
}
2016-09-07 16:11:19 -07:00
fn dispatch_io(&mut self, token: usize, ready: mio::Ready) {
2016-08-31 00:19:29 -07:00
let mut reader = None;
let mut writer = None;
2016-09-07 16:11:19 -07:00
let mut inner = self.inner.borrow_mut();
if let Some(io) = inner.io_dispatch.get_mut(token) {
2017-05-19 09:56:35 -07:00
io.readiness.fetch_or(ready2usize(ready), Ordering::Relaxed);
2016-08-31 00:19:29 -07:00
if ready.is_writable() {
writer = io.writer.take();
2017-05-19 09:56:35 -07:00
}
if !(ready & (!mio::Ready::writable())).is_empty() {
reader = io.reader.take();
2016-08-31 00:19:29 -07:00
}
}
2016-09-07 16:11:19 -07:00
drop(inner);
2016-08-31 00:19:29 -07:00
// TODO: don't notify the same task twice
if let Some(reader) = reader {
self.notify_handle(reader);
}
if let Some(writer) = writer {
self.notify_handle(writer);
}
}
2016-09-07 16:11:19 -07:00
fn dispatch_task(&mut self, token: usize) {
let mut inner = self.inner.borrow_mut();
let (task, wake) = match inner.task_dispatch.get_mut(token) {
2017-05-16 08:56:30 -07:00
Some(slot) => (slot.spawn.take(), slot.wake.take()),
2016-08-31 00:19:29 -07:00
None => return,
};
2017-05-16 08:56:30 -07:00
let (mut task, wake) = match (task, wake) {
(Some(task), Some(wake)) => (task, wake),
_ => return,
2016-08-31 00:19:29 -07:00
};
2017-05-16 08:56:30 -07:00
wake.0.set_readiness(mio::Ready::empty()).unwrap();
2016-09-07 16:11:19 -07:00
drop(inner);
2017-05-16 08:56:30 -07:00
let res = CURRENT_LOOP.set(self, || {
task.poll_future_notify(&wake, 0)
});
2017-05-07 21:17:57 -07:00
let _task_to_drop;
2016-09-07 16:11:19 -07:00
inner = self.inner.borrow_mut();
2016-08-31 00:19:29 -07:00
match res {
2016-09-01 16:42:48 -07:00
Ok(Async::NotReady) => {
2016-09-07 16:11:19 -07:00
assert!(inner.task_dispatch[token].spawn.is_none());
inner.task_dispatch[token].spawn = Some(task);
2017-05-16 08:56:30 -07:00
inner.task_dispatch[token].wake = Some(wake);
2016-08-31 00:19:29 -07:00
}
2016-09-01 16:42:48 -07:00
Ok(Async::Ready(())) |
Err(()) => {
2017-05-07 21:17:57 -07:00
_task_to_drop = inner.task_dispatch.remove(token).unwrap();
2016-08-31 00:19:29 -07:00
}
}
2017-05-07 21:17:57 -07:00
drop(inner);
2016-08-31 00:19:29 -07:00
}
2016-08-20 23:23:16 -07:00
fn consume_timeouts(&mut self, now: Instant) {
2016-09-07 16:11:19 -07:00
loop {
let mut inner = self.inner.borrow_mut();
2016-09-07 23:59:51 -07:00
match inner.timer_heap.peek() {
Some(head) if head.0 <= now => {}
Some(_) => break,
2016-09-07 16:11:19 -07:00
None => break,
};
2016-09-07 23:59:51 -07:00
let (_, slab_idx) = inner.timer_heap.pop().unwrap();
trace!("firing timeout: {}", slab_idx);
2016-09-08 07:46:47 -07:00
inner.timeouts[slab_idx].0.take().unwrap();
2016-09-07 23:59:51 -07:00
let handle = inner.timeouts[slab_idx].1.fire();
2016-09-07 16:11:19 -07:00
drop(inner);
2016-08-20 23:23:16 -07:00
if let Some(handle) = handle {
self.notify_handle(handle);
}
}
}
/// Method used to notify a task handle.
///
2017-05-16 08:56:30 -07:00
/// Note that this should be used instead of `handle.notify()` to ensure
2016-08-20 23:23:16 -07:00
/// that the `CURRENT_LOOP` variable is set appropriately.
2016-08-31 00:19:29 -07:00
fn notify_handle(&self, handle: Task) {
2016-08-20 23:23:16 -07:00
debug!("notifying a task handle");
2017-05-16 08:56:30 -07:00
CURRENT_LOOP.set(&self, || handle.notify());
2016-08-20 23:23:16 -07:00
}
2016-09-07 16:11:19 -07:00
fn consume_queue(&self) {
debug!("consuming notification queue");
// TODO: can we do better than `.unwrap()` here?
2017-01-10 00:02:53 -08:00
loop {
2017-05-16 08:56:30 -07:00
let msg = self.rx.borrow_mut().poll_stream_notify(&self.rx_readiness, 0).unwrap();
match msg {
2017-01-10 00:02:53 -08:00
Async::Ready(Some(msg)) => self.notify(msg),
Async::NotReady |
Async::Ready(None) => break,
}
2016-09-07 16:11:19 -07:00
}
}
fn notify(&self, msg: Message) {
match msg {
Message::DropSource(tok) => self.inner.borrow_mut().drop_source(tok),
Message::Schedule(tok, wake, dir) => {
let task = self.inner.borrow_mut().schedule(tok, wake, dir);
if let Some(task) = task {
self.notify_handle(task);
}
}
Message::UpdateTimeout(t, handle) => {
let task = self.inner.borrow_mut().update_timeout(t, handle);
if let Some(task) = task {
self.notify_handle(task);
}
}
2016-10-06 01:59:26 +03:00
Message::ResetTimeout(t, at) => {
self.inner.borrow_mut().reset_timeout(t, at);
}
2016-09-07 16:11:19 -07:00
Message::CancelTimeout(t) => {
self.inner.borrow_mut().cancel_timeout(t)
}
Message::Run(r) => r.call_box(self),
}
}
2017-01-15 15:15:37 +01:00
/// Get the ID of this loop
pub fn id(&self) -> CoreId {
CoreId(self.inner.borrow().id)
}
2016-09-07 16:11:19 -07:00
}
2017-05-16 08:56:30 -07:00
impl<F> Executor<F> for Core
where F: Future<Item = (), Error = ()> + 'static,
{
fn execute(&self, future: F) -> Result<(), ExecuteError<F>> {
self.handle().execute(future)
}
}
2017-03-06 12:15:29 -08:00
impl fmt::Debug for Core {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Core")
.field("id", &self.id())
.finish()
}
}
2016-09-07 16:11:19 -07:00
impl Inner {
2017-02-05 17:06:57 -08:00
fn add_source(&mut self, source: &Evented)
2016-08-20 23:23:16 -07:00
-> io::Result<(Arc<AtomicUsize>, usize)> {
debug!("adding a new I/O source");
2016-08-31 00:19:29 -07:00
let sched = ScheduledIo {
2016-08-20 23:23:16 -07:00
readiness: Arc::new(AtomicUsize::new(0)),
reader: None,
writer: None,
};
2016-09-07 16:11:19 -07:00
if self.io_dispatch.vacant_entry().is_none() {
let amt = self.io_dispatch.len();
self.io_dispatch.reserve_exact(amt);
2016-08-20 23:23:16 -07:00
}
2016-09-07 16:11:19 -07:00
let entry = self.io_dispatch.vacant_entry().unwrap();
2016-08-20 23:23:16 -07:00
try!(self.io.register(source,
2016-08-31 00:19:29 -07:00
mio::Token(TOKEN_START + entry.index() * 2),
2017-02-05 17:06:57 -08:00
mio::Ready::readable() |
mio::Ready::writable() |
platform::all(),
2016-08-20 23:23:16 -07:00
mio::PollOpt::edge()));
Ok((sched.readiness.clone(), entry.insert(sched).index()))
}
2017-02-05 17:06:57 -08:00
fn deregister_source(&mut self, source: &Evented) -> io::Result<()> {
self.io.deregister(source)
}
2016-08-20 23:23:16 -07:00
2016-09-07 16:11:19 -07:00
fn drop_source(&mut self, token: usize) {
2016-08-20 23:23:16 -07:00
debug!("dropping I/O source: {}", token);
2016-09-07 16:11:19 -07:00
self.io_dispatch.remove(token).unwrap();
2016-08-20 23:23:16 -07:00
}
2016-09-07 16:11:19 -07:00
fn schedule(&mut self, token: usize, wake: Task, dir: Direction)
-> Option<Task> {
2016-08-20 23:23:16 -07:00
debug!("scheduling direction for: {}", token);
2016-09-07 16:11:19 -07:00
let sched = self.io_dispatch.get_mut(token).unwrap();
2017-05-19 09:56:35 -07:00
let (slot, ready) = match dir {
Direction::Read => (&mut sched.reader, !mio::Ready::writable()),
Direction::Write => (&mut sched.writer, mio::Ready::writable()),
2016-08-20 23:23:16 -07:00
};
2017-05-19 09:56:35 -07:00
if sched.readiness.load(Ordering::SeqCst) & ready2usize(ready) != 0 {
debug!("cancelling block");
2016-09-07 16:11:19 -07:00
*slot = None;
Some(wake)
} else {
2017-05-19 09:56:35 -07:00
debug!("blocking");
2016-09-07 16:11:19 -07:00
*slot = Some(wake);
None
2016-08-20 23:23:16 -07:00
}
}
2016-10-06 21:11:46 +03:00
fn add_timeout(&mut self, at: Instant) -> usize {
2016-09-07 16:11:19 -07:00
if self.timeouts.vacant_entry().is_none() {
let len = self.timeouts.len();
self.timeouts.reserve_exact(len);
2016-08-20 23:23:16 -07:00
}
2016-09-07 16:11:19 -07:00
let entry = self.timeouts.vacant_entry().unwrap();
2016-09-07 23:59:51 -07:00
let slot = self.timer_heap.push((at, entry.index()));
2016-09-08 07:46:47 -07:00
let entry = entry.insert((Some(slot), TimeoutState::NotFired));
2016-08-20 23:23:16 -07:00
debug!("added a timeout: {}", entry.index());
2016-10-06 21:11:46 +03:00
return entry.index();
2016-08-20 23:23:16 -07:00
}
2016-09-07 16:11:19 -07:00
fn update_timeout(&mut self, token: usize, handle: Task) -> Option<Task> {
2016-08-20 23:23:16 -07:00
debug!("updating a timeout: {}", token);
2016-09-07 16:11:19 -07:00
self.timeouts[token].1.block(handle)
2016-08-20 23:23:16 -07:00
}
2016-10-06 01:59:26 +03:00
fn reset_timeout(&mut self, token: usize, at: Instant) {
let pair = &mut self.timeouts[token];
// TODO: avoid remove + push and instead just do one sift of the heap?
// In theory we could update it in place and then do the percolation
// as necessary
if let Some(slot) = pair.0.take() {
self.timer_heap.remove(slot);
}
let slot = self.timer_heap.push((at, token));
*pair = (Some(slot), TimeoutState::NotFired);
debug!("set a timeout: {}", token);
}
2016-09-07 16:11:19 -07:00
fn cancel_timeout(&mut self, token: usize) {
2016-08-20 23:23:16 -07:00
debug!("cancel a timeout: {}", token);
2016-09-07 16:11:19 -07:00
let pair = self.timeouts.remove(token);
2016-09-08 07:46:47 -07:00
if let Some((Some(slot), _state)) = pair {
2016-09-07 23:59:51 -07:00
self.timer_heap.remove(slot);
2016-08-20 23:23:16 -07:00
}
}
2016-09-07 16:11:19 -07:00
fn spawn(&mut self, future: Box<Future<Item=(), Error=()>>) {
if self.task_dispatch.vacant_entry().is_none() {
let len = self.task_dispatch.len();
self.task_dispatch.reserve_exact(len);
2016-08-20 23:23:16 -07:00
}
2016-09-07 16:11:19 -07:00
let entry = self.task_dispatch.vacant_entry().unwrap();
let token = TOKEN_START + 2 * entry.index() + 1;
2017-02-05 17:06:57 -08:00
let pair = mio::Registration::new2();
self.io.register(&pair.0,
mio::Token(token),
mio::Ready::readable(),
mio::PollOpt::level())
.expect("cannot fail future registration with mio");
2016-09-07 16:11:19 -07:00
let unpark = Arc::new(MySetReadiness(pair.1));
2017-05-16 08:56:30 -07:00
unpark.notify(0);
entry.insert(ScheduledTask {
2017-01-05 20:41:36 +05:30
spawn: Some(executor::spawn(future)),
2017-05-16 08:56:30 -07:00
wake: Some(unpark),
2016-09-07 16:11:19 -07:00
_registration: pair.0,
});
2016-08-20 23:23:16 -07:00
}
}
2016-09-07 16:11:19 -07:00
impl Remote {
2016-08-20 23:23:16 -07:00
fn send(&self, msg: Message) {
self.with_loop(|lp| {
match lp {
Some(lp) => {
// Need to execute all existing requests first, to ensure
// that our message is processed "in order"
lp.consume_queue();
lp.notify(msg);
}
None => {
2017-01-23 20:06:03 -08:00
match mpsc::UnboundedSender::send(&self.tx, msg) {
2016-08-20 23:23:16 -07:00
Ok(()) => {}
2017-01-10 00:02:53 -08:00
// TODO: this error should punt upwards and we should
// notify the caller that the message wasn't
// received. This is tokio-core#17
Err(e) => drop(e),
2016-08-20 23:23:16 -07:00
}
}
}
})
}
fn with_loop<F, R>(&self, f: F) -> R
2016-09-02 11:07:52 -07:00
where F: FnOnce(Option<&Core>) -> R
2016-08-20 23:23:16 -07:00
{
if CURRENT_LOOP.is_set() {
CURRENT_LOOP.with(|lp| {
2016-09-07 16:11:19 -07:00
let same = lp.inner.borrow().id == self.id;
if same {
2016-08-20 23:23:16 -07:00
f(Some(lp))
} else {
f(None)
}
})
} else {
f(None)
}
}
2016-08-31 00:19:29 -07:00
2016-09-21 18:27:25 +02:00
/// Spawns a new future into the event loop this remote is associated with.
2016-08-31 00:19:29 -07:00
///
/// This function takes a closure which is executed within the context of
/// the I/O loop itself. The future returned by the closure will be
2017-05-12 17:58:57 +08:00
/// scheduled on the event loop and run to completion.
2016-08-31 00:19:29 -07:00
///
/// Note that while the closure, `F`, requires the `Send` bound as it might
/// cross threads, the future `R` does not.
///
/// # Panics
///
/// This method will **not** catch panics from polling the future `f`. If
/// the future panics then it's the responsibility of the caller to catch
/// that panic and handle it as appropriate.
2016-08-31 00:19:29 -07:00
pub fn spawn<F, R>(&self, f: F)
2016-09-07 16:11:19 -07:00
where F: FnOnce(&Handle) -> R + Send + 'static,
2016-08-31 00:19:29 -07:00
R: IntoFuture<Item=(), Error=()>,
R::Future: 'static,
{
2016-09-02 11:07:52 -07:00
self.send(Message::Run(Box::new(|lp: &Core| {
2016-09-07 16:11:19 -07:00
let f = f(&lp.handle());
lp.inner.borrow_mut().spawn(Box::new(f.into_future()));
2016-08-31 00:19:29 -07:00
})));
}
2017-01-15 15:15:37 +01:00
/// Return the ID of the represented Core
pub fn id(&self) -> CoreId {
CoreId(self.id)
}
/// Attempts to "promote" this remote to a handle, if possible.
///
/// This function is intended for structures which typically work through a
/// `Remote` but want to optimize runtime when the remote doesn't actually
/// leave the thread of the original reactor. This will attempt to return a
/// handle if the `Remote` is on the same thread as the event loop and the
/// event loop is running.
///
/// If this `Remote` has moved to a different thread or if the event loop is
/// running, then `None` may be returned. If you need to guarantee access to
/// a `Handle`, then you can call this function and fall back to using
/// `spawn` above if it returns `None`.
pub fn handle(&self) -> Option<Handle> {
if CURRENT_LOOP.is_set() {
CURRENT_LOOP.with(|lp| {
let same = lp.inner.borrow().id == self.id;
if same {
Some(lp.handle())
} else {
None
}
})
} else {
None
}
}
2016-08-20 23:23:16 -07:00
}
2017-05-16 08:56:30 -07:00
impl<F> Executor<F> for Remote
where F: Future<Item = (), Error = ()> + Send + 'static,
{
fn execute(&self, future: F) -> Result<(), ExecuteError<F>> {
self.spawn(|_| future);
Ok(())
}
}
2017-03-06 12:15:29 -08:00
impl fmt::Debug for Remote {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Remote")
.field("id", &self.id())
.finish()
}
}
2016-09-07 16:11:19 -07:00
impl Handle {
/// Returns a reference to the underlying remote handle to the event loop.
pub fn remote(&self) -> &Remote {
&self.remote
2016-08-20 23:23:16 -07:00
}
2016-09-21 18:27:25 +02:00
/// Spawns a new future on the event loop this handle is associated with.
///
/// # Panics
///
/// This method will **not** catch panics from polling the future `f`. If
/// the future panics then it's the responsibility of the caller to catch
/// that panic and handle it as appropriate.
2016-08-31 00:19:29 -07:00
pub fn spawn<F>(&self, f: F)
where F: Future<Item=(), Error=()> + 'static,
{
2016-09-07 16:11:19 -07:00
let inner = match self.inner.upgrade() {
2016-09-02 11:07:52 -07:00
Some(inner) => inner,
None => return,
};
2016-09-07 16:11:19 -07:00
inner.borrow_mut().spawn(Box::new(f));
2016-08-20 23:23:16 -07:00
}
2016-09-26 16:52:54 -07:00
/// Spawns a closure on this event loop.
///
/// This function is a convenience wrapper around the `spawn` function above
/// for running a closure wrapped in `futures::lazy`. It will spawn the
/// function `f` provided onto the event loop, and continue to run the
2016-09-28 03:20:33 +02:00
/// future returned by `f` on the event loop as well.
///
/// # Panics
///
/// This method will **not** catch panics from polling the future `f`. If
/// the future panics then it's the responsibility of the caller to catch
/// that panic and handle it as appropriate.
2016-09-26 16:52:54 -07:00
pub fn spawn_fn<F, R>(&self, f: F)
where F: FnOnce() -> R + 'static,
R: IntoFuture<Item=(), Error=()> + 'static,
{
2017-02-05 17:06:57 -08:00
self.spawn(future::lazy(f))
2016-09-26 16:52:54 -07:00
}
2017-01-15 15:15:37 +01:00
/// Return the ID of the represented Core
pub fn id(&self) -> CoreId {
self.remote.id()
}
2016-08-20 23:23:16 -07:00
}
2017-05-16 08:56:30 -07:00
impl<F> Executor<F> for Handle
where F: Future<Item = (), Error = ()> + 'static,
{
fn execute(&self, future: F) -> Result<(), ExecuteError<F>> {
self.spawn(future);
Ok(())
}
}
2017-03-06 12:15:29 -08:00
impl fmt::Debug for Handle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Handle")
.field("id", &self.id())
.finish()
}
}
2016-08-20 23:23:16 -07:00
impl TimeoutState {
2016-08-31 00:19:29 -07:00
fn block(&mut self, handle: Task) -> Option<Task> {
2016-08-20 23:23:16 -07:00
match *self {
TimeoutState::Fired => return Some(handle),
_ => {}
}
*self = TimeoutState::Waiting(handle);
None
}
2016-08-31 00:19:29 -07:00
fn fire(&mut self) -> Option<Task> {
2016-08-20 23:23:16 -07:00
match mem::replace(self, TimeoutState::Fired) {
TimeoutState::NotFired => None,
TimeoutState::Fired => panic!("fired twice?"),
TimeoutState::Waiting(handle) => Some(handle),
}
}
}
2016-08-31 00:19:29 -07:00
struct MySetReadiness(mio::SetReadiness);
2017-05-16 08:56:30 -07:00
impl Notify for MySetReadiness {
fn notify(&self, _id: usize) {
2016-08-31 00:19:29 -07:00
self.0.set_readiness(mio::Ready::readable())
.expect("failed to set readiness");
}
}
trait FnBox: Send + 'static {
2016-09-02 11:07:52 -07:00
fn call_box(self: Box<Self>, lp: &Core);
2016-08-31 00:19:29 -07:00
}
2016-09-02 11:07:52 -07:00
impl<F: FnOnce(&Core) + Send + 'static> FnBox for F {
fn call_box(self: Box<Self>, lp: &Core) {
2016-08-31 00:19:29 -07:00
(*self)(lp)
2016-08-20 23:23:16 -07:00
}
}
2017-02-05 17:06:57 -08:00
2017-05-19 09:56:35 -07:00
fn read_ready() -> mio::Ready {
mio::Ready::readable() | platform::hup()
}
const READ: usize = 1 << 0;
const WRITE: usize = 1 << 1;
fn ready2usize(ready: mio::Ready) -> usize {
let mut bits = 0;
if ready.is_readable() {
bits |= READ;
}
if ready.is_writable() {
bits |= WRITE;
}
bits | platform::ready2usize(ready)
}
fn usize2ready(bits: usize) -> mio::Ready {
let mut ready = mio::Ready::empty();
if bits & READ != 0 {
ready.insert(mio::Ready::readable());
}
if bits & WRITE != 0 {
ready.insert(mio::Ready::writable());
}
ready | platform::usize2ready(bits)
}
#[cfg(all(unix, not(target_os = "fuchsia")))]
2017-02-05 17:06:57 -08:00
mod platform {
use mio::Ready;
use mio::unix::UnixReady;
2017-05-21 10:24:08 -06:00
pub fn aio() -> Ready {
UnixReady::aio().into()
}
pub fn all() -> Ready {
hup() | aio()
}
2017-02-05 17:06:57 -08:00
pub fn hup() -> Ready {
UnixReady::hup().into()
}
2017-05-19 09:56:35 -07:00
const HUP: usize = 1 << 2;
const ERROR: usize = 1 << 3;
2017-05-21 10:24:08 -06:00
const AIO: usize = 1 << 4;
2017-05-19 09:56:35 -07:00
pub fn ready2usize(ready: Ready) -> usize {
let ready = UnixReady::from(ready);
let mut bits = 0;
2017-05-21 10:24:08 -06:00
if ready.is_aio() {
bits |= AIO;
}
2017-05-19 09:56:35 -07:00
if ready.is_error() {
bits |= ERROR;
}
if ready.is_hup() {
bits |= HUP;
}
bits
}
pub fn usize2ready(bits: usize) -> Ready {
let mut ready = UnixReady::from(Ready::empty());
2017-05-21 10:24:08 -06:00
if bits & AIO != 0 {
ready.insert(UnixReady::aio());
}
2017-05-19 09:56:35 -07:00
if bits & HUP != 0 {
ready.insert(UnixReady::hup());
}
if bits & ERROR != 0 {
ready.insert(UnixReady::error());
}
ready.into()
}
2017-02-05 17:06:57 -08:00
}
#[cfg(any(windows, target_os = "fuchsia"))]
2017-02-05 17:06:57 -08:00
mod platform {
use mio::Ready;
pub fn all() -> Ready {
// No platform-specific Readinesses for Windows
Ready::empty()
}
2017-05-19 09:56:35 -07:00
pub fn hup() -> Ready {
Ready::empty()
}
pub fn ready2usize(_r: Ready) -> usize {
0
2017-02-05 17:06:57 -08:00
}
2017-05-19 09:56:35 -07:00
pub fn usize2ready(_r: usize) -> Ready {
2017-02-05 17:06:57 -08:00
Ready::empty()
}
}