2017-12-05 16:55:25 +01:00
|
|
|
//! The core reactor driving all I/O.
|
2016-09-02 11:07:52 -07:00
|
|
|
//!
|
2017-12-05 09:02:07 -08:00
|
|
|
//! This module contains the [`Reactor`] reactor type which is the event loop for
|
2017-12-05 16:55:25 +01:00
|
|
|
//! all I/O happening in `tokio`. This core reactor (or event loop) is used to
|
|
|
|
|
//! drive I/O resources.
|
|
|
|
|
//!
|
|
|
|
|
//! The [`Handle`] and [`Remote`] structs are refences to the event loop,
|
|
|
|
|
//! created by the [`handle`][handle_method] and [`remote`][remote_method]
|
|
|
|
|
//! respectively, and are used to construct I/O objects. `Remote` is sendable,
|
|
|
|
|
//! while `Handle` is not.
|
|
|
|
|
//!
|
|
|
|
|
//! Lastly [`PollEvented`] can be used to construct I/O objects that interact
|
|
|
|
|
//! with the event loop, e.g. [`TcpStream`] in the net module.
|
|
|
|
|
//!
|
2017-12-05 09:02:07 -08:00
|
|
|
//! [`Reactor`]: struct.Reactor.html
|
2017-12-05 16:55:25 +01:00
|
|
|
//! [`Handle`]: struct.Handle.html
|
|
|
|
|
//! [`Remote`]: struct.Remote.html
|
2017-12-05 09:02:07 -08:00
|
|
|
//! [handle_method]: struct.Reactor.html#method.handle
|
|
|
|
|
//! [remote_method]: struct.Reactor.html#method.remote
|
2017-12-05 16:55:25 +01:00
|
|
|
//! [`PollEvented`]: struct.PollEvented.html
|
|
|
|
|
//! [`TcpStream`]: ../net/struct.TcpStream.html
|
2016-09-02 11:07:52 -07:00
|
|
|
|
2017-03-06 12:15:29 -08:00
|
|
|
use std::fmt;
|
2016-08-20 23:23:16 -07:00
|
|
|
use std::io::{self, ErrorKind};
|
2017-12-05 09:47:29 -08:00
|
|
|
use std::mem;
|
|
|
|
|
use std::sync::atomic::Ordering::{Relaxed, SeqCst};
|
|
|
|
|
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
|
2017-11-17 12:51:23 -08:00
|
|
|
use std::sync::{Arc, Weak, RwLock};
|
|
|
|
|
use std::time::{Duration};
|
2016-08-20 23:23:16 -07:00
|
|
|
|
2017-10-25 10:54:54 -07:00
|
|
|
use futures::{Future, Async};
|
2017-11-17 12:51:23 -08:00
|
|
|
use futures::executor::{self, Notify};
|
|
|
|
|
use futures::task::{AtomicTask};
|
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-02 11:07:52 -07:00
|
|
|
mod io_token;
|
2017-12-05 09:47:29 -08:00
|
|
|
mod global;
|
2016-08-20 23:23:16 -07:00
|
|
|
|
2016-09-02 11:07:52 -07:00
|
|
|
mod poll_evented;
|
2016-09-07 16:11:19 -07:00
|
|
|
pub use self::poll_evented::PollEvented;
|
2016-09-02 11:07:52 -07:00
|
|
|
|
2017-12-05 16:55:25 +01:00
|
|
|
/// The core reactor, or event loop.
|
2016-08-20 23:23:16 -07:00
|
|
|
///
|
|
|
|
|
/// 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.
|
2017-12-05 09:02:07 -08:00
|
|
|
pub struct Reactor {
|
2017-11-17 12:51:23 -08:00
|
|
|
/// Reuse the `mio::Events` value across calls to poll.
|
2016-08-20 23:23:16 -07:00
|
|
|
events: mio::Events,
|
2017-01-10 00:02:53 -08:00
|
|
|
|
2017-11-17 12:51:23 -08:00
|
|
|
/// State shared between the reactor and the handles.
|
|
|
|
|
inner: Arc<Inner>,
|
2016-08-31 00:19:29 -07:00
|
|
|
|
2017-11-17 12:51:23 -08: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 {
|
2017-11-17 12:51:23 -08:00
|
|
|
/// The underlying system event queue.
|
2016-09-07 16:11:19 -07:00
|
|
|
io: mio::Poll,
|
|
|
|
|
|
2017-11-17 12:51:23 -08:00
|
|
|
/// Dispatch slabs for I/O and futures events
|
|
|
|
|
io_dispatch: RwLock<Slab<ScheduledIo>>,
|
2016-08-20 23:23:16 -07:00
|
|
|
}
|
|
|
|
|
|
2017-12-05 08:15:26 -08:00
|
|
|
/// A handle to an event loop.
|
2016-08-20 23:23:16 -07:00
|
|
|
///
|
2017-12-05 08:15:26 -08:00
|
|
|
/// A `Handle` is used for associating I/O objects with an event loop
|
|
|
|
|
/// explicitly. Typically though you won't end up using a `Handle` that often
|
|
|
|
|
/// and will instead use and implicitly configured handle for your thread.
|
2016-08-20 23:23:16 -07:00
|
|
|
#[derive(Clone)]
|
2017-12-05 08:15:26 -08:00
|
|
|
pub struct Handle {
|
2017-11-17 12:51:23 -08:00
|
|
|
inner: Weak<Inner>,
|
2016-08-20 23:23:16 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-31 00:19:29 -07:00
|
|
|
struct ScheduledIo {
|
2017-11-17 12:51:23 -08:00
|
|
|
readiness: AtomicUsize,
|
|
|
|
|
reader: AtomicTask,
|
|
|
|
|
writer: AtomicTask,
|
2016-08-31 00:19:29 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-20 23:23:16 -07:00
|
|
|
enum Direction {
|
|
|
|
|
Read,
|
|
|
|
|
Write,
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-31 00:19:29 -07:00
|
|
|
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
|
|
|
|
2017-11-17 12:51:23 -08:00
|
|
|
fn _assert_kinds() {
|
|
|
|
|
fn _assert<T: Send + Sync>() {}
|
|
|
|
|
|
|
|
|
|
_assert::<Handle>();
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-05 09:02:07 -08:00
|
|
|
impl Reactor {
|
2016-08-20 23:23:16 -07:00
|
|
|
/// Creates a new event loop, returning any error that happened during the
|
|
|
|
|
/// creation.
|
2017-12-05 09:02:07 -08:00
|
|
|
pub fn new() -> io::Result<Reactor> {
|
2017-11-17 12:51:23 -08:00
|
|
|
// Create the I/O poller
|
2016-08-20 23:23:16 -07:00
|
|
|
let io = try!(mio::Poll::new());
|
2017-11-17 12:51:23 -08:00
|
|
|
|
|
|
|
|
// Create a registration for unblocking the reactor when the "run"
|
|
|
|
|
// future becomes ready.
|
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
|
|
|
|
2017-12-05 09:02:07 -08:00
|
|
|
Ok(Reactor {
|
2016-08-30 14:45:29 -07:00
|
|
|
events: mio::Events::with_capacity(1024),
|
2016-08-31 00:19:29 -07:00
|
|
|
_future_registration: future_pair.0,
|
|
|
|
|
future_readiness: Arc::new(MySetReadiness(future_pair.1)),
|
2017-11-17 12:51:23 -08:00
|
|
|
inner: Arc::new(Inner {
|
2016-09-07 16:11:19 -07:00
|
|
|
io: io,
|
2017-11-17 12:51:23 -08:00
|
|
|
io_dispatch: RwLock::new(Slab::with_capacity(1)),
|
|
|
|
|
}),
|
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 {
|
2017-12-05 08:15:26 -08:00
|
|
|
Handle {
|
2017-11-17 12:51:23 -08:00
|
|
|
inner: Arc::downgrade(&self.inner),
|
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 {
|
2017-11-17 12:51:23 -08:00
|
|
|
let res = 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
|
|
|
}
|
|
|
|
|
|
2016-09-09 02:27:26 +01: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-09-09 02:27:26 +01:00
|
|
|
}
|
|
|
|
|
|
2016-11-11 14:27:49 -08:00
|
|
|
fn poll(&mut self, max_wait: Option<Duration>) -> bool {
|
|
|
|
|
// Block waiting for an event to happen, peeling out how many events
|
|
|
|
|
// happened.
|
2017-11-17 12:51:23 -08:00
|
|
|
match self.inner.io.poll(&mut self.events, max_wait) {
|
|
|
|
|
Ok(_) => {}
|
2016-11-11 14:27:49 -08:00
|
|
|
Err(ref e) if e.kind() == ErrorKind::Interrupted => return false,
|
2017-11-17 12:51:23 -08:00
|
|
|
// TODO: This should return an io::Result instead of panic.
|
2016-11-11 14:27:49 -08:00
|
|
|
Err(e) => panic!("error in poll: {}", e),
|
2017-11-17 12:51:23 -08:00
|
|
|
}
|
2016-11-11 14:27:49 -08:00
|
|
|
|
|
|
|
|
// Process all the events that came in, dispatching appropriately
|
|
|
|
|
let mut fired = false;
|
2016-09-09 02:27:26 +01:00
|
|
|
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());
|
2016-09-09 02:27:26 +01:00
|
|
|
|
2017-11-17 12:51:23 -08:00
|
|
|
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;
|
2016-09-09 02:27:26 +01:00
|
|
|
} else {
|
2017-02-05 17:06:57 -08:00
|
|
|
self.dispatch(token, event.readiness());
|
2016-09-09 02:27:26 +01:00
|
|
|
}
|
2016-08-20 23:23:16 -07:00
|
|
|
}
|
2017-11-17 12:51:23 -08:00
|
|
|
|
2016-11-11 14:27:49 -08:00
|
|
|
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;
|
2017-11-17 12:51:23 -08:00
|
|
|
let io_dispatch = self.inner.io_dispatch.read().unwrap();
|
2016-08-31 00:19:29 -07:00
|
|
|
|
2017-11-17 12:51:23 -08:00
|
|
|
if let Some(io) = io_dispatch.get(token) {
|
2017-12-05 09:47:29 -08:00
|
|
|
io.readiness.fetch_or(ready2usize(ready), Relaxed);
|
2016-08-31 00:19:29 -07:00
|
|
|
if ready.is_writable() {
|
2017-11-17 12:51:23 -08:00
|
|
|
io.writer.notify();
|
2017-05-19 09:56:35 -07:00
|
|
|
}
|
|
|
|
|
if !(ready & (!mio::Ready::writable())).is_empty() {
|
2017-11-17 12:51:23 -08:00
|
|
|
io.reader.notify();
|
2016-09-07 16:11:19 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-05 09:02:07 -08:00
|
|
|
impl fmt::Debug for Reactor {
|
2017-03-06 12:15:29 -08:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2017-12-05 09:02:07 -08:00
|
|
|
write!(f, "Reactor")
|
2017-03-06 12:15:29 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-05 08:40:02 -08:00
|
|
|
impl Drop for Inner {
|
|
|
|
|
fn drop(&mut self) {
|
|
|
|
|
// When a reactor is dropped it needs to wake up all blocked tasks as
|
|
|
|
|
// they'll never receive a notification, and all connected I/O objects
|
|
|
|
|
// will start returning errors pretty quickly.
|
|
|
|
|
let io = self.io_dispatch.read().unwrap();
|
|
|
|
|
for (_, io) in io.iter() {
|
|
|
|
|
io.writer.notify();
|
|
|
|
|
io.reader.notify();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-07 16:11:19 -07:00
|
|
|
impl Inner {
|
2017-11-17 12:51:23 -08:00
|
|
|
/// Register an I/O resource with the reactor.
|
|
|
|
|
///
|
|
|
|
|
/// The registration token is returned.
|
|
|
|
|
fn add_source(&self, source: &Evented)
|
|
|
|
|
-> io::Result<usize>
|
|
|
|
|
{
|
|
|
|
|
// Acquire a write lock
|
|
|
|
|
let key = self.io_dispatch.write().unwrap()
|
|
|
|
|
.insert(ScheduledIo {
|
|
|
|
|
readiness: AtomicUsize::new(0),
|
|
|
|
|
reader: AtomicTask::new(),
|
|
|
|
|
writer: AtomicTask::new(),
|
|
|
|
|
});
|
|
|
|
|
|
2016-08-20 23:23:16 -07:00
|
|
|
try!(self.io.register(source,
|
2017-10-25 10:54:54 -07:00
|
|
|
mio::Token(TOKEN_START + key),
|
2017-02-05 17:06:57 -08:00
|
|
|
mio::Ready::readable() |
|
|
|
|
|
mio::Ready::writable() |
|
2017-05-21 11:01:48 -06:00
|
|
|
platform::all(),
|
2016-08-20 23:23:16 -07:00
|
|
|
mio::PollOpt::edge()));
|
2017-11-17 12:51:23 -08:00
|
|
|
|
|
|
|
|
Ok(key)
|
2016-08-20 23:23:16 -07:00
|
|
|
}
|
2016-11-04 09:12:00 -07:00
|
|
|
|
2017-11-17 12:51:23 -08:00
|
|
|
fn deregister_source(&self, source: &Evented) -> io::Result<()> {
|
2016-11-04 09:12:00 -07:00
|
|
|
self.io.deregister(source)
|
|
|
|
|
}
|
2016-08-20 23:23:16 -07:00
|
|
|
|
2017-11-17 12:51:23 -08:00
|
|
|
fn drop_source(&self, token: usize) {
|
2016-08-20 23:23:16 -07:00
|
|
|
debug!("dropping I/O source: {}", token);
|
2017-11-17 12:51:23 -08:00
|
|
|
self.io_dispatch.write().unwrap().remove(token);
|
2016-08-20 23:23:16 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-17 12:51:23 -08:00
|
|
|
/// Registers interest in the I/O resource associated with `token`.
|
|
|
|
|
fn schedule(&self, token: usize, dir: Direction) {
|
2016-08-20 23:23:16 -07:00
|
|
|
debug!("scheduling direction for: {}", token);
|
2017-11-17 12:51:23 -08:00
|
|
|
let io_dispatch = self.io_dispatch.read().unwrap();
|
|
|
|
|
let sched = io_dispatch.get(token).unwrap();
|
|
|
|
|
|
|
|
|
|
let (task, ready) = match dir {
|
|
|
|
|
Direction::Read => (&sched.reader, !mio::Ready::writable()),
|
|
|
|
|
Direction::Write => (&sched.writer, mio::Ready::writable()),
|
2016-08-20 23:23:16 -07:00
|
|
|
};
|
2017-11-17 12:51:23 -08:00
|
|
|
|
|
|
|
|
task.register();
|
|
|
|
|
|
2017-12-05 09:47:29 -08:00
|
|
|
if sched.readiness.load(SeqCst) & ready2usize(ready) != 0 {
|
2017-11-17 12:51:23 -08:00
|
|
|
task.notify();
|
2016-08-20 23:23:16 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-05 09:47:29 -08:00
|
|
|
static HANDLE_FALLBACK: AtomicUsize = ATOMIC_USIZE_INIT;
|
|
|
|
|
|
|
|
|
|
/// Error returned from `Handle::set_fallback`.
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct SetDefaultError(());
|
|
|
|
|
|
|
|
|
|
impl Handle {
|
|
|
|
|
/// Configures the fallback handle to be returned from `Handle::default`.
|
|
|
|
|
///
|
|
|
|
|
/// The `Handle::default()` function will by default lazily spin up a global
|
|
|
|
|
/// thread and run a reactor on this global thread. This behavior is not
|
|
|
|
|
/// always desirable in all applications, however, and sometimes a different
|
|
|
|
|
/// fallback reactor is desired.
|
|
|
|
|
///
|
|
|
|
|
/// This function will attempt to globally alter the return value of
|
|
|
|
|
/// `Handle::default()` to return the `handle` specified rather than a
|
|
|
|
|
/// lazily initialized global thread. If successful then all future calls to
|
|
|
|
|
/// `Handle::default()` which would otherwise fall back to the global thread
|
|
|
|
|
/// will instead return a clone of the handle specified.
|
|
|
|
|
///
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// This function may not always succeed in configuring the fallback handle.
|
|
|
|
|
/// If this function was previously called (or perhaps concurrently called
|
|
|
|
|
/// on many threads) only the *first* invocation of this function will
|
|
|
|
|
/// succeed. All other invocations will return an error.
|
|
|
|
|
///
|
|
|
|
|
/// Additionally if the global reactor thread has already been initialized
|
|
|
|
|
/// then this function will also return an error. (aka if `Handle::default`
|
|
|
|
|
/// has been called previously in this program).
|
|
|
|
|
pub fn set_fallback(handle: Handle) -> Result<(), SetDefaultError> {
|
|
|
|
|
unsafe {
|
|
|
|
|
let val = handle.into_usize();
|
|
|
|
|
match HANDLE_FALLBACK.compare_exchange(0, val, SeqCst, SeqCst) {
|
|
|
|
|
Ok(_) => Ok(()),
|
|
|
|
|
Err(_) => {
|
|
|
|
|
drop(Handle::from_usize(val));
|
|
|
|
|
Err(SetDefaultError(()))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn into_usize(self) -> usize {
|
|
|
|
|
unsafe {
|
|
|
|
|
mem::transmute::<Weak<Inner>, usize>(self.inner)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsafe fn from_usize(val: usize) -> Handle {
|
|
|
|
|
let inner = mem::transmute::<usize, Weak<Inner>>(val);;
|
|
|
|
|
Handle { inner }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn inner(&self) -> Option<Arc<Inner>> {
|
|
|
|
|
self.inner.upgrade()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for Handle {
|
|
|
|
|
fn default() -> Handle {
|
|
|
|
|
let mut fallback = HANDLE_FALLBACK.load(SeqCst);
|
|
|
|
|
|
|
|
|
|
// If the fallback hasn't been previously initialized then let's spin
|
|
|
|
|
// up a helper thread and try to initialize with that. If we can't
|
|
|
|
|
// actually create a helper thread then we'll just return a "defunkt"
|
|
|
|
|
// handle which will return errors when I/O objects are attempted to be
|
|
|
|
|
// associated.
|
|
|
|
|
if fallback == 0 {
|
|
|
|
|
let helper = match global::HelperThread::new() {
|
|
|
|
|
Ok(helper) => helper,
|
|
|
|
|
Err(_) => return Handle { inner: Weak::new() },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// If we successfully set ourselves as the actual fallback then we
|
|
|
|
|
// want to `forget` the helper thread to ensure that it persists
|
|
|
|
|
// globally. If we fail to set ourselves as the fallback that means
|
|
|
|
|
// that someone was racing with this call to `Handle::default`.
|
|
|
|
|
// They ended up winning so we'll destroy our helper thread (which
|
|
|
|
|
// shuts down the thread) and reload the fallback.
|
|
|
|
|
if Handle::set_fallback(helper.handle().clone()).is_ok() {
|
|
|
|
|
let ret = helper.handle().clone();
|
|
|
|
|
helper.forget();
|
|
|
|
|
return ret
|
|
|
|
|
}
|
|
|
|
|
fallback = HANDLE_FALLBACK.load(SeqCst);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// At this point our fallback handle global was configured so we use
|
|
|
|
|
// its value to reify a handle, clone it, and then forget our reified
|
|
|
|
|
// handle as we don't actually have an owning reference to it.
|
|
|
|
|
assert!(fallback != 0);
|
|
|
|
|
unsafe {
|
|
|
|
|
let handle = Handle::from_usize(fallback);
|
|
|
|
|
let ret = handle.clone();
|
|
|
|
|
drop(handle.into_usize());
|
|
|
|
|
return ret
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-06 12:15:29 -08:00
|
|
|
impl fmt::Debug for Handle {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2017-11-21 20:18:11 +02:00
|
|
|
write!(f, "Handle")
|
2017-03-06 12:15:29 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-31 14:08:26 -07:00
|
|
|
#[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()
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-21 11:01:48 -06:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2017-07-31 14:08:26 -07:00
|
|
|
#[cfg(any(windows, target_os = "fuchsia"))]
|
2017-02-05 17:06:57 -08:00
|
|
|
mod platform {
|
|
|
|
|
use mio::Ready;
|
|
|
|
|
|
2017-05-21 11:01:48 -06:00
|
|
|
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()
|
|
|
|
|
}
|
|
|
|
|
}
|