Runtime removal: fully remove rtio

This patch cleans up the remnants of the runtime IO interface.

Because this eliminates APIs in `libnative` and `librustrt`, it is a:

[breaking-change]

This functionality is likely to be available publicly, in some form,
from `std` in the future.
This commit is contained in:
Aaron Turon 2014-10-17 13:39:27 -07:00
parent 431dcdc840
commit fa94fdad3e
11 changed files with 11 additions and 276 deletions

View file

@ -18,7 +18,7 @@
use alloc::arc::Arc;
use std::sync::atomic;
use std::mem;
use std::rt::rtio::{EventLoop, IoFactory, RemoteCallback};
use std::rt::rtio::{EventLoop, RemoteCallback};
use std::rt::rtio::{PausableIdleCallback, Callback};
use std::rt::exclusive::Exclusive;
@ -150,8 +150,6 @@ impl EventLoop for BasicLoop {
Box<RemoteCallback + Send>
}
fn io<'a>(&'a mut self) -> Option<&'a mut IoFactory> { None }
fn has_active_io(&self) -> bool { false }
}

View file

@ -16,7 +16,6 @@ use std::mem;
use std::rt::Runtime;
use std::rt::local::Local;
use std::rt::mutex::NativeMutex;
use std::rt::rtio;
use std::rt::task::{Task, BlockedTask, TaskOpts};
struct SimpleTask {
@ -79,9 +78,10 @@ impl Runtime for SimpleTask {
_f: proc():Send) {
panic!()
}
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>> { None }
fn stack_bounds(&self) -> (uint, uint) { panic!() }
fn stack_guard(&self) -> Option<uint> { panic!() }
fn can_block(&self) -> bool { true }
fn wrap(self: Box<SimpleTask>) -> Box<Any+'static> { panic!() }
}

View file

