<commit_before>use futures::{Future, Async, Poll};
use super::cpu_relax;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::cell::UnsafeCell;
use std::ops::{Deref, DerefMut};

#[derive(Clone)]
pub struct RwLock<T: ?Sized> {
    inner: Arc<RwLockInner<T>>
}

struct RwLockInner<T: ?Sized> {
    raw: RwLockRaw,
    data: UnsafeCell<T>
}

struct RwLockRaw {
    state: AtomicUsize
}

#[derive(Clone)]
pub struct AsyncRwLockReadGuard<T: ?Sized> {
    lock: Arc<RwLockInner<T>>
}

#[derive(Clone)]
pub struct AsyncRwLockWriteGuard<T: ?Sized> {
    lock: Arc<RwLockInner<T>>
}

#[derive(Clone)]
pub struct RwLockReadGuard<T: ?Sized> {
    lock: Arc<RwLockInner<T>>
}

#[derive(Clone)]
pub struct RwLockWriteGuard<T: ?Sized> {
    lock: Arc<RwLockInner<T>>
}

unsafe impl<T: Send> Send for RwLock<T> {}
unsafe impl<T: Send> Sync for RwLock<T> {}

unsafe impl<T: Send> Send for RwLockInner<T> {}
unsafe impl<T: Send> Sync for RwLockInner<T> {}

impl <T: ?Sized> Future for AsyncRwLockReadGuard<T> {
    type Item = RwLockReadGuard<T>;
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if self.lock.raw.try_read() {
            Ok(Async::Ready(RwLockReadGuard {
                lock: self.lock.clone()
            }))
        } else {
            Ok(Async::NotReady)
        }
    }
}

impl <T> Future for AsyncRwLockWriteGuard<T> {
    type Item = RwLockWriteGuard<T>;
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if self.lock.raw.try_write() {
            Ok(Async::Ready(RwLockWriteGuard {
                lock: self.lock.clone()
            }))
        } else {
            Ok(Async::NotReady)
        }
    }
}

impl <T> RwLock <T> {
    pub fn new(val: T) -> RwLock<T> {
        RwLock {
            inner: RwLockInner::new(val)
        }
    }
    pub fn read_async(&self) -> AsyncRwLockReadGuard<T> {
        AsyncRwLockReadGuard {
            lock: self.inner.clone()
        }
    }
    pub fn write_async(&self) -> AsyncRwLockWriteGuard<T> {
        AsyncRwLockWriteGuard {
            lock: self.inner.clone()
        }
    }
    pub fn read(&self) -> RwLockReadGuard<T> {
        while !self.inner.raw.try_read() {
            cpu_relax()
        }
        RwLockReadGuard {
            lock: self.inner.clone()
        }
    }
    pub fn write(&self) -> RwLockWriteGuard<T> {
        while !self.inner.raw.try_write() {
            cpu_relax()
        }
        RwLockWriteGuard {
            lock: self.inner.clone()
        }
    }
}

impl <T> RwLockInner<T> {
    pub fn new(val: T) -> Arc<RwLockInner<T>> {
        Arc::new(RwLockInner {
            raw: RwLockRaw::new(),
            data: UnsafeCell::new(val)
        })
    }
}

impl RwLockRaw {
    fn new() -> RwLockRaw {
        RwLockRaw {
          state: AtomicUsize::new(0)
        }
    }
    fn try_read(&self) -> bool  {
        let lc = self.state.load(Ordering::Relaxed);
        if lc == 1 {
            // write locked
            return false;
        } else {
            let next_count = if lc == 0 { 2 } else { lc + 1 };
            return self.state.compare_and_swap(lc, next_count, Ordering::Relaxed) == lc;
        }
    }
    fn try_write(&self) -> bool {
        self.state.compare_and_swap(0, 1, Ordering::Relaxed) == 0
    }
    fn unlock_read(&self) {
        loop {
            let lc = self.state.load(Ordering::Relaxed);
            let next_count = if lc == 2 { 0 } else { lc - 1 };
            assert!(lc > 1);
            if self.state.compare_and_swap(lc, next_count, Ordering::Relaxed) == lc {
                return;
            } else {
                cpu_relax();
            }
        }
    }
    fn unlock_write(&self) {
        assert_eq!(self.state.compare_and_swap(1, 0, Ordering::Relaxed), 1);
    }
}

impl <T> Deref for RwLockReadGuard<T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &Self::Target {
        unsafe {
            &*self.lock.data.get()
        }
    }
}

impl <T> Deref for RwLockWriteGuard<T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &Self::Target {
        unsafe {
            &*self.lock.data.get()
        }
    }
}

impl <T> DerefMut for RwLockWriteGuard<T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        self.mutate()
    }
}

impl <T> RwLockWriteGuard<T> {
    #[inline]
    pub fn mutate(&self) -> &mut T {
        unsafe { &mut *self.lock.data.get() }
    }
}

impl <T: ?Sized> Drop for RwLockReadGuard<T> {
    #[inline]
    fn drop(&mut self) {
        self.lock.raw.unlock_read()
    }
}

impl <T: ?Sized> Drop for RwLockWriteGuard<T> {
    #[inline]
    fn drop(&mut self) {
        self.lock.raw.unlock_write()
    }
}

#[cfg(test)]
mod tests {
    extern crate rand;
    use self::rand::Rng;
    use std::sync::mpsc::channel;
    use std::thread;
    use std::sync::Arc;
    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::time::Duration;
    use super::*;

    #[derive(Eq, PartialEq, Debug)]
    struct NonCopy(i32);

    #[test]
    fn smoke() {
        let l = RwLock::new(());
        drop(l.read());
        drop(l.write());
        drop((l.read(), l.read()));
        drop(l.write());
    }

    #[test]
    fn frob() {
        const N: u32 = 10;
        const M: u32 = 1000;

        let r = Arc::new(RwLock::new(()));

        let (tx, rx) = channel::<()>();
        for _ in 0..N {
            let tx = tx.clone();
            let r = r.clone();
            thread::spawn(move || {
                let mut rng = rand::thread_rng();
                for _ in 0..M {
                    if rng.gen_weighted_bool(N) {
                        drop(r.write());
                    } else {
                        drop(r.read());
                    }
                }
                drop(tx);
            });
        }
        drop(tx);
        let _ = rx.recv();
    }

    #[test]
    fn test_rw_arc_no_poison_wr() {
        let arc = Arc::new(RwLock::new(1));
        let arc2 = arc.clone();
        thread::spawn(move || {
            thread::sleep(Duration::from_millis(10));
            let _lock = arc2.write();
            panic!();
        });
        let lock = arc.read();
        assert_eq!(*lock, 1);
    }

    #[test]
    fn test_rw_arc_no_poison_ww() {
        let arc = Arc::new(RwLock::new(1));
        let arc2 = arc.clone();
        thread::spawn(move || {
            thread::sleep(Duration::from_millis(10));
            let _lock = arc2.write();
            panic!();
        });
        let lock = arc.write();
        assert_eq!(*lock, 1);
    }

    #[test]
    fn test_rw_arc() {
        let arc = Arc::new(RwLock::new(0));
        let arc2 = arc.clone();
        let (tx, rx) = channel();

        thread::spawn(move || {
            let mut lock = arc2.write();
            for _ in 0..10 {
                let tmp = *lock;
                *lock = -1;
                thread::yield_now();
                *lock = tmp + 1;
            }
            tx.send(()).unwrap();
        });

        // Readers try to catch the writer in the act
        let mut children = Vec::new();
        for _ in 0..5 {
            let arc3 = arc.clone();
            children.push(thread::spawn(move || {
                let lock = arc3.read();
                assert!(*lock >= 0);
            }));
        }

        // Wait for children to pass their asserts
        for r in children {
            assert!(r.join().is_ok());
        }

        // Wait for writer to finish
        rx.recv().unwrap();
        let lock = arc.read();
        assert_eq!(*lock, 10);
    }
}<commit_msg>fix rwlock guards clone<commit_after>use futures::{Future, Async, Poll};
use super::cpu_relax;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::cell::UnsafeCell;
use std::ops::{Deref, DerefMut};

#[derive(Clone)]
pub struct RwLock<T: ?Sized> {
    inner: Arc<RwLockInner<T>>
}

struct RwLockInner<T: ?Sized> {
    raw: RwLockRaw,
    data: UnsafeCell<T>
}

struct RwLockRaw {
    state: AtomicUsize
}

#[derive(Clone)]
pub struct AsyncRwLockReadGuard<T: ?Sized> {
    lock: Arc<RwLockInner<T>>
}

#[derive(Clone)]
pub struct AsyncRwLockWriteGuard<T: ?Sized> {
    lock: Arc<RwLockInner<T>>
}

struct RwLockReadGuardInner<T: ?Sized> {
    lock: Arc<RwLockInner<T>>
}

struct RwLockWriteGuardInner<T: ?Sized> {
    lock: Arc<RwLockInner<T>>
}

#[derive(Clone)]
pub struct RwLockReadGuard<T: ?Sized> {
    inner: Arc<RwLockReadGuardInner<T>>
}

#[derive(Clone)]
pub struct RwLockWriteGuard<T: ?Sized> {
    inner: Arc<RwLockWriteGuardInner<T>>
}

unsafe impl<T: Send> Send for RwLock<T> {}
unsafe impl<T: Send> Sync for RwLock<T> {}

unsafe impl<T: Send> Send for RwLockInner<T> {}
unsafe impl<T: Send> Sync for RwLockInner<T> {}

impl <T: ?Sized> Future for AsyncRwLockReadGuard<T> {
    type Item = RwLockReadGuard<T>;
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if self.lock.raw.try_read() {
            Ok(Async::Ready(RwLockReadGuard::new(&self.lock)))
        } else {
            Ok(Async::NotReady)
        }
    }
}

impl <T> Future for AsyncRwLockWriteGuard<T> {
    type Item = RwLockWriteGuard<T>;
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if self.lock.raw.try_write() {
            Ok(Async::Ready(RwLockWriteGuard::new(&self.lock)))
        } else {
            Ok(Async::NotReady)
        }
    }
}

impl <T> RwLock <T> {
    pub fn new(val: T) -> RwLock<T> {
        RwLock {
            inner: RwLockInner::new(val)
        }
    }
    pub fn read_async(&self) -> AsyncRwLockReadGuard<T> {
        AsyncRwLockReadGuard {
            lock: self.inner.clone()
        }
    }
    pub fn write_async(&self) -> AsyncRwLockWriteGuard<T> {
        AsyncRwLockWriteGuard {
            lock: self.inner.clone()
        }
    }
    pub fn read(&self) -> RwLockReadGuard<T> {
        while !self.inner.raw.try_read() {
            cpu_relax()
        }
        RwLockReadGuard::new(&self.inner)
    }
    pub fn write(&self) -> RwLockWriteGuard<T> {
        while !self.inner.raw.try_write() {
            cpu_relax()
        }
        RwLockWriteGuard::new(&self.inner)
    }
}

impl <T> RwLockInner<T> {
    pub fn new(val: T) -> Arc<RwLockInner<T>> {
        Arc::new(RwLockInner {
            raw: RwLockRaw::new(),
            data: UnsafeCell::new(val)
        })
    }
}

