Re-work I/O

* Auto-register interest whenever we see WouldBlock
* Remove implementations of `Stream<Item=Ready>`, no longer needed
* Add explicit `poll_{read,write}` methods, if needed
* Remove all I/O streams, libstd ones suffice
* Update all I/O futures
This commit is contained in:
Alex Crichton
2016-08-17 18:41:34 -07:00
parent 293d104177
commit d0b911189c
13 changed files with 367 additions and 230 deletions
+46 -25
View File
@@ -1,8 +1,7 @@
use std::io;
use std::sync::atomic::{AtomicUsize, Ordering};
use futures::stream::Stream;
use futures::{Future, Task, Poll};
use futures_io::{Ready};
use futures::{Future, Poll};
use event_loop::{IoSource, LoopHandle, AddSource};
@@ -23,6 +22,7 @@ pub struct ReadinessStream {
io_token: usize,
loop_handle: LoopHandle,
source: IoSource,
readiness: AtomicUsize,
}
pub struct ReadinessStreamNew {
@@ -45,43 +45,64 @@ impl ReadinessStream {
handle: Some(loop_handle),
}
}
/// Tests to see if this source is ready to be read from or not.
pub fn poll_read(&self) -> Poll<(), io::Error> {
if self.readiness.load(Ordering::SeqCst) & 1 != 0 {
return Poll::Ok(())
}
self.readiness.fetch_or(self.source.take_readiness(), Ordering::SeqCst);
if self.readiness.load(Ordering::SeqCst) & 1 != 0 {
Poll::Ok(())
} else {
self.loop_handle.schedule_read(self.io_token);
Poll::NotReady
}
}
/// Tests to see if this source is ready to be written to or not.
pub fn poll_write(&self) -> Poll<(), io::Error> {
if self.readiness.load(Ordering::SeqCst) & 2 != 0 {
return Poll::Ok(())
}
self.readiness.fetch_or(self.source.take_readiness(), Ordering::SeqCst);
if self.readiness.load(Ordering::SeqCst) & 2 != 0 {
Poll::Ok(())
} else {
self.loop_handle.schedule_write(self.io_token);
Poll::NotReady
}
}
/// Tests to see if this source is ready to be read from or not.
pub fn need_read(&self) {
self.readiness.fetch_and(!1, Ordering::SeqCst);
self.loop_handle.schedule_read(self.io_token);
}
/// Tests to see if this source is ready to be written to or not.
pub fn need_write(&self) {
self.readiness.fetch_and(!2, Ordering::SeqCst);
self.loop_handle.schedule_write(self.io_token);
}
}
impl Future for ReadinessStreamNew {
type Item = ReadinessStream;
type Error = io::Error;
fn poll(&mut self, task: &mut Task) -> Poll<ReadinessStream, io::Error> {
self.inner.poll(task).map(|token| {
fn poll(&mut self) -> Poll<ReadinessStream, io::Error> {
self.inner.poll().map(|token| {
ReadinessStream {
io_token: token,
source: self.source.take().unwrap(),
loop_handle: self.handle.take().unwrap(),
readiness: AtomicUsize::new(0),
}
})
}
}
impl Stream for ReadinessStream {
type Item = Ready;
type Error = io::Error;
fn poll(&mut self, task: &mut Task) -> Poll<Option<Ready>, io::Error> {
match self.source.take_readiness() {
None => {
self.loop_handle.schedule(self.io_token, task);
Poll::NotReady
}
Some(r) => {
if !r.is_read() || !r.is_write() {
self.loop_handle.schedule(self.io_token, task);
}
Poll::Ok(Some(r))
}
}
}
}
impl Drop for ReadinessStream {
fn drop(&mut self) {
self.loop_handle.drop_source(self.io_token)