@ -24,7 +24,6 @@ use std::raw;
use std::rt::Runtime;
use std::rt::local::Local;
use std::rt::mutex::NativeMutex;
use std::rt::rtio;
use std::rt::stack;
use std::rt::task::{Task, BlockedTask, TaskOpts};
use std::rt;
@ -468,14 +467,6 @@ impl Runtime for GreenTask {
sched.run_task(me, sibling)
}
// Local I/O is provided by the scheduler's event loop
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>> {
match self.sched.as_mut().unwrap().event_loop.io() {
Some(io) => Some(rtio::LocalIo::new(io)),
None => None,
}
}
fn stack_bounds(&self) -> (uint, uint) {
let c = self.coroutine.as_ref()
.expect("GreenTask.stack_bounds called without a coroutine");

View file

@ -1,102 +0,0 @@
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Native thread-blocking I/O implementation
//!
//! This module contains the implementation of native thread-blocking
//! implementations of I/O on all platforms. This module is not intended to be
//! used directly, but rather the rust runtime will fall back to using it if
//! necessary.
//!
//! Rust code normally runs inside of green tasks with a local scheduler using
//! asynchronous I/O to cooperate among tasks. This model is not always
//! available, however, and that's where these native implementations come into
//! play. The only dependencies of these modules are the normal system libraries
//! that you would find on the respective platform.
#![allow(non_snake_case)]
use libc::{mod, c_int};
use std::c_str::CString;
use std::os;
use std::rt::rtio::{mod, IoResult, IoError};
use std::num;
#[cfg(windows)]
#[path = "tty_windows.rs"]
mod tty;
fn unimpl() -> IoError {
#[cfg(unix)] use libc::ENOSYS as ERROR;
#[cfg(windows)] use libc::ERROR_CALL_NOT_IMPLEMENTED as ERROR;
IoError {
code: ERROR as uint,
extra: 0,
detail: Some("not yet supported by the `native` runtime, maybe try `green`.".to_string()),
}
}
fn last_error() -> IoError {
let errno = os::errno() as uint;
IoError {
code: os::errno() as uint,
extra: 0,
detail: Some(os::error_string(errno)),
}
}
#[cfg(windows)]
#[inline]
fn retry<I> (f: || -> I) -> I { f() } // PR rust-lang/rust/#17020
#[cfg(unix)]
#[inline]
fn retry<I: PartialEq + num::One + Neg<I>> (f: || -> I) -> I {
let minus_one = -num::one::<I>();
loop {
let n = f();
if n == minus_one && os::errno() == libc::EINTR as int { }
else { return n }
}
}
fn keep_going(data: &[u8], f: |*const u8, uint| -> i64) -> i64 {
let origamt = data.len();
let mut data = data.as_ptr();
let mut amt = origamt;
while amt > 0 {
let ret = retry(|| f(data, amt));
if ret == 0 {
break
} else if ret != -1 {
amt -= ret as uint;
data = unsafe { data.offset(ret as int) };
} else {
return ret;
}
}
return (origamt - amt) as i64;
}
/// Implementation of rt::rtio's IoFactory trait to generate handles to the
/// native I/O functionality.
pub struct IoFactory {
_cannot_construct_outside_of_this_module: ()
}
impl IoFactory {
pub fn new() -> IoFactory {
IoFactory { _cannot_construct_outside_of_this_module: () }
}
}
impl rtio::IoFactory for IoFactory {
}

View file

@ -74,7 +74,6 @@ use std::str;
pub use task::NativeTaskBuilder;
pub mod io;
pub mod task;
#[cfg(any(windows, android))]

View file

@ -19,13 +19,11 @@ use std::mem;
use std::rt::bookkeeping;
use std::rt::local::Local;
use std::rt::mutex::NativeMutex;
use std::rt::rtio;
use std::rt::stack;
use std::rt::task::{Task, BlockedTask, TaskOpts};
use std::rt::thread::Thread;
use std::rt;
use io;
use std::task::{TaskBuilder, Spawner};
/// Creates a new Task which is ready to execute as a 1:1 task.
@ -42,7 +40,6 @@ fn ops() -> Box<Ops> {
box Ops {
lock: unsafe { NativeMutex::new() },
awoken: false,
io: io::IoFactory::new(),
// these *should* get overwritten
stack_bounds: (0, 0),
stack_guard: 0
@ -112,7 +109,6 @@ impl<S: Spawner> NativeTaskBuilder for TaskBuilder<S> {
struct Ops {
lock: NativeMutex, // native synchronization
awoken: bool, // used to prevent spurious wakeups
io: io::IoFactory, // local I/O factory
// This field holds the known bounds of the stack in (lo, hi) form. Not all
// native tasks necessarily know their precise bounds, hence this is
@ -272,10 +268,6 @@ impl rt::Runtime for Ops {
NativeSpawner.spawn(opts, f);
}
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>> {
Some(rtio::LocalIo::new(&mut self.io as &mut rtio::IoFactory))
}
}
#[cfg(test)]

View file

@ -90,7 +90,6 @@ pub trait Runtime {
cur_task: Box<Task>,
opts: TaskOpts,
f: proc():Send);
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>>;
/// The (low, high) edges of the current stack.
fn stack_bounds(&self) -> (uint, uint); // (lo, hi)
/// The last writable byte of the stack next to the guard page

View file

@ -12,12 +12,6 @@
use core::prelude::*;
use alloc::boxed::Box;
use collections::string::String;
use core::mem;
use libc::c_int;
use local::Local;
use task::Task;
pub trait EventLoop {
fn run(&mut self);
@ -27,8 +21,7 @@ pub trait EventLoop {
fn remote_callback(&mut self, Box<Callback + Send>)
-> Box<RemoteCallback + Send>;
/// The asynchronous I/O services. Not all event loops may provide one.
fn io<'a>(&'a mut self) -> Option<&'a mut IoFactory>;
// last vestige of IoFactory
fn has_active_io(&self) -> bool;
}
@ -46,128 +39,7 @@ pub trait RemoteCallback {
fn fire(&mut self);
}
pub struct LocalIo<'a> {
factory: &'a mut IoFactory+'a,
}
#[unsafe_destructor]
impl<'a> Drop for LocalIo<'a> {
fn drop(&mut self) {
// FIXME(pcwalton): Do nothing here for now, but eventually we may want
// something. For now this serves to make `LocalIo` noncopyable.
}
}
impl<'a> LocalIo<'a> {
/// Returns the local I/O: either the local scheduler's I/O services or
/// the native I/O services.
pub fn borrow() -> Option<LocalIo<'a>> {
// FIXME(#11053): bad
//
// This is currently very unsafely implemented. We don't actually
// *take* the local I/O so there's a very real possibility that we
// can have two borrows at once. Currently there is not a clear way
// to actually borrow the local I/O factory safely because even if
// ownership were transferred down to the functions that the I/O
// factory implements it's just too much of a pain to know when to
// relinquish ownership back into the local task (but that would be
// the safe way of implementing this function).
//
// In order to get around this, we just transmute a copy out of the task
// in order to have what is likely a static lifetime (bad).
let mut t: Box<Task> = match Local::try_take() {
Some(t) => t,
None => return None,
};
let ret = t.local_io().map(|t| {
unsafe { mem::transmute_copy(&t) }
});
Local::put(t);
return ret;
}
pub fn maybe_raise<T>(f: |io: &mut IoFactory| -> IoResult<T>)
-> IoResult<T>
{
#[cfg(unix)] use libc::EINVAL as ERROR;
#[cfg(windows)] use libc::ERROR_CALL_NOT_IMPLEMENTED as ERROR;
match LocalIo::borrow() {
Some(mut io) => f(io.get()),
None => Err(IoError {
code: ERROR as uint,
extra: 0,
detail: None,
}),
}
}
pub fn new<'a>(io: &'a mut IoFactory+'a) -> LocalIo<'a> {
LocalIo { factory: io }
}
/// Returns the underlying I/O factory as a trait reference.
#[inline]
pub fn get<'a>(&'a mut self) -> &'a mut IoFactory {
let f: &'a mut IoFactory = self.factory;
f
}
}
pub trait IoFactory {
fn timer_init(&mut self) -> IoResult<Box<RtioTimer + Send>>;
fn tty_open(&mut self, fd: c_int, readable: bool)
-> IoResult<Box<RtioTTY + Send>>;
}
pub trait RtioTimer {
fn sleep(&mut self, msecs: u64);
fn oneshot(&mut self, msecs: u64, cb: Box<Callback + Send>);
fn period(&mut self, msecs: u64, cb: Box<Callback + Send>);
}
pub trait RtioPipe {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint>;
fn write(&mut self, buf: &[u8]) -> IoResult<()>;
fn clone(&self) -> Box<RtioPipe + Send>;
fn close_write(&mut self) -> IoResult<()>;
fn close_read(&mut self) -> IoResult<()>;
fn set_timeout(&mut self, timeout_ms: Option<u64>);
fn set_read_timeout(&mut self, timeout_ms: Option<u64>);
fn set_write_timeout(&mut self, timeout_ms: Option<u64>);
}
pub trait RtioUnixListener {
fn listen(self: Box<Self>) -> IoResult<Box<RtioUnixAcceptor + Send>>;
}
pub trait RtioUnixAcceptor {
fn accept(&mut self) -> IoResult<Box<RtioPipe + Send>>;
fn set_timeout(&mut self, timeout: Option<u64>);
fn clone(&self) -> Box<RtioUnixAcceptor + Send>;
fn close_accept(&mut self) -> IoResult<()>;
}
pub trait RtioTTY {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint>;
fn write(&mut self, buf: &[u8]) -> IoResult<()>;
fn set_raw(&mut self, raw: bool) -> IoResult<()>;
fn get_winsize(&mut self) -> IoResult<(int, int)>;
fn isatty(&self) -> bool;
}
pub trait PausableIdleCallback {
fn pause(&mut self);
fn resume(&mut self);
}
pub trait RtioSignal {}
#[deriving(Show)]
pub struct IoError {
pub code: uint,
pub extra: uint,
pub detail: Option<String>,
}
pub type IoResult<T> = Result<T, IoError>;