impl RwLockRaw {
    fn new() -> RwLockRaw {
        RwLockRaw {
          state: AtomicUsize::new(0)
        }
    }
    fn try_read(&self) -> bool  {
        let lc = self.state.load(Ordering::Relaxed);
        if lc == 1 {
            // write locked
            return false;
        } else {
            let next_count = if lc == 0 { 2 } else { lc + 1 };
            return self.state.compare_and_swap(lc, next_count, Ordering::Relaxed) == lc;
        }
    }
    fn try_write(&self) -> bool {
        self.state.compare_and_swap(0, 1, Ordering::Relaxed) == 0
    }
    fn unlock_read(&self) {
        loop {
            let lc = self.state.load(Ordering::Relaxed);
            assert!(lc > 1);
            let next_count = if lc == 2 { 0 } else { lc - 1 };
            if self.state.compare_and_swap(lc, next_count, Ordering::Relaxed) == lc {
                return;
            } else {
                cpu_relax();
            }
        }
    }
    fn unlock_write(&self) {
        assert_eq!(self.state.compare_and_swap(1, 0, Ordering::Relaxed), 1);
    }
}

impl <T: ?Sized>  RwLockReadGuard<T> {
    fn new(raw: &Arc<RwLockInner<T>>) -> RwLockReadGuard<T> {
        RwLockReadGuard {
            inner: Arc::new(RwLockReadGuardInner {
                lock: raw.clone(),
            })
        }
    }
}

impl <T>  RwLockWriteGuard<T> {
    fn new(raw: &Arc<RwLockInner<T>>) -> RwLockWriteGuard<T> {
        RwLockWriteGuard {
            inner: Arc::new(RwLockWriteGuardInner {
                lock: raw.clone(),
            })
        }
    }
}

impl <T> Deref for RwLockReadGuardInner<T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &Self::Target {
        unsafe {
            &*self.lock.data.get()
        }
    }
}

impl <T> Deref for RwLockWriteGuardInner<T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &Self::Target {
        unsafe {
            &*self.lock.data.get()
        }
    }
}

impl <T> DerefMut for RwLockWriteGuardInner<T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        self.mutate()
    }
}

impl <T> RwLockWriteGuardInner<T> {
    #[inline]
    pub fn mutate(&self) -> &mut T {
        unsafe { &mut *self.lock.data.get() }
    }
}

impl <T> RwLockWriteGuard<T> {
    #[inline]
    pub fn mutate(&self) -> &mut T {
        self.inner.mutate()
    }
}

impl <T: ?Sized> Drop for RwLockReadGuardInner<T> {
    #[inline]
    fn drop(&mut self) {
        self.lock.raw.unlock_read()
    }
}

impl <T: ?Sized> Drop for RwLockWriteGuardInner<T> {
    #[inline]
    fn drop(&mut self) {
        self.lock.raw.unlock_write()
    }
}

impl <T> Deref for RwLockReadGuard<T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &Self::Target {
        &*self.inner
    }
}

impl <T> Deref for RwLockWriteGuard<T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &Self::Target {
        &*self.inner
    }
}

impl <T> DerefMut for RwLockWriteGuard<T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        self.inner.mutate()
    }
}

#[cfg(test)]
mod tests {
    extern crate rand;
    use self::rand::Rng;
    use std::sync::mpsc::channel;
    use std::thread;
    use std::sync::Arc;
    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::time::Duration;
    use super::*;

    #[derive(Eq, PartialEq, Debug)]
    struct NonCopy(i32);

    #[test]
    fn smoke() {
        let l = RwLock::new(());
        drop(l.read());
        drop(l.write());
        drop((l.read(), l.read()));
        drop(l.write());
    }

    #[test]
    fn frob() {
        const N: u32 = 10;
        const M: u32 = 1000;

        let r = Arc::new(RwLock::new(()));

        let (tx, rx) = channel::<()>();
        for _ in 0..N {
            let tx = tx.clone();
            let r = r.clone();
            thread::spawn(move || {
                let mut rng = rand::thread_rng();
                for _ in 0..M {
                    if rng.gen_weighted_bool(N) {
                        drop(r.write());
                    } else {
                        drop(r.read());
                    }
                }
                drop(tx);
            });
        }
        drop(tx);
        let _ = rx.recv();
    }

    #[test]
    fn test_rw_arc_no_poison_wr() {
        let arc = Arc::new(RwLock::new(1));
        let arc2 = arc.clone();
        thread::spawn(move || {
            thread::sleep(Duration::from_millis(10));
            let _lock = arc2.write();
            panic!();
        });
        let lock = arc.read();
        assert_eq!(*lock, 1);
    }

    #[test]
    fn test_rw_arc_no_poison_ww() {
        let arc = Arc::new(RwLock::new(1));
        let arc2 = arc.clone();
        thread::spawn(move || {
            thread::sleep(Duration::from_millis(10));
            let _lock = arc2.write();
            panic!();
        });
        let lock = arc.write();
        assert_eq!(*lock, 1);
    }

    #[test]
    fn test_rw_arc() {
        let arc = Arc::new(RwLock::new(0));
        let arc2 = arc.clone();
        let (tx, rx) = channel();

        thread::spawn(move || {
            let mut lock = arc2.write();
            for _ in 0..10 {
                let tmp = *lock;
                *lock = -1;
                thread::yield_now();
                *lock = tmp + 1;
            }
            tx.send(()).unwrap();
        });

        // Readers try to catch the writer in the act
        let mut children = Vec::new();
        for _ in 0..5 {
            let arc3 = arc.clone();
            children.push(thread::spawn(move || {
                let lock = arc3.read();
                assert!(*lock >= 0);
            }));
        }

        // Wait for children to pass their asserts
        for r in children {
            assert!(r.join().is_ok());
        }

        // Wait for writer to finish
        rx.recv().unwrap();
        let lock = arc.read();
        assert_eq!(*lock, 10);
    }

    #[test]
    fn clone_guard() {
        let lock = RwLock::new(0);
        {
            let guard1 = lock.read();
            let guard2 = guard1.clone();
        }
        {
            let mut guard3 = lock.write();
            *guard3 = 3;
        }
        let guard4 = lock.read();
        assert_eq!(*guard4, 3);
    }
}<|endoftext|>


<commit_before>extern crate byteorder;
extern crate clap;

#[macro_use]
extern crate futures;
extern crate futures_cpupool;

#[macro_use]
extern crate tokio_core;

use futures::{Async, Poll, Future};

use byteorder::{LittleEndian, ByteOrder};

use std::cell::{Cell};
use std::rc::Rc;
use std::time::Duration;

mod all {
    use futures::{Async, Poll, Future};
    enum ElemState<T> where T: Future {
        Pending(T),
        Done(T::Item),
    }

    pub struct All<T> where T: Future {
        elems: Vec<ElemState<T>>,
    }

    impl <T> All<T> where T: Future {
        pub fn new<I>(futures: I) -> All<T> where I: Iterator<Item=T> {
            let mut result = All { elems: Vec::new() };
            for f in futures {
                result.elems.push(ElemState::Pending(f))
            }
            result
        }
    }

    impl <T> Future for All<T> where T: Future {
        type Item = Vec<T::Item>;
        type Error = T::Error;

        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            let mut all_done = true;

            for idx in 0 .. self.elems.len() {
                let done_val = match &mut self.elems[idx] {
                    &mut ElemState::Pending(ref mut t) => {
                        match t.poll() {
                            Ok(Async::Ready(t)) => t,
                            Ok(Async::NotReady) => {
                                all_done = false;
                                continue
                            }
                            Err(e) => return Err(e),
                        }
                    }
                    &mut ElemState::Done(ref mut _v) => continue,
                };

                self.elems[idx] = ElemState::Done(done_val);
            }

            if all_done {
                let mut result = Vec::new();
                let elems = ::std::mem::replace(&mut self.elems, Vec::new());
                for e in elems.into_iter() {
                    match e {
                        ElemState::Done(t) => result.push(t),
                        _ => unreachable!(),
                    }
                }
                Ok(Async::Ready(result))
            } else {
                Ok(Async::NotReady)
            }
        }
    }
}

struct Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>
{
    f: F,
    in_progress: T,
}

fn tie_knot<F, S, T, E>(initial_state: S, f: F) -> Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>,
{
    let in_progress = f(initial_state);
    Knot {
        f: f,
        in_progress: in_progress,
    }
}

impl <F, S, T, E> Future for Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>
{
    type Item = S;
    type Error = E;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            let (s, more) = try_ready!(self.in_progress.poll());
            if more {
                self.in_progress = (self.f)(s);
            } else {
                return Ok(Async::Ready(s))
            }
        }
    }
}

struct Reading<R> where R: ::std::io::Read {
    reader: Option<R>,
    buffer: Vec<u8>,
    pos: usize,
    frame_end: Option<u8>,
}

impl <R> Reading<R> where R: ::std::io::Read {
    fn new(reader: R) -> Reading<R> {
        Reading {
            reader: Some(reader),
            buffer: Vec::new(),
            pos: 0,
            frame_end: None,
        }
    }
}

impl <R> Future for Reading<R> where R: ::std::io::Read {
    type Item = (R, Option<Vec<u8>>);
    type Error = ::std::io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            if let Some(frame_end) = self.frame_end {
                let n = try_nb!(self.reader.as_mut().unwrap().read(&mut self.buffer[self.pos..frame_end as usize]));
                self.pos += n;
                if self.pos == frame_end as usize {
                    self.pos = 0;
                    let result = ::std::mem::replace(&mut self.buffer, Vec::new());
                    self.frame_end = None;
                    return Ok(Async::Ready((self.reader.take().unwrap(), Some(result))))
                }
            } else {
                let mut buf = [0u8];
                let n = try_nb!(self.reader.as_mut().unwrap().read(&mut buf));
                if n == 0 { // EOF
                    return Ok(Async::Ready((self.reader.take().unwrap(), None)))
                }
                self.frame_end = Some(buf[0]);
                self.buffer = vec![0; buf[0] as usize];
            }
        }
    }
}

pub struct Writing<W, B> where W: ::std::io::Write, B: AsRef<[u8]> {
    writer: Option<W>,
    message: B,
    pos: usize,
    wrote_header: bool,
}

impl <W, B> Writing<W, B> where W: ::std::io::Write, B: AsRef<[u8]> {
    fn new(writer: W, message: B) -> Writing<W, B> {
        Writing {
            writer: Some(writer),
            message: message,
            pos: 0,
            wrote_header: false,
        }
    }
}

impl <W, B> Future for Writing<W, B> where W: ::std::io::Write, B: AsRef<[u8]> {
    type Item = W;
    type Error = ::std::io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            if !self.wrote_header {
                let buf = [self.message.as_ref().len() as u8];
                try_nb!(self.writer.as_mut().unwrap().write(&buf));
                self.wrote_header = true;
            } else {
                let n = try_nb!(self.writer.as_mut().unwrap().write(&self.message.as_ref()[self.pos..]));
                self.pos += n;
                if self.pos >= self.message.as_ref().len() {
                    return Ok(Async::Ready(self.writer.take().unwrap()))
                }
            }
        }
    }
}

