Files
tokio/src/io/task.rs
T
Alex Crichton 330ab823b0 Update to futures master
* Remove `LoopData` as it's no longer necessary
* Add `LoopHandle::spawn` to spawn new futures onto an event loop
* Add `LoopData::spawn` to also spawn new futures onto an event loop
* Rejigger the implementation of the event loop a bit (make a slab of futures),
  but otherwise everything else is pretty constant.
2016-08-31 19:00:42 -07:00

103 lines
3.1 KiB
Rust

use std::cell::RefCell;
use std::io::{self, Read, Write};
use futures::task::TaskRc;
/// Abstraction that allows inserting an I/O object into task-local storage,
/// returning a handle that can be split.
///
/// A `TaskIo<T>` handle implements the `ReadTask` and `WriteTask` and will only
/// work with the same task that the associated object was inserted into. The
/// handle may then be optionally `split` into the read/write halves so they can
/// be worked with independently.
///
/// Note that it is important that the future returned from `TaskIo::new`, when
/// polled, will pin the yielded `TaskIo<T>` object to that specific task. Any
/// attempt to read or write the object on other tasks will result in a panic.
pub struct TaskIo<T> {
handle: TaskRc<RefCell<T>>,
}
/// The readable half of a `TaskIo<T>` instance returned from `TaskIo::split`.
///
/// This handle implements the `ReadTask` trait and can be used to split up an
/// I/O object into two distinct halves.
pub struct TaskIoRead<T> {
handle: TaskRc<RefCell<T>>,
}
/// The writable half of a `TaskIo<T>` instance returned from `TaskIo::split`.
///
/// This handle implements the `WriteTask` trait and can be used to split up an
/// I/O object into two distinct halves.
pub struct TaskIoWrite<T> {
handle: TaskRc<RefCell<T>>,
}
impl<T> TaskIo<T> {
/// Returns a new future which represents the insertion of the I/O object
/// `T` into task local storage, returning a `TaskIo<T>` handle to it.
///
/// The returned future will never resolve to an error.
pub fn new(t: T) -> TaskIo<T> {
TaskIo {
handle: TaskRc::new(RefCell::new(t)),
}
}
}
impl<T> TaskIo<T>
where T: Read + Write,
{
/// For an I/O object which is both readable and writable, this method can
/// be used to split the handle into two independently owned halves.
///
/// The returned pair implements the `ReadTask` and `WriteTask` traits,
/// respectively, and can be used to pass around the object to different
/// combinators if necessary.
pub fn split(self) -> (TaskIoRead<T>, TaskIoWrite<T>) {
(TaskIoRead { handle: self.handle.clone() },
TaskIoWrite { handle: self.handle })
}
}
impl<T> Read for TaskIo<T>
where T: io::Read,
{
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.handle.with(|t| t.borrow_mut().read(buf))
}
}
impl<T> Write for TaskIo<T>
where T: io::Write,
{
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.handle.with(|t| t.borrow_mut().write(buf))
}
fn flush(&mut self) -> io::Result<()> {
self.handle.with(|t| t.borrow_mut().flush())
}
}
impl<T> Read for TaskIoRead<T>
where T: io::Read,
{
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.handle.with(|t| t.borrow_mut().read(buf))
}
}
impl<T> Write for TaskIoWrite<T>
where T: io::Write,
{
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.handle.with(|t| t.borrow_mut().write(buf))
}
fn flush(&mut self) -> io::Result<()> {
self.handle.with(|t| t.borrow_mut().flush())
}
}