|
|
|
@ -2,7 +2,7 @@ use std::fmt;
|
|
|
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
|
use std::time::Duration;
|
|
|
|
|
|
|
|
|
|
use mio::{self, Evented};
|
|
|
|
|
use mio::{self, event::Source, Interest};
|
|
|
|
|
use slab::Slab;
|
|
|
|
|
|
|
|
|
|
use crate::io;
|
|
|
|
@ -64,25 +64,26 @@ impl Reactor {
|
|
|
|
|
/// Creates a new reactor for polling I/O events.
|
|
|
|
|
pub fn new() -> io::Result<Reactor> {
|
|
|
|
|
let poller = mio::Poll::new()?;
|
|
|
|
|
let notify_reg = mio::Registration::new2();
|
|
|
|
|
|
|
|
|
|
let mut reactor = Reactor {
|
|
|
|
|
poller,
|
|
|
|
|
events: Mutex::new(mio::Events::with_capacity(1000)),
|
|
|
|
|
entries: Mutex::new(Slab::new()),
|
|
|
|
|
notify_reg,
|
|
|
|
|
notify_token: mio::Token(0),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Register a dummy I/O handle for waking up the polling thread.
|
|
|
|
|
let entry = reactor.register(&reactor.notify_reg.0)?;
|
|
|
|
|
reactor.notify_token = entry.token;
|
|
|
|
|
|
|
|
|
|
Ok(reactor)
|
|
|
|
|
todo!();
|
|
|
|
|
// let notify_reg = mio::Registration::new2();
|
|
|
|
|
|
|
|
|
|
// let mut reactor = Reactor {
|
|
|
|
|
// poller,
|
|
|
|
|
// events: Mutex::new(mio::Events::with_capacity(1000)),
|
|
|
|
|
// entries: Mutex::new(Slab::new()),
|
|
|
|
|
// notify_reg,
|
|
|
|
|
// notify_token: mio::Token(0),
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// // Register a dummy I/O handle for waking up the polling thread.
|
|
|
|
|
// let entry = reactor.register(&reactor.notify_reg.0)?;
|
|
|
|
|
// reactor.notify_token = entry.token;
|
|
|
|
|
|
|
|
|
|
// Ok(reactor)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Registers an I/O event source and returns its associated entry.
|
|
|
|
|
fn register(&self, source: &dyn Evented) -> io::Result<Arc<Entry>> {
|
|
|
|
|
fn register(&self, source: &mut dyn Source) -> io::Result<Arc<Entry>> {
|
|
|
|
|
let mut entries = self.entries.lock().unwrap();
|
|
|
|
|
|
|
|
|
|
// Reserve a vacant spot in the slab and use its key as the token value.
|
|
|
|
@ -104,17 +105,17 @@ impl Reactor {
|
|
|
|
|
vacant.insert(entry.clone());
|
|
|
|
|
|
|
|
|
|
// Register the I/O event source in the poller.
|
|
|
|
|
let interest = mio::Ready::all();
|
|
|
|
|
let opts = mio::PollOpt::edge();
|
|
|
|
|
self.poller.register(source, token, interest, opts)?;
|
|
|
|
|
// TODO: ADD AIO and LIO?
|
|
|
|
|
const interest: Interest = Interest::READABLE.add(Interest::WRITABLE);
|
|
|
|
|
self.poller.registry().register(source, token, interest)?;
|
|
|
|
|
|
|
|
|
|
Ok(entry)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Deregisters an I/O event source associated with an entry.
|
|
|
|
|
fn deregister(&self, source: &dyn Evented, entry: &Entry) -> io::Result<()> {
|
|
|
|
|
fn deregister(&self, source: &mut dyn Source, entry: &Entry) -> io::Result<()> {
|
|
|
|
|
// Deregister the I/O object from the mio instance.
|
|
|
|
|
self.poller.deregister(source)?;
|
|
|
|
|
self.poller.registry().deregister(source)?;
|
|
|
|
|
|
|
|
|
|
// Remove the entry associated with the I/O object.
|
|
|
|
|
self.entries.lock().unwrap().remove(entry.token.0);
|
|
|
|
@ -124,7 +125,8 @@ impl Reactor {
|
|
|
|
|
|
|
|
|
|
/// Notifies the reactor so that polling stops blocking.
|
|
|
|
|
pub fn notify(&self) -> io::Result<()> {
|
|
|
|
|
self.notify_reg.1.set_readiness(mio::Ready::readable())
|
|
|
|
|
todo!()
|
|
|
|
|
// self.notify_reg.1.set_readiness(mio::Ready::readable())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Waits on the poller for new events and wakes up tasks blocked on I/O handles.
|
|
|
|
@ -147,16 +149,13 @@ impl Reactor {
|
|
|
|
|
|
|
|
|
|
if token == self.notify_token {
|
|
|
|
|
// If this is the notification token, we just need the notification state.
|
|
|
|
|
self.notify_reg.1.set_readiness(mio::Ready::empty())?;
|
|
|
|
|
todo!()
|
|
|
|
|
// self.notify_reg.1.set_readiness(mio::Ready::empty())?;
|
|
|
|
|
} else {
|
|
|
|
|
// Otherwise, look for the entry associated with this token.
|
|
|
|
|
if let Some(entry) = entries.get(token.0) {
|
|
|
|
|
// Set the readiness flags from this I/O event.
|
|
|
|
|
let readiness = event.readiness();
|
|
|
|
|
|
|
|
|
|
// Wake up reader tasks blocked on this I/O handle.
|
|
|
|
|
let reader_interests = mio::Ready::all() - mio::Ready::writable();
|
|
|
|
|
if !(readiness & reader_interests).is_empty() {
|
|
|
|
|
if event.is_readable() {
|
|
|
|
|
let mut readers = entry.readers.lock().unwrap();
|
|
|
|
|
readers.ready = true;
|
|
|
|
|
for w in readers.wakers.drain(..) {
|
|
|
|
@ -166,8 +165,7 @@ impl Reactor {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Wake up writer tasks blocked on this I/O handle.
|
|
|
|
|
let writer_interests = mio::Ready::all() - mio::Ready::readable();
|
|
|
|
|
if !(readiness & writer_interests).is_empty() {
|
|
|
|
|
if event.is_writable() {
|
|
|
|
|
let mut writers = entry.writers.lock().unwrap();
|
|
|
|
|
writers.ready = true;
|
|
|
|
|
for w in writers.wakers.drain(..) {
|
|
|
|
@ -187,7 +185,7 @@ impl Reactor {
|
|
|
|
|
///
|
|
|
|
|
/// This handle wraps an I/O event source and exposes a "futurized" interface on top of it,
|
|
|
|
|
/// implementing traits `AsyncRead` and `AsyncWrite`.
|
|
|
|
|
pub struct Watcher<T: Evented> {
|
|
|
|
|
pub struct Watcher<T: Source> {
|
|
|
|
|
/// Data associated with the I/O handle.
|
|
|
|
|
entry: Arc<Entry>,
|
|
|
|
|
|
|
|
|
@ -195,7 +193,7 @@ pub struct Watcher<T: Evented> {
|
|
|
|
|
source: Option<T>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: Evented> Watcher<T> {
|
|
|
|
|
impl<T: Source> Watcher<T> {
|
|
|
|
|
/// Creates a new I/O handle.
|
|
|
|
|
///
|
|
|
|
|
/// The provided I/O event source will be kept registered inside the reactor's poller for the
|
|
|
|
@ -204,7 +202,7 @@ impl<T: Evented> Watcher<T> {
|
|
|
|
|
Watcher {
|
|
|
|
|
entry: RUNTIME
|
|
|
|
|
.reactor()
|
|
|
|
|
.register(&source)
|
|
|
|
|
.register(&mut source)
|
|
|
|
|
.expect("cannot register an I/O event source"),
|
|
|
|
|
source: Some(source),
|
|
|
|
|
}
|
|
|
|
@ -327,15 +325,15 @@ impl<T: Evented> Watcher<T> {
|
|
|
|
|
let source = self.source.take().unwrap();
|
|
|
|
|
RUNTIME
|
|
|
|
|
.reactor()
|
|
|
|
|
.deregister(&source, &self.entry)
|
|
|
|
|
.deregister(&mut source, &self.entry)
|
|
|
|
|
.expect("cannot deregister I/O event source");
|
|
|
|
|
source
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: Evented> Drop for Watcher<T> {
|
|
|
|
|
impl<T: Source> Drop for Watcher<T> {
|
|
|
|
|
fn drop(&mut self) {
|
|
|
|
|
if let Some(ref source) = self.source {
|
|
|
|
|
if let Some(ref mut source) = self.source {
|
|
|
|
|
RUNTIME
|
|
|
|
|
.reactor()
|
|
|
|
|
.deregister(source, &self.entry)
|
|
|
|
@ -344,7 +342,7 @@ impl<T: Evented> Drop for Watcher<T> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: Evented + fmt::Debug> fmt::Debug for Watcher<T> {
|
|
|
|
|
impl<T: Source + fmt::Debug> fmt::Debug for Watcher<T> {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
|
f.debug_struct("Watcher")
|
|
|
|
|
.field("entry", &self.entry)
|
|
|
|
|