#[derive(Clone)]
struct ConnectionIdSource {
    next_id: Rc<Cell<u64>>,
}

impl ConnectionIdSource {
    fn new() -> ConnectionIdSource {
        ConnectionIdSource {
            next_id: Rc::new(Cell::new(1)),
        }
    }

    fn next(&self) -> u64 {
        let result = self.next_id.get();
        self.next_id.set(result + 1);
        result
    }
}

static CLOCK_PREFIX: &'static [u8] = &[0,0,0,0,0,0,0,0];

fn read_until_message_with_prefix<R, B>(
    reader: R,
    prefix: B,
    timeout_seconds: u64)
    -> Box<Future<Item=(R, Option<Vec<u8>>), Error=::std::io::Error> + 'static + Send>
    where R: ::std::io::Read + 'static + Send,
          B: AsRef<[u8]> + 'static + Send,
{
    Box::new(tie_knot((reader, prefix, 0, None), move |(reader, prefix, ticks, _)| {
        Reading::new(reader).and_then(move |(reader, message)| {
            match message {
                Some(message) => {
                    let len = prefix.as_ref().len();
                    let mut new_ticks = ticks;
                    if  &message[0..len] != prefix.as_ref() {
                        Ok(((reader, prefix, new_ticks, Some(message)), false))
                    } else {
                        if &message[..CLOCK_PREFIX.len()] == CLOCK_PREFIX {
                            new_ticks = ticks + 1;
                        }

                        if new_ticks > timeout_seconds {
                            Ok(((reader, prefix, new_ticks, None), false))
                        }  else {
                            Ok(((reader, prefix, new_ticks, Some(message)), true))
                        }
                    }
                }
                None => {
                    Ok(((reader, prefix, ticks, None), false))
                }
            }
        })
    }).map(|(reader, _, _, message)| (reader, message)))
}

fn read_until_eof<R>(reader: R)
                     -> Box<Future<Item=R, Error=::std::io::Error> + 'static + Send>
    where R: ::std::io::Read + 'static + Send,
{
    Box::new(tie_knot(reader, move |reader| {
        Reading::new(reader).and_then(move |(reader, message)| {
            match message {
                Some(_) => {
                    Ok((reader, true))
                }
                None => {
                    Ok((reader, false))
                }
            }
        })
    }))
}

fn new_task(handle: &::tokio_core::reactor::Handle,
            addr: &::std::net::SocketAddr,
            connection_id_source: ConnectionIdSource,
            number_of_messages: u64,
            number_of_subscribers: u64)
            -> Box<Future<Item=usize, Error=::std::io::Error> + Send>
{
    use all::All;
    use std::sync::atomic::{AtomicUsize, Ordering};

    let publisher = ::tokio_core::net::TcpStream::connect(addr, handle);
    let publisher_id = connection_id_source.next();

    let mut subscribers = Vec::new();
    for _ in 0..number_of_subscribers {
        let subscriber_id = connection_id_source.next();
        subscribers.push(::tokio_core::net::TcpStream::connect(addr, handle).and_then(move |socket| {
            let mut buf = [0; 8];
            <LittleEndian as ByteOrder>::write_u64(&mut buf[..], subscriber_id);
            Writing::new(socket, buf).and_then(move |socket| {
                read_until_message_with_prefix(socket, buf, 2)
                    .map(|(socket, _message)| { socket })
            })
        }))
    }

    Box::new(publisher.join(All::new(subscribers.into_iter())).and_then(move |(publisher, subscribers)| {
        let successful_message_count = ::futures::task::TaskRc::new(AtomicUsize::new(0));
        let smc = successful_message_count.clone();
        tie_knot((publisher, subscribers, 0u64), move |(publisher, subscribers, n)| {
            println!("looping {}", n);
            let mut buf = vec![255; 16];
            let mut prefix = [0; 8];
            <LittleEndian as ByteOrder>::write_u64(&mut buf[..8], publisher_id);
            <LittleEndian as ByteOrder>::write_u64(&mut prefix[..], publisher_id);

            let smc = smc.clone();
            Writing::new(publisher, buf).and_then(move |publisher| {
                All::new(subscribers.into_iter().map(move |s| {
                    let smc = smc.clone();
                    read_until_message_with_prefix(s, prefix, 2)
                        .map(move |(stream, message)| {
                            match message {
                                Some(_) => {
                                    // TODO check that the message is what the publisher sent.
                                    smc.with(|x| {
                                        x.fetch_add(1, Ordering::SeqCst);
                                    });
                                }
                                None => (),
                            }
                            stream
                        })
                })).and_then(move |subscribers| {
                    futures::finished(((publisher, subscribers, n + 1), n < number_of_messages))
                })
            })
        }).and_then(|(publisher, subscribers, _)| {
            try!(publisher.shutdown(::std::net::Shutdown::Write));
            for sub in &subscribers {
                try!(sub.shutdown(::std::net::Shutdown::Write));
            }
            Ok((publisher, subscribers))
        }).and_then(|(publisher, subscribers)| {
            read_until_eof(publisher).join(
                All::new(subscribers.into_iter().map(|sub| {
                    read_until_eof(sub)
                })))
        }).map(move |_| successful_message_count.with(|x| x.load(Ordering::SeqCst)))
    }))
}

struct ChildProcess {
    child: ::std::process::Child
}

impl ChildProcess {
    fn new(child: ::std::process::Child) -> ChildProcess {
        ChildProcess { child: child }
    }
}

impl Drop for ChildProcess {
    fn drop(&mut self) {
        let _ = self.child.kill();
    }
}

pub fn run() -> Result<(), ::std::io::Error> {
    use clap::{App, Arg};
    let matches = App::new("Zillions benchmarker")
        .version("0.0.0")
        .about("Does awesome things")
        .arg(Arg::with_name("EXECUTABLE")
             .required(true)
             .index(1)
             .help("The executable to benchmark"))
        .arg(Arg::with_name("server")
             .required(false)
             .long("server")
             .short("s")
             .value_name("address")
             .default_value("127.0.0.1:8080")
             .help("address to use to connect to server"))
        .get_matches();

    let executable = matches.value_of("EXECUTABLE").unwrap();

    println!("exectuable: {}", executable);

    let addr_str = matches.value_of("server").unwrap();
    let addr = match addr_str.parse::<::std::net::SocketAddr>() {
        Ok(a) => a,
        Err(e) => {
            panic!("failed to parse socket address {}", e);
        }
    };

    let mut child = try!(::std::process::Command::new(executable)
        .arg(addr_str)
        .stdout(::std::process::Stdio::piped())
        .stderr(::std::process::Stdio::inherit())
        .spawn());

    let mut child_stdout = ::std::io::BufReader::new(child.stdout.take().unwrap());
    let _wrapped_child = ChildProcess::new(child);

    let mut first_line = String::new();
    try!(::std::io::BufRead::read_line(&mut child_stdout, &mut first_line));

    if !first_line.starts_with("listening on") {
        return Err(::std::io::Error::new(
            ::std::io::ErrorKind::Other,
            format!(
                "expected first line from server to start with 'listening on ', but got {}",
                first_line)))
    }

    // start tokio reactor
    let mut core = try!(::tokio_core::reactor::Core::new());

    let handle = core.handle();

    let pool = ::futures_cpupool::CpuPool::new_num_cpus();
    let connection_id_source = ConnectionIdSource::new();

    // Start a connection whose sole job is to send periodic "tick" messages.
    let clock_connection = ::tokio_core::net::TcpStream::connect(&addr, &handle);
    let handle1 = handle.clone();
    handle.spawn(clock_connection.and_then(move |stream| {
        tie_knot((stream, handle1), move |(stream, handle)| {
            use tokio_core::reactor::Timeout;
            Timeout::new(Duration::from_secs(1), &handle).expect("creating timeout").and_then(move |()| {
                Writing::new(stream, CLOCK_PREFIX).map(move |stream| {
                    ((stream, handle), true)
                })
            })
        })
    }).map(|_| ()).map_err(|e| { println!("error from clock task: {}", e); () }));

    let f = pool.spawn(new_task(&handle, &addr, connection_id_source.clone(), 5, 3)
                       .join(new_task(&core.handle(), &addr, connection_id_source, 5, 10)));

    let x = try!(core.run(f));
    println!("x = {:?}", x);

    Ok(())
}

pub fn main() {
    run().expect("top level error");
}
<commit_msg>fix off-by-one<commit_after>extern crate byteorder;
extern crate clap;

#[macro_use]
extern crate futures;
extern crate futures_cpupool;

#[macro_use]
extern crate tokio_core;

use futures::{Async, Poll, Future};

use byteorder::{LittleEndian, ByteOrder};

use std::cell::{Cell};
use std::rc::Rc;
use std::time::Duration;

mod all {
    use futures::{Async, Poll, Future};
    enum ElemState<T> where T: Future {
        Pending(T),
        Done(T::Item),
    }

    pub struct All<T> where T: Future {
        elems: Vec<ElemState<T>>,
    }

    impl <T> All<T> where T: Future {
        pub fn new<I>(futures: I) -> All<T> where I: Iterator<Item=T> {
            let mut result = All { elems: Vec::new() };
            for f in futures {
                result.elems.push(ElemState::Pending(f))
            }
            result
        }
    }

    impl <T> Future for All<T> where T: Future {
        type Item = Vec<T::Item>;
        type Error = T::Error;

        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            let mut all_done = true;

            for idx in 0 .. self.elems.len() {
                let done_val = match &mut self.elems[idx] {
                    &mut ElemState::Pending(ref mut t) => {
                        match t.poll() {
                            Ok(Async::Ready(t)) => t,
                            Ok(Async::NotReady) => {
                                all_done = false;
                                continue
                            }
                            Err(e) => return Err(e),
                        }
                    }
                    &mut ElemState::Done(ref mut _v) => continue,
                };

                self.elems[idx] = ElemState::Done(done_val);
            }

            if all_done {
                let mut result = Vec::new();
                let elems = ::std::mem::replace(&mut self.elems, Vec::new());
                for e in elems.into_iter() {
                    match e {
                        ElemState::Done(t) => result.push(t),
                        _ => unreachable!(),
                    }
                }
                Ok(Async::Ready(result))
            } else {
                Ok(Async::NotReady)
            }
        }
    }
}

struct Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>
{
    f: F,
    in_progress: T,
}

fn tie_knot<F, S, T, E>(initial_state: S, f: F) -> Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>,
{
    let in_progress = f(initial_state);
    Knot {
        f: f,
        in_progress: in_progress,
    }
}

impl <F, S, T, E> Future for Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>
{
    type Item = S;
    type Error = E;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            let (s, more) = try_ready!(self.in_progress.poll());
            if more {
                self.in_progress = (self.f)(s);
            } else {
                return Ok(Async::Ready(s))
            }
        }
    }
}

struct Reading<R> where R: ::std::io::Read {
    reader: Option<R>,
    buffer: Vec<u8>,
    pos: usize,
    frame_end: Option<u8>,
}

