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:
parent
431dcdc840
commit
fa94fdad3e
@ -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 }
|
||||
}
|
||||
|
||||
|
@ -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!() }
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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 {
|
||||
}
|
@ -74,7 +74,6 @@ use std::str;
|
||||
|
||||
pub use task::NativeTaskBuilder;
|
||||
|
||||
pub mod io;
|
||||
pub mod task;
|
||||
|
||||
#[cfg(any(windows, android))]
|
||||
|
@ -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)]
|
||||
|
@ -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
|
||||
|
@ -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>;
|
||||
|
@ -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`.
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user