forked from M-Labs/artiq
1
0
Fork 0

ksupport: avoid allocations on I/O error paths.

Fixes #715.
This commit is contained in:
whitequark 2017-04-21 17:20:50 +00:00
parent b913d1d6f2
commit a820ae98cf
4 changed files with 21 additions and 20 deletions

View File

@ -9,3 +9,4 @@ path = "lib.rs"
[features] [features]
alloc = [] alloc = []
io_error_alloc = []

View File

@ -8,8 +8,8 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#[cfg(feature="alloc")] use alloc::boxed::Box; #[cfg(feature="io_error_alloc")] use alloc::boxed::Box;
#[cfg(not(feature="alloc"))] use ::FakeBox as Box; #[cfg(not(feature="io_error_alloc"))] use ::FakeBox as Box;
use core::convert::Into; use core::convert::Into;
use core::fmt; use core::fmt;
use core::marker::{Send, Sync}; use core::marker::{Send, Sync};
@ -63,18 +63,18 @@ pub struct Error {
enum Repr { enum Repr {
Os(i32), Os(i32),
#[cfg(feature="alloc")] #[cfg(feature="io_error_alloc")]
Custom(Box<Custom>), Custom(Box<Custom>),
#[cfg(not(feature="alloc"))] #[cfg(not(feature="io_error_alloc"))]
Custom(Custom), Custom(Custom),
} }
#[derive(Debug)] #[derive(Debug)]
struct Custom { struct Custom {
kind: ErrorKind, kind: ErrorKind,
#[cfg(feature="alloc")] #[cfg(feature="io_error_alloc")]
error: Box<error::Error+Send+Sync>, error: Box<error::Error+Send+Sync>,
#[cfg(not(feature="alloc"))] #[cfg(not(feature="io_error_alloc"))]
error: &'static str error: &'static str
} }
@ -169,21 +169,21 @@ impl Error {
/// // errors can also be created from other errors /// // errors can also be created from other errors
/// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
/// ``` /// ```
#[cfg(feature="alloc")] #[cfg(feature="io_error_alloc")]
pub fn new<E>(kind: ErrorKind, error: E) -> Error pub fn new<E>(kind: ErrorKind, error: E) -> Error
where E: Into<Box<error::Error+Send+Sync>> where E: Into<Box<error::Error+Send+Sync>>
{ {
Self::_new(kind, error.into()) Self::_new(kind, error.into())
} }
#[cfg(not(feature="alloc"))] #[cfg(not(feature="io_error_alloc"))]
pub fn new<E>(kind: ErrorKind, error: E) -> Error pub fn new<E>(kind: ErrorKind, error: E) -> Error
where E: Into<&'static str> where E: Into<&'static str>
{ {
Self::_new(kind, error.into()) Self::_new(kind, error.into())
} }
#[cfg(feature="alloc")] #[cfg(feature="io_error_alloc")]
fn _new(kind: ErrorKind, error: Box<error::Error+Send+Sync>) -> Error { fn _new(kind: ErrorKind, error: Box<error::Error+Send+Sync>) -> Error {
Error { Error {
repr: Repr::Custom(Box::new(Custom { repr: Repr::Custom(Box::new(Custom {
@ -193,7 +193,7 @@ impl Error {
} }
} }
#[cfg(not(feature="alloc"))] #[cfg(not(feature="io_error_alloc"))]
fn _new(kind: ErrorKind, error: &'static str) -> Error { fn _new(kind: ErrorKind, error: &'static str) -> Error {
Error { Error {
repr: Repr::Custom(Box::new(Custom { repr: Repr::Custom(Box::new(Custom {
@ -224,7 +224,7 @@ impl Error {
/// ///
/// If this `Error` was constructed via `new` then this function will /// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`. /// return `Some`, otherwise it will return `None`.
#[cfg(feature="alloc")] #[cfg(feature="io_error_alloc")]
pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> { pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
@ -237,7 +237,7 @@ impl Error {
/// ///
/// If this `Error` was constructed via `new` then this function will /// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`. /// return `Some`, otherwise it will return `None`.
#[cfg(feature="alloc")] #[cfg(feature="io_error_alloc")]
pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> { pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
@ -249,7 +249,7 @@ impl Error {
/// ///
/// If this `Error` was constructed via `new` then this function will /// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`. /// return `Some`, otherwise it will return `None`.
#[cfg(feature="alloc")] #[cfg(feature="io_error_alloc")]
pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> { pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
@ -312,9 +312,9 @@ impl error::Error for Error {
ErrorKind::__Nonexhaustive => unreachable!() ErrorKind::__Nonexhaustive => unreachable!()
}, },
Repr::Custom(ref c) => { Repr::Custom(ref c) => {
#[cfg(feature="alloc")] #[cfg(feature="io_error_alloc")]
{ c.error.description() } { c.error.description() }
#[cfg(not(feature="alloc"))] #[cfg(not(feature="io_error_alloc"))]
{ c.error } { c.error }
}, },
} }
@ -324,9 +324,9 @@ impl error::Error for Error {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
Repr::Custom(ref _c) => { Repr::Custom(ref _c) => {
#[cfg(feature="alloc")] #[cfg(feature="io_error_alloc")]
{ _c.error.cause() } { _c.error.cause() }
#[cfg(not(feature="alloc"))] #[cfg(not(feature="io_error_alloc"))]
{ None } { None }
} }
} }

View File

@ -31,9 +31,9 @@ pub mod error;
pub mod io; pub mod io;
// Provide Box::new wrapper // Provide Box::new wrapper
#[cfg(not(feature="alloc"))] #[cfg(any(not(feature="alloc"), not(feature="io_error_alloc")))]
struct FakeBox<T>(core::marker::PhantomData<T>); struct FakeBox<T>(core::marker::PhantomData<T>);
#[cfg(not(feature="alloc"))] #[cfg(any(not(feature="alloc"), not(feature="io_error_alloc")))]
impl<T> FakeBox<T> { impl<T> FakeBox<T> {
fn new(val: T) -> T { fn new(val: T) -> T {
val val

View File

@ -18,7 +18,7 @@ cslice = { version = "0.3" }
log = { version = "0.3", default-features = false } log = { version = "0.3", default-features = false }
fringe = { version = "= 1.1.0", default-features = false, features = ["alloc"] } fringe = { version = "= 1.1.0", default-features = false, features = ["alloc"] }
alloc_artiq = { path = "../liballoc_artiq" } alloc_artiq = { path = "../liballoc_artiq" }
std_artiq = { path = "../libstd_artiq", features = ["alloc"] } std_artiq = { path = "../libstd_artiq", features = ["alloc", "io_error_alloc"] }
logger_artiq = { path = "../liblogger_artiq" } logger_artiq = { path = "../liblogger_artiq" }
board = { path = "../libboard", features = ["uart_console"] } board = { path = "../libboard", features = ["uart_console"] }
proto = { path = "../libproto", features = ["log"] } proto = { path = "../libproto", features = ["log"] }