impl <R> Reading<R> where R: ::std::io::Read {
    fn new(reader: R) -> Reading<R> {
        Reading {
            reader: Some(reader),
            buffer: Vec::new(),
            pos: 0,
            frame_end: None,
        }
    }
}

impl <R> Future for Reading<R> where R: ::std::io::Read {
    type Item = (R, Option<Vec<u8>>);
    type Error = ::std::io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            if let Some(frame_end) = self.frame_end {
                let n = try_nb!(self.reader.as_mut().unwrap().read(&mut self.buffer[self.pos..frame_end as usize]));
                self.pos += n;
                if self.pos == frame_end as usize {
                    self.pos = 0;
                    let result = ::std::mem::replace(&mut self.buffer, Vec::new());
                    self.frame_end = None;
                    return Ok(Async::Ready((self.reader.take().unwrap(), Some(result))))
                }
            } else {
                let mut buf = [0u8];
                let n = try_nb!(self.reader.as_mut().unwrap().read(&mut buf));
                if n == 0 { // EOF
                    return Ok(Async::Ready((self.reader.take().unwrap(), None)))
                }
                self.frame_end = Some(buf[0]);
                self.buffer = vec![0; buf[0] as usize];
            }
        }
    }
}

pub struct Writing<W, B> where W: ::std::io::Write, B: AsRef<[u8]> {
    writer: Option<W>,
    message: B,
    pos: usize,
    wrote_header: bool,
}

impl <W, B> Writing<W, B> where W: ::std::io::Write, B: AsRef<[u8]> {
    fn new(writer: W, message: B) -> Writing<W, B> {
        Writing {
            writer: Some(writer),
            message: message,
            pos: 0,
            wrote_header: false,
        }
    }
}

impl <W, B> Future for Writing<W, B> where W: ::std::io::Write, B: AsRef<[u8]> {
    type Item = W;
    type Error = ::std::io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            if !self.wrote_header {
                let buf = [self.message.as_ref().len() as u8];
                try_nb!(self.writer.as_mut().unwrap().write(&buf));
                self.wrote_header = true;
            } else {
                let n = try_nb!(self.writer.as_mut().unwrap().write(&self.message.as_ref()[self.pos..]));
                self.pos += n;
                if self.pos >= self.message.as_ref().len() {
                    return Ok(Async::Ready(self.writer.take().unwrap()))
                }
            }
        }
    }
}

#[derive(Clone)]
struct ConnectionIdSource {
    next_id: Rc<Cell<u64>>,
}

impl ConnectionIdSource {
    fn new() -> ConnectionIdSource {
        ConnectionIdSource {
            next_id: Rc::new(Cell::new(1)),
        }
    }

    fn next(&self) -> u64 {
        let result = self.next_id.get();
        self.next_id.set(result + 1);
        result
    }
}

static CLOCK_PREFIX: &'static [u8] = &[0,0,0,0,0,0,0,0];

fn read_until_message_with_prefix<R, B>(
    reader: R,
    prefix: B,
    timeout_seconds: u64)
    -> Box<Future<Item=(R, Option<Vec<u8>>), Error=::std::io::Error> + 'static + Send>
    where R: ::std::io::Read + 'static + Send,
          B: AsRef<[u8]> + 'static + Send,
{
    Box::new(tie_knot((reader, prefix, 0, None), move |(reader, prefix, ticks, _)| {
        Reading::new(reader).and_then(move |(reader, message)| {
            match message {
                Some(message) => {
                    let len = prefix.as_ref().len();
                    let mut new_ticks = ticks;
                    if  &message[0..len] != prefix.as_ref() {
                        Ok(((reader, prefix, new_ticks, Some(message)), false))
                    } else {
                        if &message[..CLOCK_PREFIX.len()] == CLOCK_PREFIX {
                            new_ticks = ticks + 1;
                        }

                        if new_ticks > timeout_seconds {
                            Ok(((reader, prefix, new_ticks, None), false))
                        }  else {
                            Ok(((reader, prefix, new_ticks, Some(message)), true))
                        }
                    }
                }
                None => {
                    Ok(((reader, prefix, ticks, None), false))
                }
            }
        })
    }).map(|(reader, _, _, message)| (reader, message)))
}

fn read_until_eof<R>(reader: R)
                     -> Box<Future<Item=R, Error=::std::io::Error> + 'static + Send>
    where R: ::std::io::Read + 'static + Send,
{
    Box::new(tie_knot(reader, move |reader| {
        Reading::new(reader).and_then(move |(reader, message)| {
            match message {
                Some(_) => {
                    Ok((reader, true))
                }
                None => {
                    Ok((reader, false))
                }
            }
        })
    }))
}

fn new_task(handle: &::tokio_core::reactor::Handle,
            addr: &::std::net::SocketAddr,
            connection_id_source: ConnectionIdSource,
            number_of_messages: u64,
            number_of_subscribers: u64)
            -> Box<Future<Item=usize, Error=::std::io::Error> + Send>
{
    use all::All;
    use std::sync::atomic::{AtomicUsize, Ordering};

    let publisher = ::tokio_core::net::TcpStream::connect(addr, handle);
    let publisher_id = connection_id_source.next();

    let mut subscribers = Vec::new();
    for _ in 0..number_of_subscribers {
        let subscriber_id = connection_id_source.next();
        subscribers.push(::tokio_core::net::TcpStream::connect(addr, handle).and_then(move |socket| {
            let mut buf = [0; 8];
            <LittleEndian as ByteOrder>::write_u64(&mut buf[..], subscriber_id);
            Writing::new(socket, buf).and_then(move |socket| {
                read_until_message_with_prefix(socket, buf, 2)
                    .map(|(socket, _message)| { socket })
            })
        }))
    }

    Box::new(publisher.join(All::new(subscribers.into_iter())).and_then(move |(publisher, subscribers)| {
        let successful_message_count = ::futures::task::TaskRc::new(AtomicUsize::new(0));
        let smc = successful_message_count.clone();
        tie_knot((publisher, subscribers, 0u64), move |(publisher, subscribers, n)| {
//            println!("looping {}", n);
            let mut buf = vec![255; 16];
            let mut prefix = [0; 8];
            <LittleEndian as ByteOrder>::write_u64(&mut buf[..8], publisher_id);
            <LittleEndian as ByteOrder>::write_u64(&mut prefix[..], publisher_id);

            let smc = smc.clone();
            Writing::new(publisher, buf).and_then(move |publisher| {
                All::new(subscribers.into_iter().map(move |s| {
                    let smc = smc.clone();
                    read_until_message_with_prefix(s, prefix, 2)
                        .map(move |(stream, message)| {
                            match message {
                                Some(_) => {
                                    // TODO check that the message is what the publisher sent.
                                    smc.with(|x| {
                                        x.fetch_add(1, Ordering::SeqCst);
                                    });
                                }
                                None => (),
                            }
                            stream
                        })
                })).and_then(move |subscribers| {
                    futures::finished(((publisher, subscribers, n + 1), n + 1 < number_of_messages))
                })
            })
        }).and_then(|(publisher, subscribers, _)| {
            println!("shutting down");
            try!(publisher.shutdown(::std::net::Shutdown::Write));
            for sub in &subscribers {
                try!(sub.shutdown(::std::net::Shutdown::Write));
            }
            Ok((publisher, subscribers))
        }).and_then(|(publisher, subscribers)| {
            read_until_eof(publisher).join(
                All::new(subscribers.into_iter().map(|sub| {
                    read_until_eof(sub)
                })))
        }).map(move |_| successful_message_count.with(|x| x.load(Ordering::SeqCst)))
    }))
}

struct ChildProcess {
    child: ::std::process::Child
}

impl ChildProcess {
    fn new(child: ::std::process::Child) -> ChildProcess {
        ChildProcess { child: child }
    }
}

impl Drop for ChildProcess {
    fn drop(&mut self) {
        let _ = self.child.kill();
    }
}

pub fn run() -> Result<(), ::std::io::Error> {
    use clap::{App, Arg};
    let matches = App::new("Zillions benchmarker")
        .version("0.0.0")
        .about("Does awesome things")
        .arg(Arg::with_name("EXECUTABLE")
             .required(true)
             .index(1)
             .help("The executable to benchmark"))
        .arg(Arg::with_name("server")
             .required(false)
             .long("server")
             .short("s")
             .value_name("address")
             .default_value("127.0.0.1:8080")
             .help("address to use to connect to server"))
        .get_matches();

    let executable = matches.value_of("EXECUTABLE").unwrap();

    println!("exectuable: {}", executable);

    let addr_str = matches.value_of("server").unwrap();
    let addr = match addr_str.parse::<::std::net::SocketAddr>() {
        Ok(a) => a,
        Err(e) => {
            panic!("failed to parse socket address {}", e);
        }
    };

    let mut child = try!(::std::process::Command::new(executable)
        .arg(addr_str)
        .stdout(::std::process::Stdio::piped())
        .stderr(::std::process::Stdio::inherit())
        .spawn());

    let mut child_stdout = ::std::io::BufReader::new(child.stdout.take().unwrap());
    let _wrapped_child = ChildProcess::new(child);

    let mut first_line = String::new();
    try!(::std::io::BufRead::read_line(&mut child_stdout, &mut first_line));

    if !first_line.starts_with("listening on") {
        return Err(::std::io::Error::new(
            ::std::io::ErrorKind::Other,
            format!(
                "expected first line from server to start with 'listening on ', but got {}",
                first_line)))
    }

    // start tokio reactor
    let mut core = try!(::tokio_core::reactor::Core::new());

    let handle = core.handle();

    let pool = ::futures_cpupool::CpuPool::new_num_cpus();
    let connection_id_source = ConnectionIdSource::new();

    // Start a connection whose sole job is to send periodic "tick" messages.
    let clock_connection = ::tokio_core::net::TcpStream::connect(&addr, &handle);
    let handle1 = handle.clone();
    handle.spawn(clock_connection.and_then(move |stream| {
        tie_knot((stream, handle1), move |(stream, handle)| {
            use tokio_core::reactor::Timeout;
            Timeout::new(Duration::from_secs(1), &handle).expect("creating timeout").and_then(move |()| {
                Writing::new(stream, CLOCK_PREFIX).map(move |stream| {
                    ((stream, handle), true)
                })
            })
        })
    }).map(|_| ()).map_err(|e| { println!("error from clock task: {}", e); () }));

    let f = pool.spawn(new_task(&handle, &addr, connection_id_source.clone(), 1000, 3)
                       .join(new_task(&core.handle(), &addr, connection_id_source, 1000, 10)));

    let x = try!(core.run(f));
    println!("x = {:?}", x);

    Ok(())
}

pub fn main() {
    run().expect("top level error");
}
<|endoftext|>


<commit_before>use std::env;

use cargo::ops::CompileOptions;
use cargo::ops;
use cargo::util::important_paths::{find_root_manifest_for_cwd};
use cargo::util::{CliResult, CliError, Config};