View file

@ -26,7 +26,6 @@ use core::raw;
use local_data;
use Runtime;
use local::Local;
use rtio::LocalIo;
use unwind;
use unwind::Unwinder;
use collections::str::SendStr;
@ -421,13 +420,6 @@ impl Task {
ops.maybe_yield(self);
}
/// Acquires a handle to the I/O factory that this task contains, normally
/// stored in the task's runtime. This factory may not always be available,
/// which is why the return type is `Option`
pub fn local_io<'a>(&'a mut self) -> Option<LocalIo<'a>> {
self.imp.as_mut().unwrap().local_io()
}
/// Returns the stack bounds for this task in (lo, hi) format. The stack
/// bounds may not be known for all tasks, so the return value may be
/// `None`.

View file

@ -228,15 +228,15 @@ use error::{FromError, Error};
use fmt;
use int;
use iter::Iterator;
use libc;
use mem::transmute;
use ops::{BitOr, BitXor, BitAnd, Sub, Not};
use option::{Option, Some, None};
use os;
use boxed::Box;
use result::{Ok, Err, Result};
use rt::rtio;
use sys;
use slice::{AsSlice, SlicePrelude};
use str::{Str, StrPrelude};
use str;
use string::String;
use uint;
@ -328,17 +328,6 @@ impl IoError {
pub fn last_error() -> IoError {
IoError::from_errno(os::errno() as uint, true)
}
fn from_rtio_error(err: rtio::IoError) -> IoError {
let rtio::IoError { code, extra, detail } = err;
let mut ioerr = IoError::from_errno(code, false);
ioerr.detail = detail;
ioerr.kind = match ioerr.kind {
TimedOut if extra > 0 => ShortWrite(extra),
k => k,
};
return ioerr;
}
}
impl fmt::Show for IoError {

View file

@ -9,6 +9,11 @@
// except according to those terms.
#![allow(missing_doc)]
#![allow(non_camel_case_types)]
#![allow(unused_imports)]
#![allow(dead_code)]
#![allow(unused_unsafe)]
#![allow(unused_mut)]
extern crate libc;