#[derive(RustcDecodable)]
struct Options {
    arg_opts: Option<Vec<String>>,
    flag_package: Option<String>,
    flag_jobs: Option<u32>,
    flag_features: Vec<String>,
    flag_no_default_features: bool,
    flag_target: Option<String>,
    flag_manifest_path: Option<String>,
    flag_verbose: bool,
    flag_quiet: bool,
    flag_release: bool,
    flag_lib: bool,
    flag_bin: Vec<String>,
    flag_example: Vec<String>,
    flag_test: Vec<String>,
    flag_bench: Vec<String>,
}

pub const USAGE: &'static str = "
Compile a package and all of its dependencies

Usage:
    cargo rustc [options] [--] [<opts>...]

Options:
    -h, --help               Print this message
    -p SPEC, --package SPEC  The profile to compile for
    -j N, --jobs N           The number of jobs to run in parallel
    --lib                    Build only this package's library
    --bin NAME               Build only the specified binary
    --example NAME           Build only the specified example
    --test NAME              Build only the specified test
    --bench NAME             Build only the specified benchmark
    --release                Build artifacts in release mode, with optimizations
    --features FEATURES      Features to compile for the package
    --no-default-features    Do not compile default features for the package
    --target TRIPLE          Target triple which compiles will be for
    --manifest-path PATH     Path to the manifest to fetch depednencies for
    -v, --verbose            Use verbose output
    -q, --quiet              No output printed to stdout

The specified target for the current package (or package specified by SPEC if
provided) will be compiled along with all of its dependencies. The specified
<opts>... will all be passed to the final compiler invocation, not any of the
dependencies. Note that the compiler will still unconditionally receive
arguments such as -L, --extern, and --crate-type, and the specified <opts>...
will simply be added to the compiler invocation.

This command requires that only one target is being compiled. If more than one
target is available for the current package the filters of --lib, --bin, etc,
must be used to select which target is compiled.
";

pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
    debug!("executing; cmd=cargo-rustc; args={:?}",
           env::args().collect::<Vec<_>>());
    try!(config.shell().set_verbosity(options.flag_verbose, options.flag_quiet));

    let root = try!(find_root_manifest_for_cwd(options.flag_manifest_path));

    let opts = CompileOptions {
        config: config,
        jobs: options.flag_jobs,
        target: options.flag_target.as_ref().map(|t| &t[..]),
        features: &options.flag_features,
        no_default_features: options.flag_no_default_features,
        spec: options.flag_package.as_ref().map(|s| &s[..]),
        exec_engine: None,
        mode: ops::CompileMode::Build,
        release: options.flag_release,
        filter: ops::CompileFilter::new(options.flag_lib,
                                        &options.flag_bin,
                                        &options.flag_test,
                                        &options.flag_example,
                                        &options.flag_bench),
        target_rustc_args: options.arg_opts.as_ref().map(|a| &a[..]),
    };

    ops::compile(&root, &opts).map(|_| None).map_err(|err| {
        CliError::from_boxed(err, 101)
    })
}

<commit_msg>Auto merge of #1785 - kennytm:patch-1, r=alexcrichton<commit_after>use std::env;

use cargo::ops::CompileOptions;
use cargo::ops;
use cargo::util::important_paths::{find_root_manifest_for_cwd};
use cargo::util::{CliResult, CliError, Config};

#[derive(RustcDecodable)]
struct Options {
    arg_opts: Option<Vec<String>>,
    flag_package: Option<String>,
    flag_jobs: Option<u32>,
    flag_features: Vec<String>,
    flag_no_default_features: bool,
    flag_target: Option<String>,
    flag_manifest_path: Option<String>,
    flag_verbose: bool,
    flag_quiet: bool,
    flag_release: bool,
    flag_lib: bool,
    flag_bin: Vec<String>,
    flag_example: Vec<String>,
    flag_test: Vec<String>,
    flag_bench: Vec<String>,
}

pub const USAGE: &'static str = "
Compile a package and all of its dependencies

Usage:
    cargo rustc [options] [--] [<opts>...]

Options:
    -h, --help               Print this message
    -p SPEC, --package SPEC  The profile to compile for
    -j N, --jobs N           The number of jobs to run in parallel
    --lib                    Build only this package's library
    --bin NAME               Build only the specified binary
    --example NAME           Build only the specified example
    --test NAME              Build only the specified test
    --bench NAME             Build only the specified benchmark
    --release                Build artifacts in release mode, with optimizations
    --features FEATURES      Features to compile for the package
    --no-default-features    Do not compile default features for the package
    --target TRIPLE          Target triple which compiles will be for
    --manifest-path PATH     Path to the manifest to fetch dependencies for
    -v, --verbose            Use verbose output
    -q, --quiet              No output printed to stdout

The specified target for the current package (or package specified by SPEC if
provided) will be compiled along with all of its dependencies. The specified
<opts>... will all be passed to the final compiler invocation, not any of the
dependencies. Note that the compiler will still unconditionally receive
arguments such as -L, --extern, and --crate-type, and the specified <opts>...
will simply be added to the compiler invocation.

This command requires that only one target is being compiled. If more than one
target is available for the current package the filters of --lib, --bin, etc,
must be used to select which target is compiled.
";

pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
    debug!("executing; cmd=cargo-rustc; args={:?}",
           env::args().collect::<Vec<_>>());
    try!(config.shell().set_verbosity(options.flag_verbose, options.flag_quiet));

    let root = try!(find_root_manifest_for_cwd(options.flag_manifest_path));

    let opts = CompileOptions {
        config: config,
        jobs: options.flag_jobs,
        target: options.flag_target.as_ref().map(|t| &t[..]),
        features: &options.flag_features,
        no_default_features: options.flag_no_default_features,
        spec: options.flag_package.as_ref().map(|s| &s[..]),
        exec_engine: None,
        mode: ops::CompileMode::Build,
        release: options.flag_release,
        filter: ops::CompileFilter::new(options.flag_lib,
                                        &options.flag_bin,
                                        &options.flag_test,
                                        &options.flag_example,
                                        &options.flag_bench),
        target_rustc_args: options.arg_opts.as_ref().map(|a| &a[..]),
    };

    ops::compile(&root, &opts).map(|_| None).map_err(|err| {
        CliError::from_boxed(err, 101)
    })
}

<|endoftext|>


<commit_before>// Copyright 2013 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.

// Coroutines represent nothing more than a context and a stack
// segment.

use std::default::Default;
use std::rt::util::min_stack;
use thunk::Thunk;
use std::mem::{transmute, transmute_copy};
use std::rt::unwind::try;
use std::any::Any;
use std::cell::UnsafeCell;
use std::ops::DerefMut;
use std::ptr;

use context::Context;
use stack::{StackPool, Stack};

#[derive(Debug, Copy)]
pub enum State {
    Suspended,
    Running,
    Finished,
    Panicked,
}

pub type ResumeResult<T> = Result<T, Box<Any + Send>>;

/// Coroutine spawn options
#[derive(Debug)]
pub struct Options {
    pub stack_size: usize,
    pub name: Option<String>,
}

impl Default for Options {
    fn default() -> Options {
        Options {
            stack_size: min_stack(),
            name: None,
        }
    }
}

/// Handle of a Coroutine
#[derive(Debug)]
pub struct Handle(Box<Coroutine>);

impl Handle {

    #[inline]
    pub fn state(&self) -> State {
        self.0.state()
    }

    pub fn resume(mut self) -> ResumeResult<Handle> {
        match self.state() {
            State::Finished | State::Running => return Ok(self),
            State::Panicked => panic!("Tried to resume a panicked coroutine"),
            _ => {}
        }

        let result = UnsafeCell::new(None);
        COROUTINE_ENVIRONMENT.with(|env| {
            let env: &mut Environment = unsafe { transmute(env.get()) };

            // Move out, keep this reference
            // It may not be the only reference to the Coroutine
            //
            let mut from_coro = env.current_running.take().unwrap();

            // Save state
            self.0.state = State::Running;
            self.0.parent = from_coro.0.deref_mut();
            from_coro.0.state = State::Suspended;

            // Move inside the Environment
            env.current_running = Some(self);

            Context::swap(&mut from_coro.0.saved_context, &env.current_running.as_ref().unwrap().0.saved_context);

            // Move out here
            self = env.current_running.take().unwrap();
            env.current_running = Some(from_coro);

            let result: &mut Option<_> = unsafe { transmute(result.get()) };
            match env.running_state.take() {
                Some(err) => {
                    *result = Some(Err(err));
                },
                None => {
                    *result = Some(Ok(self))
                }
            }
        });

        unsafe { result.into_inner().unwrap() }
    }

    #[inline]
    pub fn join(self) -> ResumeResult<Handle> {
        let mut coro = self;
        loop {
            match coro.state() {
                State::Suspended => coro = try!(coro.resume()),
                _ => break,
            }
        }
        Ok(coro)
    }

    #[inline]
    pub fn name(&self) -> Option<&str> {
        self.0.name.as_ref().map(|s| &**s)
    }
}

/// A coroutine is nothing more than a (register context, stack) pair.
#[allow(raw_pointer_derive)]
#[derive(Debug)]
pub struct Coroutine {
    /// The segment of stack on which the task is currently running or
    /// if the task is blocked, on which the task will resume
    /// execution.
    current_stack_segment: Option<Stack>,

    /// Always valid if the task is alive and not running.
    saved_context: Context,

    /// Parent coroutine, will always be valid
    parent: *mut Coroutine,

    /// State
    state: State,

    /// Name
    name: Option<String>,
}

unsafe impl Send for Coroutine {}
unsafe impl Sync for Coroutine {}

/// Destroy coroutine and try to reuse std::stack segment.
impl Drop for Coroutine {
    fn drop(&mut self) {
        match self.current_stack_segment.take() {
            Some(stack) => {
                COROUTINE_ENVIRONMENT.with(|env| {
                    let env: &mut Environment = unsafe { transmute(env.get()) };
                    env.stack_pool.give_stack(stack);
                });
            },
            None => {}
        }
    }
}

/// Initialization function for make context
extern "C" fn coroutine_initialize(_: usize, f: *mut ()) -> ! {
    let func: Box<Thunk> = unsafe { transmute(f) };

    let ret = unsafe { try(move|| func.invoke(())) };

    COROUTINE_ENVIRONMENT.with(move|env| {
        let env: &mut Environment = unsafe { transmute(env.get()) };

        match ret {
            Ok(..) => {
                env.running_state = None;
                env.current_running.as_mut().unwrap().0.state = State::Finished;
            }
            Err(err) => {
                env.running_state = Some(err);
                env.current_running.as_mut().unwrap().0.state = State::Panicked;

                current().with(|cur| {
                    match cur.name() {
                        Some(name) => println!("Coroutine `{}` panicked", name),
                        None => println!("Coroutine `<unnamed>` panicked"),
                    }
                    cur
                });
            }
        }
    });

    loop {
        Coroutine::sched();
    }
}

impl Coroutine {
    fn empty() -> Handle {
        Handle(box Coroutine {
            current_stack_segment: None,
            saved_context: Context::empty(),
            parent: ptr::null_mut(),
            state: State::Running,
            name: None,
        })
    }

    fn with_name(name: &str) -> Handle {
        Handle(box Coroutine {
            current_stack_segment: None,
            saved_context: Context::empty(),
            parent: ptr::null_mut(),
            state: State::Running,
            name: Some(name.to_string()),
        })
    }

    pub fn spawn_opts<F>(f: F, opts: Options) -> Handle
            where F: FnOnce() + Send + 'static {

        let coro = UnsafeCell::new(Coroutine::empty());
        COROUTINE_ENVIRONMENT.with(|env| {
            unsafe {
                let env: &mut Environment = transmute(env.get());

                let mut stack = env.stack_pool.take_stack(opts.stack_size);

                let ctx = Context::new(coroutine_initialize,
                                   0,
                                   f,
                                   &mut stack);

                let coro: &mut Handle = transmute(coro.get());
                coro.0.saved_context = ctx;
                coro.0.current_stack_segment = Some(stack);
                coro.0.state = State::Suspended;
            }
        });

        let mut coro = unsafe { coro.into_inner() };
        coro.0.name = opts.name;
        coro
    }

    /// Spawn a coroutine with default options
    pub fn spawn<F>(f: F) -> Handle
            where F: FnOnce() + Send + 'static {
        Coroutine::spawn_opts(f, Default::default())
    }

    pub fn sched() {
        COROUTINE_ENVIRONMENT.with(|env| {
            let env: &mut Environment = unsafe { transmute(env.get()) };

            // Move out
            let mut from_coro = env.current_running.as_mut().unwrap();

            match from_coro.state() {
                State::Finished | State::Panicked => {},
                _ => from_coro.0.state = State::Suspended,
            }

            let to_coro: &mut Coroutine = unsafe { transmute_copy(&from_coro.0.parent) };

            Context::swap(&mut from_coro.0.saved_context, &to_coro.saved_context);
        });
    }

    pub fn current() -> HandleGuard {
        HandleGuard
    }

    pub fn state(&self) -> State {
        self.state
    }
}

/// HandleGuard. With provide a `with` method for accessing the current running Coroutine
pub struct HandleGuard;

impl HandleGuard {
    /// Get the current running Coroutine. You have to return it back!
    pub fn with<F>(&self, f: F)
            where F: FnOnce(Handle) -> Handle + Send + 'static {
        COROUTINE_ENVIRONMENT.with(|env| {
            let env: &mut Environment = unsafe { transmute(env.get()) };
            env.current_running = Some(f(env.current_running.take().unwrap()));
        });
    }
}

thread_local!(static COROUTINE_ENVIRONMENT: UnsafeCell<Environment> = UnsafeCell::new(Environment::new()));

/// Coroutine managing environment
#[allow(raw_pointer_derive)]
#[derive(Debug)]
struct Environment {
    stack_pool: StackPool,
    current_running: Option<Handle>,

    running_state: Option<Box<Any + Send>>,
}

impl Environment {
    /// Initialize a new environment
    fn new() -> Environment {
        let mut coro = Coroutine::with_name("<Environment Root Coroutine>");
        coro.0.parent = coro.0.deref_mut(); // Pointing to itself

        Environment {
            stack_pool: StackPool::new(),
            current_running: Some(coro),

            running_state: None,
        }
    }
}

/// Coroutine configuration. Provides detailed control over the properties and behavior of new Coroutines.
pub struct Builder {
    opts: Options,
}

impl Builder {
    /// Generate the base configuration for spawning a Coroutine, from which configuration methods can be chained.
    pub fn new() -> Builder {
        Builder {
            opts: Default::default(),
        }
    }

    /// Name the Coroutine-to-be. Currently the name is used for identification only in panic messages.
    pub fn name(mut self, name: String) -> Builder {
        self.opts.name = Some(name);
        self
    }

    /// Set the size of the stack for the new Coroutine.
    pub fn stack_size(mut self, size: usize) -> Builder {
        self.opts.stack_size = size;
        self
    }

    /// Spawn a new Coroutine, and return a handle for it.
    pub fn spawn<F>(self, f: F) -> Handle
            where F: FnOnce() + Send + 'static {
        Coroutine::spawn_opts(f, self.opts)
    }
}

/// Spawn a new Coroutine
pub fn spawn<F>(f: F) -> Handle
        where F: FnOnce() + Send + 'static {
    Builder::new().spawn(f)
}

/// Get the current Coroutine
pub fn current() -> HandleGuard {
    Coroutine::current()
}

/// Yield the current Coroutine
pub fn sched() {
    Coroutine::sched()
}

#[cfg(test)]
mod test {
    use std::sync::mpsc::channel;

    use super::Coroutine;
    use super::Builder;

    #[test]
    fn test_coroutine_basic() {
        let (tx, rx) = channel();
        Coroutine::spawn(move|| {
            tx.send(1).unwrap();
        }).resume().unwrap();

        assert_eq!(rx.recv().unwrap(), 1);
    }

    #[test]
    fn test_coroutine_yield() {
        let (tx, rx) = channel();
        let coro = Coroutine::spawn(move|| {
            tx.send(1).unwrap();

            Coroutine::sched();

            tx.send(2).unwrap();
        }).resume().unwrap();
        assert_eq!(rx.recv().unwrap(), 1);
        assert!(rx.try_recv().is_err());

        coro.resume().unwrap();

        assert_eq!(rx.recv().unwrap(), 2);
    }

    #[test]
    fn test_coroutine_spawn_inside() {
        let (tx, rx) = channel();
        Coroutine::spawn(move|| {
            tx.send(1).unwrap();

            Coroutine::spawn(move|| {
                tx.send(2).unwrap();
            }).join().unwrap();

        }).join().unwrap();;

        assert_eq!(rx.recv().unwrap(), 1);
        assert_eq!(rx.recv().unwrap(), 2);
    }

    #[test]
    fn test_coroutine_panic() {
        let coro = Coroutine::spawn(move|| {
            panic!("Panic inside a coroutine!!");
        });
        assert!(coro.join().is_err());
    }

    #[test]
    fn test_coroutine_child_panic() {
        Coroutine::spawn(move|| {
            let _ = Coroutine::spawn(move|| {
                panic!("Panic inside a coroutine's child!!");
            }).join();
        }).join().unwrap();
    }

    #[test]
    fn test_coroutine_resume_after_finished() {
        let mut coro = Coroutine::spawn(move|| {});

        // It is already finished, but we try to resume it
        // Idealy it would come back immediately
        coro = coro.resume().unwrap();

        // Again?
        assert!(coro.resume().is_ok());
    }

    #[test]
    fn test_coroutine_resume_itself() {
        let coro = Coroutine::spawn(move|| {
            // Resume itself
            Coroutine::current().with(|me| {
                me.resume().unwrap()
            });
        });

        assert!(coro.resume().is_ok());
    }

    #[test]
    fn test_coroutine_yield_in_main() {
        Coroutine::sched();
    }

    #[test]
    fn test_builder_basic() {
        let (tx, rx) = channel();
        Builder::new().name("Test builder".to_string()).spawn(move|| {
            tx.send(1).unwrap();
        }).join().unwrap();
        assert_eq!(rx.recv().unwrap(), 1);
    }
}

#[cfg(test)]
mod bench {
    use std::sync::mpsc::channel;

    use test::Bencher;

    use super::Coroutine;

    #[bench]
    fn bench_coroutine_spawning_with_recycle(b: &mut Bencher) {
        b.iter(|| {
            let _ = Coroutine::spawn(move|| {}).resume();
        });
    }

    #[bench]
    fn bench_normal_counting(b: &mut Bencher) {
        b.iter(|| {
            const MAX_NUMBER: usize = 100;

            let (tx, rx) = channel();

            let mut result = 0;
            for _ in 0..MAX_NUMBER {
                tx.send(1).unwrap();
                result += rx.recv().unwrap();
            }
            assert_eq!(result, MAX_NUMBER);
        });
    }

    #[bench]
    fn bench_coroutine_counting(b: &mut Bencher) {
        b.iter(|| {
            const MAX_NUMBER: usize = 100;
            let (tx, rx) = channel();

            let mut coro = Coroutine::spawn(move|| {
                for _ in 0..MAX_NUMBER {
                    tx.send(1).unwrap();
                    Coroutine::sched();
                }
            }).resume().unwrap();;

            let mut result = 0;
            for n in rx.iter() {
                coro = coro.resume().unwrap();
                result += n;
            }
            assert_eq!(result, MAX_NUMBER);
        });
    }
}
<commit_msg>Printout panic messages<commit_after>// Copyright 2013 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.

// Coroutines represent nothing more than a context and a stack
// segment.

use std::default::Default;
use std::rt::util::min_stack;
use thunk::Thunk;
use std::mem::{transmute, transmute_copy};
use std::rt::unwind::try;
use std::any::Any;
use std::cell::UnsafeCell;
use std::ops::DerefMut;
use std::ptr;

use context::Context;
use stack::{StackPool, Stack};

#[derive(Debug, Copy)]
pub enum State {
    Suspended,
    Running,
    Finished,
    Panicked,
}

pub type ResumeResult<T> = Result<T, Box<Any + Send>>;

/// Coroutine spawn options
#[derive(Debug)]
pub struct Options {
    pub stack_size: usize,
    pub name: Option<String>,
}

impl Default for Options {
    fn default() -> Options {
        Options {
            stack_size: min_stack(),
            name: None,
        }
    }
}

/// Handle of a Coroutine
#[derive(Debug)]
pub struct Handle(Box<Coroutine>);

impl Handle {

    #[inline]
    pub fn state(&self) -> State {
        self.0.state()
    }

    pub fn resume(mut self) -> ResumeResult<Handle> {
        match self.state() {
            State::Finished | State::Running => return Ok(self),
            State::Panicked => panic!("Tried to resume a panicked coroutine"),
            _ => {}
        }

        let result = UnsafeCell::new(None);
        COROUTINE_ENVIRONMENT.with(|env| {
            let env: &mut Environment = unsafe { transmute(env.get()) };

            // Move out, keep this reference
            // It may not be the only reference to the Coroutine
            //
            let mut from_coro = env.current_running.take().unwrap();

            // Save state
            self.0.state = State::Running;
            self.0.parent = from_coro.0.deref_mut();
            from_coro.0.state = State::Suspended;

            // Move inside the Environment
            env.current_running = Some(self);

            Context::swap(&mut from_coro.0.saved_context, &env.current_running.as_ref().unwrap().0.saved_context);

            // Move out here
            self = env.current_running.take().unwrap();
            env.current_running = Some(from_coro);

            let result: &mut Option<_> = unsafe { transmute(result.get()) };
            match env.running_state.take() {
                Some(err) => {
                    *result = Some(Err(err));
                },
                None => {
                    *result = Some(Ok(self))
                }
            }
        });

        unsafe { result.into_inner().unwrap() }
    }

    #[inline]
    pub fn join(self) -> ResumeResult<Handle> {
        let mut coro = self;
        loop {
            match coro.state() {
                State::Suspended => coro = try!(coro.resume()),
                _ => break,
            }
        }
        Ok(coro)
    }

    #[inline]
    pub fn name(&self) -> Option<&str> {
        self.0.name.as_ref().map(|s| &**s)
    }
}

/// A coroutine is nothing more than a (register context, stack) pair.
#[allow(raw_pointer_derive)]
#[derive(Debug)]
pub struct Coroutine {
    /// The segment of stack on which the task is currently running or
    /// if the task is blocked, on which the task will resume
    /// execution.
    current_stack_segment: Option<Stack>,

    /// Always valid if the task is alive and not running.
    saved_context: Context,

    /// Parent coroutine, will always be valid
    parent: *mut Coroutine,

    /// State
    state: State,

    /// Name
    name: Option<String>,
}

unsafe impl Send for Coroutine {}
unsafe impl Sync for Coroutine {}

/// Destroy coroutine and try to reuse std::stack segment.
impl Drop for Coroutine {
    fn drop(&mut self) {
        match self.current_stack_segment.take() {
            Some(stack) => {
                COROUTINE_ENVIRONMENT.with(|env| {
                    let env: &mut Environment = unsafe { transmute(env.get()) };
                    env.stack_pool.give_stack(stack);
                });
            },
            None => {}
        }
    }
}

/// Initialization function for make context
extern "C" fn coroutine_initialize(_: usize, f: *mut ()) -> ! {
    let func: Box<Thunk> = unsafe { transmute(f) };

    let ret = unsafe { try(move|| func.invoke(())) };

    COROUTINE_ENVIRONMENT.with(move|env| {
        let env: &mut Environment = unsafe { transmute(env.get()) };

        match ret {
            Ok(..) => {
                env.running_state = None;
                env.current_running.as_mut().unwrap().0.state = State::Finished;
            }
            Err(err) => {
                env.current_running.as_mut().unwrap().0.state = State::Panicked;

                {
                    let msg = match err.downcast_ref::<&'static str>() {
                        Some(s) => *s,
                        None => match err.downcast_ref::<String>() {
                            Some(s) => &s[..],
                            None => "Box<Any>",
                        }
                    }.to_string();
                    current().with(move|cur| {
                        {
                            let name = cur.name().unwrap_or("<unnamed>");
                            println!("Coroutine '{}' panicked at '{}'", name, msg);
                        }
                        cur
                    });
                }

                env.running_state = Some(err);
            }
        }
    });

    loop {
        Coroutine::sched();
    }
}

impl Coroutine {
    fn empty() -> Handle {
        Handle(box Coroutine {
            current_stack_segment: None,
            saved_context: Context::empty(),
            parent: ptr::null_mut(),
            state: State::Running,
            name: None,
        })
    }

    fn with_name(name: &str) -> Handle {
        Handle(box Coroutine {
            current_stack_segment: None,
            saved_context: Context::empty(),
            parent: ptr::null_mut(),
            state: State::Running,
            name: Some(name.to_string()),
        })
    }

    pub fn spawn_opts<F>(f: F, opts: Options) -> Handle
            where F: FnOnce() + Send + 'static {

        let coro = UnsafeCell::new(Coroutine::empty());
        COROUTINE_ENVIRONMENT.with(|env| {
            unsafe {
                let env: &mut Environment = transmute(env.get());

                let mut stack = env.stack_pool.take_stack(opts.stack_size);

                let ctx = Context::new(coroutine_initialize,
                                   0,
                                   f,
                                   &mut stack);

                let coro: &mut Handle = transmute(coro.get());
                coro.0.saved_context = ctx;
                coro.0.current_stack_segment = Some(stack);
                coro.0.state = State::Suspended;
            }
        });

        let mut coro = unsafe { coro.into_inner() };
        coro.0.name = opts.name;
        coro
    }

    /// Spawn a coroutine with default options
    pub fn spawn<F>(f: F) -> Handle
            where F: FnOnce() + Send + 'static {
        Coroutine::spawn_opts(f, Default::default())
    }

    pub fn sched() {
        COROUTINE_ENVIRONMENT.with(|env| {
            let env: &mut Environment = unsafe { transmute(env.get()) };

            // Move out
            let mut from_coro = env.current_running.as_mut().unwrap();

            match from_coro.state() {
                State::Finished | State::Panicked => {},
                _ => from_coro.0.state = State::Suspended,
            }

            let to_coro: &mut Coroutine = unsafe { transmute_copy(&from_coro.0.parent) };

            Context::swap(&mut from_coro.0.saved_context, &to_coro.saved_context);
        });
    }

    pub fn current() -> HandleGuard {
        HandleGuard
    }

    pub fn state(&self) -> State {
        self.state
    }
}

/// HandleGuard. With provide a `with` method for accessing the current running Coroutine
pub struct HandleGuard;

impl HandleGuard {
    /// Get the current running Coroutine. You have to return it back!
    pub fn with<F>(&self, f: F)
            where F: FnOnce(Handle) -> Handle + Send + 'static {
        COROUTINE_ENVIRONMENT.with(|env| {
            let env: &mut Environment = unsafe { transmute(env.get()) };
            env.current_running = Some(f(env.current_running.take().unwrap()));
        });
    }
}

thread_local!(static COROUTINE_ENVIRONMENT: UnsafeCell<Environment> = UnsafeCell::new(Environment::new()));

/// Coroutine managing environment
#[allow(raw_pointer_derive)]
#[derive(Debug)]
struct Environment {
    stack_pool: StackPool,
    current_running: Option<Handle>,

    running_state: Option<Box<Any + Send>>,
}

impl Environment {
    /// Initialize a new environment
    fn new() -> Environment {
        let mut coro = Coroutine::with_name("<Environment Root Coroutine>");
        coro.0.parent = coro.0.deref_mut(); // Pointing to itself

        Environment {
            stack_pool: StackPool::new(),
            current_running: Some(coro),

            running_state: None,
        }
    }
}

/// Coroutine configuration. Provides detailed control over the properties and behavior of new Coroutines.
pub struct Builder {
    opts: Options,
}

impl Builder {
    /// Generate the base configuration for spawning a Coroutine, from which configuration methods can be chained.
    pub fn new() -> Builder {
        Builder {
            opts: Default::default(),
        }
    }

    /// Name the Coroutine-to-be. Currently the name is used for identification only in panic messages.
    pub fn name(mut self, name: String) -> Builder {
        self.opts.name = Some(name);
        self
    }

    /// Set the size of the stack for the new Coroutine.
    pub fn stack_size(mut self, size: usize) -> Builder {
        self.opts.stack_size = size;
        self
    }

    /// Spawn a new Coroutine, and return a handle for it.
    pub fn spawn<F>(self, f: F) -> Handle
            where F: FnOnce() + Send + 'static {
        Coroutine::spawn_opts(f, self.opts)
    }
}

/// Spawn a new Coroutine
pub fn spawn<F>(f: F) -> Handle
        where F: FnOnce() + Send + 'static {
    Builder::new().spawn(f)
}

/// Get the current Coroutine
pub fn current() -> HandleGuard {
    Coroutine::current()
}

/// Yield the current Coroutine
pub fn sched() {
    Coroutine::sched()
}

#[cfg(test)]
mod test {
    use std::sync::mpsc::channel;

    use super::Coroutine;
    use super::Builder;

    #[test]
    fn test_coroutine_basic() {
        let (tx, rx) = channel();
        Coroutine::spawn(move|| {
            tx.send(1).unwrap();
        }).resume().unwrap();

        assert_eq!(rx.recv().unwrap(), 1);
    }

    #[test]
    fn test_coroutine_yield() {
        let (tx, rx) = channel();
        let coro = Coroutine::spawn(move|| {
            tx.send(1).unwrap();

            Coroutine::sched();

            tx.send(2).unwrap();
        }).resume().unwrap();
        assert_eq!(rx.recv().unwrap(), 1);
        assert!(rx.try_recv().is_err());

        coro.resume().unwrap();

        assert_eq!(rx.recv().unwrap(), 2);
    }

    #[test]
    fn test_coroutine_spawn_inside() {
        let (tx, rx) = channel();
        Coroutine::spawn(move|| {
            tx.send(1).unwrap();

            Coroutine::spawn(move|| {
                tx.send(2).unwrap();
            }).join().unwrap();

        }).join().unwrap();;

        assert_eq!(rx.recv().unwrap(), 1);
        assert_eq!(rx.recv().unwrap(), 2);
    }

    #[test]
    fn test_coroutine_panic() {
        let coro = Coroutine::spawn(move|| {
            panic!("Panic inside a coroutine!!");
        });
        assert!(coro.join().is_err());
    }

    #[test]
    fn test_coroutine_child_panic() {
        Coroutine::spawn(move|| {
            let _ = Coroutine::spawn(move|| {
                panic!("Panic inside a coroutine's child!!");
            }).join();
        }).join().unwrap();
    }

    #[test]
    fn test_coroutine_resume_after_finished() {
        let mut coro = Coroutine::spawn(move|| {});

        // It is already finished, but we try to resume it
        // Idealy it would come back immediately
        coro = coro.resume().unwrap();

        // Again?
        assert!(coro.resume().is_ok());
    }

    #[test]
    fn test_coroutine_resume_itself() {
        let coro = Coroutine::spawn(move|| {
            // Resume itself
            Coroutine::current().with(|me| {
                me.resume().unwrap()
            });
        });

        assert!(coro.resume().is_ok());
    }

    #[test]
    fn test_coroutine_yield_in_main() {
        Coroutine::sched();
    }

    #[test]
    fn test_builder_basic() {
        let (tx, rx) = channel();
        Builder::new().name("Test builder".to_string()).spawn(move|| {
            tx.send(1).unwrap();
        }).join().unwrap();
        assert_eq!(rx.recv().unwrap(), 1);
    }
}

#[cfg(test)]
mod bench {
    use std::sync::mpsc::channel;

    use test::Bencher;

    use super::Coroutine;

    #[bench]
    fn bench_coroutine_spawning_with_recycle(b: &mut Bencher) {
        b.iter(|| {
            let _ = Coroutine::spawn(move|| {}).resume();
        });
    }

    #[bench]
    fn bench_normal_counting(b: &mut Bencher) {
        b.iter(|| {
            const MAX_NUMBER: usize = 100;

            let (tx, rx) = channel();

            let mut result = 0;
            for _ in 0..MAX_NUMBER {
                tx.send(1).unwrap();
                result += rx.recv().unwrap();
            }
            assert_eq!(result, MAX_NUMBER);
        });
    }

    #[bench]
    fn bench_coroutine_counting(b: &mut Bencher) {
        b.iter(|| {
            const MAX_NUMBER: usize = 100;
            let (tx, rx) = channel();

            let mut coro = Coroutine::spawn(move|| {
                for _ in 0..MAX_NUMBER {
                    tx.send(1).unwrap();
                    Coroutine::sched();
                }
            }).resume().unwrap();;

            let mut result = 0;
            for n in rx.iter() {
                coro = coro.resume().unwrap();
                result += n;
            }
            assert_eq!(result, MAX_NUMBER);
        });
    }
}
<|endoftext|>


<commit_before>#![allow(
    clippy::cognitive_complexity,
    clippy::large_enum_variant,
    clippy::needless_doctest_main
)]
#![warn(
    missing_debug_implementations,
    missing_docs,
    rust_2018_idioms,
    unreachable_pub
)]
#![cfg_attr(docsrs, deny(broken_intra_doc_links))]
#![doc(test(
    no_crate_inject,
    attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
))]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(docsrs, deny(broken_intra_doc_links))]
#![doc(test(
    no_crate_inject,
    attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
))]
#![cfg_attr(docsrs, feature(doc_cfg))]

//! Stream utilities for Tokio.
//!
//! A `Stream` is an asynchronous sequence of values. It can be thought of as
//! an asynchronous version of the standard library's `Iterator` trait.
//!
//! This crate provides helpers to work with them. For examples of usage and a more in-depth
//! description of streams you can also refer to the [streams
//! tutorial](https://tokio.rs/tokio/tutorial/streams) on the tokio website.
//!
//! # Iterating over a Stream
//!
//! Due to similarities with the standard library's `Iterator` trait, some new
//! users may assume that they can use `for in` syntax to iterate over a
//! `Stream`, but this is unfortunately not possible. Instead, you can use a
//! `while let` loop as follows:
//!
//! ```rust
//! use tokio_stream::{self as stream, StreamExt};
//!
//! #[tokio::main]
//! async fn main() {
//!     let mut stream = stream::iter(vec![0, 1, 2]);
//!
//!     while let Some(value) = stream.next().await {
//!         println!("Got {}", value);
//!     }
//! }
//! ```
//!
//! # Returning a Stream from a function
//!
//! A common way to stream values from a function is to pass in the sender
//! half of a channel and use the receiver as the stream. This requires awaiting
//! both futures to ensure progress is made. Another alternative is the
//! [async-stream] crate, which contains macros that provide a `yield` keyword
//! and allow you to return an `impl Stream`.
//!
//! [async-stream]: https://docs.rs/async-stream
//!
//! # Conversion to and from AsyncRead/AsyncWrite
//!
//! It is often desirable to convert a `Stream` into an [`AsyncRead`],
//! especially when dealing with plaintext formats streamed over the network.
//! The opposite conversion from an [`AsyncRead`] into a `Stream` is also
//! another commonly required feature. To enable these conversions,
//! [`tokio-util`] provides the [`StreamReader`] and [`ReaderStream`]
//! types when the io feature is enabled.
//!
//! [`tokio-util`]: https://docs.rs/tokio-util/0.4/tokio_util/codec/index.html
//! [`tokio::io`]: https://docs.rs/tokio/1.0/tokio/io/index.html
//! [`AsyncRead`]: https://docs.rs/tokio/1.0/tokio/io/trait.AsyncRead.html
//! [`AsyncWrite`]: https://docs.rs/tokio/1.0/tokio/io/trait.AsyncWrite.html
//! [`ReaderStream`]: https://docs.rs/tokio-util/0.4/tokio_util/io/struct.ReaderStream.html
//! [`StreamReader`]: https://docs.rs/tokio-util/0.4/tokio_util/io/struct.StreamReader.html

#[macro_use]
mod macros;

pub mod wrappers;

mod stream_ext;
pub use stream_ext::{collect::FromStream, StreamExt};

mod empty;
pub use empty::{empty, Empty};

mod iter;
pub use iter::{iter, Iter};

mod once;
pub use once::{once, Once};

mod pending;
pub use pending::{pending, Pending};

mod stream_map;
pub use stream_map::StreamMap;

#[doc(no_inline)]
pub use futures_core::Stream;
<commit_msg>stream: remove duplicate doc_cfg declaration (#3561)<commit_after>#![allow(
    clippy::cognitive_complexity,
    clippy::large_enum_variant,
    clippy::needless_doctest_main
)]
#![warn(
    missing_debug_implementations,
    missing_docs,
    rust_2018_idioms,
    unreachable_pub
)]
#![cfg_attr(docsrs, deny(broken_intra_doc_links))]
#![doc(test(
    no_crate_inject,
    attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
))]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(docsrs, deny(broken_intra_doc_links))]
#![doc(test(
    no_crate_inject,
    attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
))]

//! Stream utilities for Tokio.
//!
//! A `Stream` is an asynchronous sequence of values. It can be thought of as
//! an asynchronous version of the standard library's `Iterator` trait.
//!
//! This crate provides helpers to work with them. For examples of usage and a more in-depth
//! description of streams you can also refer to the [streams
//! tutorial](https://tokio.rs/tokio/tutorial/streams) on the tokio website.
//!
//! # Iterating over a Stream
//!
//! Due to similarities with the standard library's `Iterator` trait, some new
//! users may assume that they can use `for in` syntax to iterate over a
//! `Stream`, but this is unfortunately not possible. Instead, you can use a
//! `while let` loop as follows:
//!
//! ```rust
//! use tokio_stream::{self as stream, StreamExt};
//!
//! #[tokio::main]
//! async fn main() {
//!     let mut stream = stream::iter(vec![0, 1, 2]);
//!
//!     while let Some(value) = stream.next().await {
//!         println!("Got {}", value);
//!     }
//! }
//! ```
//!
//! # Returning a Stream from a function
//!
//! A common way to stream values from a function is to pass in the sender
//! half of a channel and use the receiver as the stream. This requires awaiting
//! both futures to ensure progress is made. Another alternative is the
//! [async-stream] crate, which contains macros that provide a `yield` keyword
//! and allow you to return an `impl Stream`.
//!
//! [async-stream]: https://docs.rs/async-stream
//!
//! # Conversion to and from AsyncRead/AsyncWrite
//!
//! It is often desirable to convert a `Stream` into an [`AsyncRead`],
//! especially when dealing with plaintext formats streamed over the network.
//! The opposite conversion from an [`AsyncRead`] into a `Stream` is also
//! another commonly required feature. To enable these conversions,
//! [`tokio-util`] provides the [`StreamReader`] and [`ReaderStream`]
//! types when the io feature is enabled.
//!
//! [`tokio-util`]: https://docs.rs/tokio-util/0.4/tokio_util/codec/index.html
//! [`tokio::io`]: https://docs.rs/tokio/1.0/tokio/io/index.html
//! [`AsyncRead`]: https://docs.rs/tokio/1.0/tokio/io/trait.AsyncRead.html
//! [`AsyncWrite`]: https://docs.rs/tokio/1.0/tokio/io/trait.AsyncWrite.html
//! [`ReaderStream`]: https://docs.rs/tokio-util/0.4/tokio_util/io/struct.ReaderStream.html
//! [`StreamReader`]: https://docs.rs/tokio-util/0.4/tokio_util/io/struct.StreamReader.html

#[macro_use]
mod macros;

pub mod wrappers;

mod stream_ext;
pub use stream_ext::{collect::FromStream, StreamExt};

mod empty;
pub use empty::{empty, Empty};

mod iter;
pub use iter::{iter, Iter};

mod once;
pub use once::{once, Once};

mod pending;
pub use pending::{pending, Pending};

mod stream_map;
pub use stream_map::StreamMap;

#[doc(no_inline)]
pub use futures_core::Stream;
<|endoftext|>


<commit_before>use std::fmt;
use std::error;

use parsers::ParseError;

#[derive(Debug, Clone, PartialEq)]
pub enum AttributeError {
    // parse error
    Parse (ParseError),

    // invalid value
    Value (String)
}

#[derive(Debug, Clone, PartialEq)]
pub struct NodeError {
    attr_name: &'static str,
    err:       AttributeError
}

impl NodeError {
    pub fn parse_error (attr_name: &'static str, error: ParseError) -> NodeError {
        NodeError {
            attr_name: attr_name,
            err: AttributeError::Parse (error)
        }
    }

    pub fn value_error (attr_name: &'static str, description: String) -> NodeError {
        NodeError {
            attr_name: attr_name,
            err: AttributeError::Value (description)
        }
    }

    pub fn attribute_error (attr_name: &'static str, error: AttributeError) -> NodeError {
        NodeError {
            attr_name: attr_name,
            err: error
        }
    }
}

impl error::Error for NodeError {
    fn description (&self) -> &str {
        match self.err {
            AttributeError::Parse (_) => &"parse error",
            AttributeError::Value (_) => &"invalid attribute value"
        }
    }
}

impl fmt::Display for NodeError {
    fn fmt (&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.err {
            AttributeError::Parse (ref n) => write! (f,
                                                     "error parsing value for attribute \"{}\": {}",
                                                     self.attr_name,
                                                     n.display),

            AttributeError::Value (ref s) => write! (f,
                                                     "invalid value for attribute \"{}\": {}",
                                                     self.attr_name,
                                                     s)
        }
    }
}

impl From<ParseError> for AttributeError {
    fn from (pe: ParseError) -> AttributeError {
        AttributeError::Parse (pe)
    }
}

pub fn is_parse_error<T> (r: &Result<T, AttributeError>) -> bool {
    match *r {
        Err (AttributeError::Parse (_)) => true,
        _ => false
    }
}

pub fn is_value_error<T> (r: &Result<T, AttributeError>) -> bool {
    match *r {
        Err (AttributeError::Value (_)) => true,
        _ => false
    }
}
<commit_msg>NodeError: use a String for the attr_name, not a &'static str<commit_after>use std::fmt;
use std::error;

use parsers::ParseError;

#[derive(Debug, Clone, PartialEq)]
pub enum AttributeError {
    // parse error
    Parse (ParseError),

    // invalid value
    Value (String)
}

#[derive(Debug, Clone, PartialEq)]
pub struct NodeError {
    attr_name: String,
    err:       AttributeError
}

impl NodeError {
    pub fn parse_error (attr_name: &str, error: ParseError) -> NodeError {
        NodeError {
            attr_name: attr_name.to_string (),
            err: AttributeError::Parse (error)
        }
    }

    pub fn value_error (attr_name: &str, description: String) -> NodeError {
        NodeError {
            attr_name: attr_name.to_string (),
            err: AttributeError::Value (description)
        }
    }

    pub fn attribute_error (attr_name: &str, error: AttributeError) -> NodeError {
        NodeError {
            attr_name: attr_name.to_string (),
            err: error
        }
    }
}

impl error::Error for NodeError {
    fn description (&self) -> &str {
        match self.err {
            AttributeError::Parse (_) => &"parse error",
            AttributeError::Value (_) => &"invalid attribute value"
        }
    }
}

impl fmt::Display for NodeError {
    fn fmt (&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.err {
            AttributeError::Parse (ref n) => write! (f,
                                                     "error parsing value for attribute \"{}\": {}",
                                                     self.attr_name,
                                                     n.display),

            AttributeError::Value (ref s) => write! (f,
                                                     "invalid value for attribute \"{}\": {}",
                                                     self.attr_name,
                                                     s)
        }
    }
}

impl From<ParseError> for AttributeError {
    fn from (pe: ParseError) -> AttributeError {
        AttributeError::Parse (pe)
    }
}

pub fn is_parse_error<T> (r: &Result<T, AttributeError>) -> bool {
    match *r {
        Err (AttributeError::Parse (_)) => true,
        _ => false
    }
}

pub fn is_value_error<T> (r: &Result<T, AttributeError>) -> bool {
    match *r {
        Err (AttributeError::Value (_)) => true,
        _ => false
    }
}
<|endoftext|>