<commit_before>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

use crate::spinwait::SpinWait;
use crate::thread_parker::{ThreadParker, ThreadParkerT, UnparkHandleT};
use core::{
    cell::Cell,
    mem, ptr,
    sync::atomic::{fence, AtomicUsize, Ordering},
};

struct ThreadData {
    parker: ThreadParker,

    // Linked list of threads in the queue. The queue is split into two parts:
    // the processed part and the unprocessed part. When new nodes are added to
    // the list, they only have the next pointer set, and queue_tail is null.
    //
    // Nodes are processed with the queue lock held, which consists of setting
    // the prev pointer for each node and setting the queue_tail pointer on the
    // first processed node of the list.
    //
    // This setup allows nodes to be added to the queue without a lock, while
    // still allowing O(1) removal of nodes from the processed part of the list.
    // The only cost is the O(n) processing, but this only needs to be done
    // once for each node, and therefore isn't too expensive.
    queue_tail: Cell<*const ThreadData>,
    prev: Cell<*const ThreadData>,
    next: Cell<*const ThreadData>,
}

impl ThreadData {
    #[inline]
    fn new() -> ThreadData {
        assert!(mem::align_of::<ThreadData>() > !QUEUE_MASK);
        ThreadData {
            parker: ThreadParker::new(),
            queue_tail: Cell::new(ptr::null()),
            prev: Cell::new(ptr::null()),
            next: Cell::new(ptr::null()),
        }
    }
}

// Invokes the given closure with a reference to the current thread `ThreadData`.
#[inline]
fn with_thread_data<T>(f: impl FnOnce(&ThreadData) -> T) -> T {
    let mut thread_data_ptr = ptr::null();
    // If ThreadData is expensive to construct, then we want to use a cached
    // version in thread-local storage if possible.
    if !ThreadParker::IS_CHEAP_TO_CONSTRUCT {
        thread_local!(static THREAD_DATA: ThreadData = ThreadData::new());
        if let Ok(tls_thread_data) = THREAD_DATA.try_with(|x| x as *const ThreadData) {
            thread_data_ptr = tls_thread_data;
        }
    }
    // Otherwise just create a ThreadData on the stack
    let mut thread_data_storage = None;
    if thread_data_ptr.is_null() {
        thread_data_ptr = thread_data_storage.get_or_insert_with(ThreadData::new);
    }

    f(unsafe { &*thread_data_ptr })
}

const LOCKED_BIT: usize = 1;
const QUEUE_LOCKED_BIT: usize = 2;
const QUEUE_MASK: usize = !3;

// Word-sized lock that is used to implement the parking_lot API. Since this
// can't use parking_lot, it instead manages its own queue of waiting threads.
pub struct WordLock {
    state: AtomicUsize,
}

impl WordLock {
    /// Returns a new, unlocked, WordLock.
    pub const fn new() -> Self {
        WordLock {
            state: AtomicUsize::new(0),
        }
    }

    #[inline]
    pub fn lock(&self) {
        if self
            .state
            .compare_exchange_weak(0, LOCKED_BIT, Ordering::Acquire, Ordering::Relaxed)
            .is_ok()
        {
            return;
        }
        self.lock_slow();
    }

    /// Must not be called on an already unlocked `WordLock`!
    #[inline]
    pub unsafe fn unlock(&self) {
        let state = self.state.fetch_sub(LOCKED_BIT, Ordering::Release);
        if state.is_queue_locked() || state.queue_head().is_null() {
            return;
        }
        self.unlock_slow();
    }

    #[cold]
    fn lock_slow(&self) {
        let mut spinwait = SpinWait::new();
        let mut state = self.state.load(Ordering::Relaxed);
        loop {
            // Grab the lock if it isn't locked, even if there is a queue on it
            if !state.is_locked() {
                match self.state.compare_exchange_weak(
                    state,
                    state | LOCKED_BIT,
                    Ordering::Acquire,
                    Ordering::Relaxed,
                ) {
                    Ok(_) => return,
                    Err(x) => state = x,
                }
                continue;
            }

            // If there is no queue, try spinning a few times
            if state.queue_head().is_null() && spinwait.spin() {
                state = self.state.load(Ordering::Relaxed);
                continue;
            }

            // Get our thread data and prepare it for parking
            state = with_thread_data(|thread_data| {
                // The pthread implementation is still unsafe, so we need to surround `prepare_park`
                // with `unsafe {}`.
                #[allow(unused_unsafe)]
                unsafe {
                    thread_data.parker.prepare_park();
                }

                // Add our thread to the front of the queue
                let queue_head = state.queue_head();
                if queue_head.is_null() {
                    thread_data.queue_tail.set(thread_data);
                    thread_data.prev.set(ptr::null());
                } else {
                    thread_data.queue_tail.set(ptr::null());
                    thread_data.prev.set(ptr::null());
                    thread_data.next.set(queue_head);
                }
                if let Err(x) = self.state.compare_exchange_weak(
                    state,
                    state.with_queue_head(thread_data),
                    Ordering::Release,
                    Ordering::Relaxed,
                ) {
                    return x;
                }

                // Sleep until we are woken up by an unlock
                // Ignoring unused unsafe, since it's only a few platforms where this is unsafe.
                #[allow(unused_unsafe)]
                unsafe {
                    thread_data.parker.park();
                }

                // Loop back and try locking again
                spinwait.reset();
                self.state.load(Ordering::Relaxed)
            });
        }
    }

    #[cold]
    fn unlock_slow(&self) {
        let mut state = self.state.load(Ordering::Relaxed);
        loop {
            // We just unlocked the WordLock. Just check if there is a thread
            // to wake up. If the queue is locked then another thread is already
            // taking care of waking up a thread.
            if state.is_queue_locked() || state.queue_head().is_null() {
                return;
            }

            // Try to grab the queue lock
            match self.state.compare_exchange_weak(
                state,
                state | QUEUE_LOCKED_BIT,
                Ordering::Acquire,
                Ordering::Relaxed,
            ) {
                Ok(_) => break,
                Err(x) => state = x,
            }
        }

        // Now we have the queue lock and the queue is non-empty
        'outer: loop {
            // First, we need to fill in the prev pointers for any newly added
            // threads. We do this until we reach a node that we previously
            // processed, which has a non-null queue_tail pointer.
            let queue_head = state.queue_head();
            let mut queue_tail;
            let mut current = queue_head;
            loop {
                queue_tail = unsafe { (*current).queue_tail.get() };
                if !queue_tail.is_null() {
                    break;
                }
                unsafe {
                    let next = (*current).next.get();
                    (*next).prev.set(current);
                    current = next;
                }
            }

            // Set queue_tail on the queue head to indicate that the whole list
            // has prev pointers set correctly.
            unsafe {
                (*queue_head).queue_tail.set(queue_tail);
            }

            // If the WordLock is locked, then there is no point waking up a
            // thread now. Instead we let the next unlocker take care of waking
            // up a thread.
            if state.is_locked() {
                match self.state.compare_exchange_weak(
                    state,
                    state & !QUEUE_LOCKED_BIT,
                    Ordering::Release,
                    Ordering::Relaxed,
                ) {
                    Ok(_) => return,
                    Err(x) => state = x,
                }

                // Need an acquire fence before reading the new queue
                fence(Ordering::Acquire);
                continue;
            }

            // Remove the last thread from the queue and unlock the queue
            let new_tail = unsafe { (*queue_tail).prev.get() };
            if new_tail.is_null() {
                loop {
                    match self.state.compare_exchange_weak(
                        state,
                        state & LOCKED_BIT,
                        Ordering::Release,
                        Ordering::Relaxed,
                    ) {
                        Ok(_) => break,
                        Err(x) => state = x,
                    }

                    // If the compare_exchange failed because a new thread was
                    // added to the queue then we need to re-scan the queue to
                    // find the previous element.
                    if state.queue_head().is_null() {
                        continue;
                    } else {
                        // Need an acquire fence before reading the new queue
                        fence(Ordering::Acquire);
                        continue 'outer;
                    }
                }
            } else {
                unsafe {
                    (*queue_head).queue_tail.set(new_tail);
                }
                self.state.fetch_and(!QUEUE_LOCKED_BIT, Ordering::Release);
            }

            // Finally, wake up the thread we removed from the queue. Note that
            // we don't need to worry about any races here since the thread is
            // guaranteed to be sleeping right now and we are the only one who
            // can wake it up.
            unsafe {
                (*queue_tail).parker.unpark_lock().unpark();
            }
            break;
        }
    }
}

trait LockState {
    fn is_locked(self) -> bool;
    fn is_queue_locked(self) -> bool;
    fn queue_head(self) -> *const ThreadData;
    fn with_queue_head(self, thread_data: *const ThreadData) -> Self;
}

impl LockState for usize {
    #[inline]
    fn is_locked(self) -> bool {
        self & LOCKED_BIT != 0
    }

    #[inline]
    fn is_queue_locked(self) -> bool {
        self & QUEUE_LOCKED_BIT != 0
    }

    #[inline]
    fn queue_head(self) -> *const ThreadData {
        (self & QUEUE_MASK) as *const ThreadData
    }

    #[inline]
    fn with_queue_head(self, thread_data: *const ThreadData) -> Self {
        (self & !QUEUE_MASK) | thread_data as *const _ as usize
    }
}
<commit_msg>Fix Ordering on WordLock (tsan detected)<commit_after>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

use crate::spinwait::SpinWait;
use crate::thread_parker::{ThreadParker, ThreadParkerT, UnparkHandleT};
use core::{
    cell::Cell,
    mem, ptr,
    sync::atomic::{fence, AtomicUsize, Ordering},
};

struct ThreadData {
    parker: ThreadParker,

    // Linked list of threads in the queue. The queue is split into two parts:
    // the processed part and the unprocessed part. When new nodes are added to
    // the list, they only have the next pointer set, and queue_tail is null.
    //
    // Nodes are processed with the queue lock held, which consists of setting
    // the prev pointer for each node and setting the queue_tail pointer on the
    // first processed node of the list.
    //
    // This setup allows nodes to be added to the queue without a lock, while
    // still allowing O(1) removal of nodes from the processed part of the list.
    // The only cost is the O(n) processing, but this only needs to be done
    // once for each node, and therefore isn't too expensive.
    queue_tail: Cell<*const ThreadData>,
    prev: Cell<*const ThreadData>,
    next: Cell<*const ThreadData>,
}

impl ThreadData {
    #[inline]
    fn new() -> ThreadData {
        assert!(mem::align_of::<ThreadData>() > !QUEUE_MASK);
        ThreadData {
            parker: ThreadParker::new(),
            queue_tail: Cell::new(ptr::null()),
            prev: Cell::new(ptr::null()),
            next: Cell::new(ptr::null()),
        }
    }
}

// Invokes the given closure with a reference to the current thread `ThreadData`.
#[inline]
fn with_thread_data<T>(f: impl FnOnce(&ThreadData) -> T) -> T {
    let mut thread_data_ptr = ptr::null();
    // If ThreadData is expensive to construct, then we want to use a cached
    // version in thread-local storage if possible.
    if !ThreadParker::IS_CHEAP_TO_CONSTRUCT {
        thread_local!(static THREAD_DATA: ThreadData = ThreadData::new());
        if let Ok(tls_thread_data) = THREAD_DATA.try_with(|x| x as *const ThreadData) {
            thread_data_ptr = tls_thread_data;
        }
    }
    // Otherwise just create a ThreadData on the stack
    let mut thread_data_storage = None;
    if thread_data_ptr.is_null() {
        thread_data_ptr = thread_data_storage.get_or_insert_with(ThreadData::new);
    }

    f(unsafe { &*thread_data_ptr })
}

const LOCKED_BIT: usize = 1;
const QUEUE_LOCKED_BIT: usize = 2;
const QUEUE_MASK: usize = !3;

// Word-sized lock that is used to implement the parking_lot API. Since this
// can't use parking_lot, it instead manages its own queue of waiting threads.
pub struct WordLock {
    state: AtomicUsize,
}

impl WordLock {
    /// Returns a new, unlocked, WordLock.
    pub const fn new() -> Self {
        WordLock {
            state: AtomicUsize::new(0),
        }
    }

    #[inline]
    pub fn lock(&self) {
        if self
            .state
            .compare_exchange_weak(0, LOCKED_BIT, Ordering::Acquire, Ordering::Relaxed)
            .is_ok()
        {
            return;
        }
        self.lock_slow();
    }

    /// Must not be called on an already unlocked `WordLock`!
    #[inline]
    pub unsafe fn unlock(&self) {
        let state = self.state.fetch_sub(LOCKED_BIT, Ordering::Release);
        if state.is_queue_locked() || state.queue_head().is_null() {
            return;
        }
        self.unlock_slow();
    }

    #[cold]
    fn lock_slow(&self) {
        let mut spinwait = SpinWait::new();
        let mut state = self.state.load(Ordering::Relaxed);
        loop {
            // Grab the lock if it isn't locked, even if there is a queue on it
            if !state.is_locked() {
                match self.state.compare_exchange_weak(
                    state,
                    state | LOCKED_BIT,
                    Ordering::Acquire,
                    Ordering::Relaxed,
                ) {
                    Ok(_) => return,
                    Err(x) => state = x,
                }
                continue;
            }

            // If there is no queue, try spinning a few times
            if state.queue_head().is_null() && spinwait.spin() {
                state = self.state.load(Ordering::Relaxed);
                continue;
            }

            // Get our thread data and prepare it for parking
            state = with_thread_data(|thread_data| {
                // The pthread implementation is still unsafe, so we need to surround `prepare_park`
                // with `unsafe {}`.
                #[allow(unused_unsafe)]
                unsafe {
                    thread_data.parker.prepare_park();
                }

                // Add our thread to the front of the queue
                let queue_head = state.queue_head();
                if queue_head.is_null() {
                    thread_data.queue_tail.set(thread_data);
                    thread_data.prev.set(ptr::null());
                } else {
                    thread_data.queue_tail.set(ptr::null());
                    thread_data.prev.set(ptr::null());
                    thread_data.next.set(queue_head);
                }
                if let Err(x) = self.state.compare_exchange_weak(
                    state,
                    state.with_queue_head(thread_data),
                    Ordering::AcqRel,
                    Ordering::Relaxed,
                ) {
                    return x;
                }

                // Sleep until we are woken up by an unlock
                // Ignoring unused unsafe, since it's only a few platforms where this is unsafe.
                #[allow(unused_unsafe)]
                unsafe {
                    thread_data.parker.park();
                }

                // Loop back and try locking again
                spinwait.reset();
                self.state.load(Ordering::Relaxed)
            });
        }
    }

    #[cold]
    fn unlock_slow(&self) {
        let mut state = self.state.load(Ordering::Relaxed);
        loop {
            // We just unlocked the WordLock. Just check if there is a thread
            // to wake up. If the queue is locked then another thread is already
            // taking care of waking up a thread.
            if state.is_queue_locked() || state.queue_head().is_null() {
                return;
            }

            // Try to grab the queue lock
            match self.state.compare_exchange_weak(
                state,
                state | QUEUE_LOCKED_BIT,
                Ordering::AcqRel,
                Ordering::Relaxed,
            ) {
                Ok(_) => break,
                Err(x) => state = x,
            }
        }

        // Now we have the queue lock and the queue is non-empty
        'outer: loop {
            // First, we need to fill in the prev pointers for any newly added
            // threads. We do this until we reach a node that we previously
            // processed, which has a non-null queue_tail pointer.
            let queue_head = state.queue_head();
            let mut queue_tail;
            let mut current = queue_head;
            loop {
                queue_tail = unsafe { (*current).queue_tail.get() };
                if !queue_tail.is_null() {
                    break;
                }
                unsafe {
                    let next = (*current).next.get();
                    (*next).prev.set(current);
                    current = next;
                }
            }

            // Set queue_tail on the queue head to indicate that the whole list
            // has prev pointers set correctly.
            unsafe {
                (*queue_head).queue_tail.set(queue_tail);
            }

            // If the WordLock is locked, then there is no point waking up a
            // thread now. Instead we let the next unlocker take care of waking
            // up a thread.
            if state.is_locked() {
                match self.state.compare_exchange_weak(
                    state,
                    state & !QUEUE_LOCKED_BIT,
                    Ordering::AcqRel,
                    Ordering::Relaxed,
                ) {
                    Ok(_) => return,
                    Err(x) => state = x,
                }

                // Need an acquire fence before reading the new queue
                fence(Ordering::Acquire);
                continue;
            }

            // Remove the last thread from the queue and unlock the queue
            let new_tail = unsafe { (*queue_tail).prev.get() };
            if new_tail.is_null() {
                loop {
                    match self.state.compare_exchange_weak(
                        state,
                        state & LOCKED_BIT,
                        Ordering::AcqRel,
                        Ordering::Relaxed,
                    ) {
                        Ok(_) => break,
                        Err(x) => state = x,
                    }

                    // If the compare_exchange failed because a new thread was
                    // added to the queue then we need to re-scan the queue to
                    // find the previous element.
                    if state.queue_head().is_null() {
                        continue;
                    } else {
                        // Need an acquire fence before reading the new queue
                        fence(Ordering::Acquire);
                        continue 'outer;
                    }
                }
            } else {
                unsafe {
                    (*queue_head).queue_tail.set(new_tail);
                }
                self.state.fetch_and(!QUEUE_LOCKED_BIT, Ordering::Release);
            }

            // Finally, wake up the thread we removed from the queue. Note that
            // we don't need to worry about any races here since the thread is
            // guaranteed to be sleeping right now and we are the only one who
            // can wake it up.
            unsafe {
                (*queue_tail).parker.unpark_lock().unpark();
            }
            break;
        }
    }
}

trait LockState {
    fn is_locked(self) -> bool;
    fn is_queue_locked(self) -> bool;
    fn queue_head(self) -> *const ThreadData;
    fn with_queue_head(self, thread_data: *const ThreadData) -> Self;
}

impl LockState for usize {
    #[inline]
    fn is_locked(self) -> bool {
        self & LOCKED_BIT != 0
    }

    #[inline]
    fn is_queue_locked(self) -> bool {
        self & QUEUE_LOCKED_BIT != 0
    }

    #[inline]
    fn queue_head(self) -> *const ThreadData {
        (self & QUEUE_MASK) as *const ThreadData
    }

    #[inline]
    fn with_queue_head(self, thread_data: *const ThreadData) -> Self {
        (self & !QUEUE_MASK) | thread_data as *const _ as usize
    }
}
<|endoftext|>


<commit_before>
//! Implements generic error type

use curl;
use git2;
use rustc_serialize;
use std::error::Error;
use std;
use url;

quick_error! {
    #[derive(Debug)]
    pub enum GGRError {
        Curl(err: curl::Error) {
            description(err.description())
            from()
        }
        General(err: String) {
            description(err)
            from()
        }
        Git2(err: git2::Error) {
            description(err.message())
            from()
        }
        JsonDecoder(err: rustc_serialize::json::DecoderError) {
            description(err.description())
            from()
        }
        StdIo(err: std::io::Error) {
            description(err.description())
            from()
        }
        Url(err: url::ParseError) {
            description(err.description())
            from()
        }
    }
}

/// General result type
pub type GGRResult<T> = Result<T, GGRError>;

<commit_msg>error: small: remove unused import<commit_after>
//! Implements generic error type

use curl;
use git2;
use rustc_serialize;
use std;
use url;

quick_error! {
    #[derive(Debug)]
    pub enum GGRError {
        Curl(err: curl::Error) {
            description(err.description())
            from()
        }
        General(err: String) {
            description(err)
            from()
        }
        Git2(err: git2::Error) {
            description(err.message())
            from()
        }
        JsonDecoder(err: rustc_serialize::json::DecoderError) {
            description(err.description())
            from()
        }
        StdIo(err: std::io::Error) {
            description(err.description())
            from()
        }
        Url(err: url::ParseError) {
            description(err.description())
            from()
        }
    }
}

/// General result type
pub type GGRResult<T> = Result<T, GGRError>;

<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Handle_a_signal
//
// Note that this solution only works on Unix.
#![feature(libc)]

extern crate libc;
extern crate time;

#[cfg(all(unix, not(test)))]
fn main()
{
    use libc::consts::os::posix88::SIGINT;
    use libc::funcs::posix01::signal;
    use std::old_io::timer::Timer;
    use std::mem;
    use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
    use std::time::duration::Duration;

    // The time between ticks of our counter.
    let duration = Duration::seconds(1) / 2;
    let mut timer = Timer::new().unwrap();
    // "SIGINT received" global variable.
    static mut GOT_SIGINT: AtomicBool = ATOMIC_BOOL_INIT;
    unsafe {
        // Initially, "SIGINT received" is false.
        GOT_SIGINT.store(false, Ordering::Release);
        // Interrupt handler that handles the SIGINT signal
        unsafe fn handle_sigint() {
            // It is dangerous to perform any system calls in interrupts, so just set the atomic
            // "SIGINT received" global to true when it arrives.
            GOT_SIGINT.store(true, Ordering::Release);
        }
        // Make handle_sigint the signal handler for SIGINT.
        signal::signal(SIGINT, mem::transmute(handle_sigint));
    }
    let periodic = timer.periodic(duration);
    // Get the start time...
    let start = time::precise_time_ns();
    // Integer counter
    let mut i = 0u32;
    // Every `duration`...
    for _ in periodic.iter() {
        // Break if SIGINT was handled
        if unsafe { GOT_SIGINT.load(Ordering::Acquire) } { break }
        // Otherwise, increment and display the integer and continue the loop.
        i += 1;
        println!("{}", i);
    }
    // Get the end time.
    let end = time::precise_time_ns();
    // Compute the difference
    let diff = Duration::nanoseconds((end - start) as i64);
    // Print the difference and exit
    println!("Program has run for {} seconds", diff);
}

#[cfg(not(unix))]
fn main()
{
    println!("Not supported on this platform");
}
<commit_msg>forgot warning in handle_a_signal<commit_after>// Implements http://rosettacode.org/wiki/Handle_a_signal
//
// Note that this solution only works on Unix.
#![allow(unused_features)]
#![feature(libc)]
#![feature(std_misc)]
#![feature(io)]

extern crate libc;
extern crate time;

#[cfg(all(unix, not(test)))]
fn main()
{
    use libc::consts::os::posix88::SIGINT;
    use libc::funcs::posix01::signal;
    use std::old_io::timer::Timer;
    use std::mem;
    use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
    use std::time::duration::Duration;

    // The time between ticks of our counter.
    let duration = Duration::seconds(1) / 2;
    let mut timer = Timer::new().unwrap();
    // "SIGINT received" global variable.
    static mut GOT_SIGINT: AtomicBool = ATOMIC_BOOL_INIT;
    unsafe {
        // Initially, "SIGINT received" is false.
        GOT_SIGINT.store(false, Ordering::Release);
        // Interrupt handler that handles the SIGINT signal
        unsafe fn handle_sigint() {
            // It is dangerous to perform any system calls in interrupts, so just set the atomic
            // "SIGINT received" global to true when it arrives.
            GOT_SIGINT.store(true, Ordering::Release);
        }
        // Make handle_sigint the signal handler for SIGINT.
        signal::signal(SIGINT, mem::transmute(handle_sigint));
    }
    let periodic = timer.periodic(duration);
    // Get the start time...
    let start = time::precise_time_ns();
    // Integer counter
    let mut i = 0u32;
    // Every `duration`...
    for _ in periodic.iter() {
        // Break if SIGINT was handled
        if unsafe { GOT_SIGINT.load(Ordering::Acquire) } { break }
        // Otherwise, increment and display the integer and continue the loop.
        i += 1;
        println!("{}", i);
    }
    // Get the end time.
    let end = time::precise_time_ns();
    // Compute the difference
    let diff = Duration::nanoseconds((end - start) as i64);
    // Print the difference and exit
    println!("Program has run for {} seconds", diff);
}

#[cfg(not(unix))]
fn main()
{
    println!("Not supported on this platform");
}
<|endoftext|>


<commit_before>use types::{BeaconStateError as Error, *};

/// Process slashings.
///
/// Spec v0.6.3
pub fn process_slashings<T: EthSpec>(
    state: &mut BeaconState<T>,
    current_total_balance: u64,
    spec: &ChainSpec,
) -> Result<(), Error> {
    let current_epoch = state.current_epoch();

    let total_at_start = state.get_slashed_balance(current_epoch + 1)?;
    let total_at_end = state.get_slashed_balance(current_epoch)?;
    let total_penalities = total_at_end - total_at_start;

    for (index, validator) in state.validator_registry.iter().enumerate() {
        let should_penalize = current_epoch.as_usize()
            == validator.withdrawable_epoch.as_usize() - T::LatestSlashedExitLength::to_usize() / 2;

        if validator.slashed && should_penalize {
            let effective_balance = state.get_effective_balance(index, spec)?;

            let penalty = std::cmp::max(
                effective_balance * std::cmp::min(total_penalities * 3, current_total_balance)
                    / current_total_balance,
                effective_balance / spec.min_slashing_penalty_quotient,
            );

            safe_sub_assign!(state.balances[index], penalty);
        }
    }

    Ok(())
}
<commit_msg>process slashings: fix subtraction overflow<commit_after>use types::{BeaconStateError as Error, *};

/// Process slashings.
///
/// Spec v0.6.3
pub fn process_slashings<T: EthSpec>(
    state: &mut BeaconState<T>,
    current_total_balance: u64,
    spec: &ChainSpec,
) -> Result<(), Error> {
    let current_epoch = state.current_epoch();

    let total_at_start = state.get_slashed_balance(current_epoch + 1)?;
    let total_at_end = state.get_slashed_balance(current_epoch)?;
    let total_penalities = total_at_end - total_at_start;

    for (index, validator) in state.validator_registry.iter().enumerate() {
        let should_penalize = current_epoch.as_usize() + T::LatestSlashedExitLength::to_usize() / 2
            == validator.withdrawable_epoch.as_usize();

        if validator.slashed && should_penalize {
            let effective_balance = state.get_effective_balance(index, spec)?;

            let penalty = std::cmp::max(
                effective_balance * std::cmp::min(total_penalities * 3, current_total_balance)
                    / current_total_balance,
                effective_balance / spec.min_slashing_penalty_quotient,
            );

            safe_sub_assign!(state.balances[index], penalty);
        }
    }

    Ok(())
}
<|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.

/*! Non-blocking access to stdin, stdout, and stderr.

This module provides bindings to the local event loop's TTY interface, using it
to offer synchronous but non-blocking versions of stdio. These handles can be
inspected for information about terminal dimensions or for related information
about the stream or terminal to which it is attached.

# Example

```rust
# #![allow(unused_must_use)]
use std::io;

let mut out = io::stdout();
out.write(b"Hello, world!");
```

*/

use failure::local_stderr;
use fmt;
use io::{Reader, Writer, IoResult, IoError, OtherIoError,
         standard_error, EndOfFile, LineBufferedWriter, BufferedReader};
use iter::Iterator;
use kinds::Send;
use libc;
use option::{Option, Some, None};
use boxed::Box;
use result::{Ok, Err};
use rt;
use rt::local::Local;
use rt::task::Task;
use rt::rtio::{DontClose, IoFactory, LocalIo, RtioFileStream, RtioTTY};
use slice::ImmutableVector;
use str::StrSlice;
use uint;

// And so begins the tale of acquiring a uv handle to a stdio stream on all
// platforms in all situations. Our story begins by splitting the world into two
// categories, windows and unix. Then one day the creators of unix said let
// there be redirection! And henceforth there was redirection away from the
// console for standard I/O streams.
//
// After this day, the world split into four factions:
//
// 1. Unix with stdout on a terminal.
// 2. Unix with stdout redirected.
// 3. Windows with stdout on a terminal.
// 4. Windows with stdout redirected.
//
// Many years passed, and then one day the nation of libuv decided to unify this
// world. After months of toiling, uv created three ideas: TTY, Pipe, File.
// These three ideas propagated throughout the lands and the four great factions
// decided to settle among them.
//
// The groups of 1, 2, and 3 all worked very hard towards the idea of TTY. Upon
// doing so, they even enhanced themselves further then their Pipe/File
// brethren, becoming the dominant powers.
//
// The group of 4, however, decided to work independently. They abandoned the
// common TTY belief throughout, and even abandoned the fledgling Pipe belief.
// The members of the 4th faction decided to only align themselves with File.
//
// tl;dr; TTY works on everything but when windows stdout is redirected, in that
//        case pipe also doesn't work, but magically file does!
enum StdSource {
    TTY(Box<RtioTTY + Send>),
    File(Box<RtioFileStream + Send>),
}

fn src<T>(fd: libc::c_int, readable: bool, f: |StdSource| -> T) -> T {
    LocalIo::maybe_raise(|io| {
        Ok(match io.tty_open(fd, readable) {
            Ok(tty) => f(TTY(tty)),
            Err(_) => f(File(io.fs_from_raw_fd(fd, DontClose))),
        })
    }).map_err(IoError::from_rtio_error).unwrap()
}

local_data_key!(local_stdout: Box<Writer + Send>)

/// Creates a new non-blocking handle to the stdin of the current process.
///
/// The returned handled is buffered by default with a `BufferedReader`. If
/// buffered access is not desired, the `stdin_raw` function is provided to
/// provided unbuffered access to stdin.
///
/// Care should be taken when creating multiple handles to the stdin of a
/// process. Because this is a buffered reader by default, it's possible for
/// pending input to be unconsumed in one reader and unavailable to other
/// readers. It is recommended that only one handle at a time is created for the
/// stdin of a process.
///
/// See `stdout()` for more notes about this function.
pub fn stdin() -> BufferedReader<StdReader> {
    // The default buffer capacity is 64k, but apparently windows doesn't like
    // 64k reads on stdin. See #13304 for details, but the idea is that on
    // windows we use a slightly smaller buffer that's been seen to be
    // acceptable.
    if cfg!(windows) {
        BufferedReader::with_capacity(8 * 1024, stdin_raw())
    } else {
        BufferedReader::new(stdin_raw())
    }
}

/// Creates a new non-blocking handle to the stdin of the current process.
///
/// Unlike `stdin()`, the returned reader is *not* a buffered reader.
///
/// See `stdout()` for more notes about this function.
pub fn stdin_raw() -> StdReader {
    src(libc::STDIN_FILENO, true, |src| StdReader { inner: src })
}

/// Creates a line-buffered handle to the stdout of the current process.
///
/// Note that this is a fairly expensive operation in that at least one memory
/// allocation is performed. Additionally, this must be called from a runtime
/// task context because the stream returned will be a non-blocking object using
/// the local scheduler to perform the I/O.
///
/// Care should be taken when creating multiple handles to an output stream for
/// a single process. While usage is still safe, the output may be surprising if
/// no synchronization is performed to ensure a sane output.
pub fn stdout() -> LineBufferedWriter<StdWriter> {
    LineBufferedWriter::new(stdout_raw())
}

/// Creates an unbuffered handle to the stdout of the current process
///
/// See notes in `stdout()` for more information.
pub fn stdout_raw() -> StdWriter {
    src(libc::STDOUT_FILENO, false, |src| StdWriter { inner: src })
}

/// Creates a line-buffered handle to the stderr of the current process.
///
/// See `stdout()` for notes about this function.
pub fn stderr() -> LineBufferedWriter<StdWriter> {
    LineBufferedWriter::new(stderr_raw())
}

/// Creates an unbuffered handle to the stderr of the current process
///
/// See notes in `stdout()` for more information.
pub fn stderr_raw() -> StdWriter {
    src(libc::STDERR_FILENO, false, |src| StdWriter { inner: src })
}

/// Resets the task-local stdout handle to the specified writer
///
/// This will replace the current task's stdout handle, returning the old
/// handle. All future calls to `print` and friends will emit their output to
/// this specified handle.
///
/// Note that this does not need to be called for all new tasks; the default
/// output handle is to the process's stdout stream.
pub fn set_stdout(stdout: Box<Writer + Send>) -> Option<Box<Writer + Send>> {
    local_stdout.replace(Some(stdout)).and_then(|mut s| {
        let _ = s.flush();
        Some(s)
    })
}

/// Resets the task-local stderr handle to the specified writer
///
/// This will replace the current task's stderr handle, returning the old
/// handle. Currently, the stderr handle is used for printing failure messages
/// during task failure.
///
/// Note that this does not need to be called for all new tasks; the default
/// output handle is to the process's stderr stream.
pub fn set_stderr(stderr: Box<Writer + Send>) -> Option<Box<Writer + Send>> {
    local_stderr.replace(Some(stderr)).and_then(|mut s| {
        let _ = s.flush();
        Some(s)
    })
}

// Helper to access the local task's stdout handle
//
// Note that this is not a safe function to expose because you can create an
// aliased pointer very easily:
//
//  with_task_stdout(|io1| {
//      with_task_stdout(|io2| {
//          // io1 aliases io2
//      })
//  })
fn with_task_stdout(f: |&mut Writer| -> IoResult<()>) {
    let result = if Local::exists(None::<Task>) {
        let mut my_stdout = local_stdout.replace(None).unwrap_or_else(|| {
            box stdout() as Box<Writer + Send>
        });
        let result = f(my_stdout);
        local_stdout.replace(Some(my_stdout));
        result
    } else {
        let mut io = rt::Stdout;
        f(&mut io as &mut Writer)
    };
    match result {
        Ok(()) => {}
        Err(e) => fail!("failed printing to stdout: {}", e),
    }
}

/// Flushes the local task's stdout handle.
///
/// By default, this stream is a line-buffering stream, so flushing may be
/// necessary to ensure that all output is printed to the screen (if there are
/// no newlines printed).
///
/// Note that logging macros do not use this stream. Using the logging macros
/// will emit output to stderr, and while they are line buffered the log
/// messages are always terminated in a newline (no need to flush).
pub fn flush() {
    with_task_stdout(|io| io.flush())
}

/// Prints a string to the stdout of the current process. No newline is emitted
/// after the string is printed.
pub fn print(s: &str) {
    with_task_stdout(|io| io.write(s.as_bytes()))
}

/// Prints a string as a line. to the stdout of the current process. A literal
/// `\n` character is printed to the console after the string.
pub fn println(s: &str) {
    with_task_stdout(|io| {
        io.write(s.as_bytes()).and_then(|()| io.write([b'\n']))
    })
}

/// Similar to `print`, but takes a `fmt::Arguments` structure to be compatible
/// with the `format_args!` macro.
pub fn print_args(fmt: &fmt::Arguments) {
    with_task_stdout(|io| write!(io, "{}", fmt))
}

/// Similar to `println`, but takes a `fmt::Arguments` structure to be
/// compatible with the `format_args!` macro.
pub fn println_args(fmt: &fmt::Arguments) {
    with_task_stdout(|io| writeln!(io, "{}", fmt))
}

/// Representation of a reader of a standard input stream
pub struct StdReader {
    inner: StdSource
}

impl StdReader {
    /// Returns whether this stream is attached to a TTY instance or not.
    pub fn isatty(&self) -> bool {
        match self.inner {
            TTY(..) => true,
            File(..) => false,
        }
    }
}

impl Reader for StdReader {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        let ret = match self.inner {
            TTY(ref mut tty) => {
                // Flush the task-local stdout so that weird issues like a
                // print!'d prompt not being shown until after the user hits
                // enter.
                flush();
                tty.read(buf)
            },
            File(ref mut file) => file.read(buf).map(|i| i as uint),
        }.map_err(IoError::from_rtio_error);
        match ret {
            // When reading a piped stdin, libuv will return 0-length reads when
            // stdin reaches EOF. For pretty much all other streams it will
            // return an actual EOF error, but apparently for stdin it's a
            // little different. Hence, here we convert a 0 length read to an
            // end-of-file indicator so the caller knows to stop reading.
            Ok(0) => { Err(standard_error(EndOfFile)) }
            ret @ Ok(..) | ret @ Err(..) => ret,
        }
    }
}

/// Representation of a writer to a standard output stream
pub struct StdWriter {
    inner: StdSource
}

impl StdWriter {
    /// Gets the size of this output window, if possible. This is typically used
    /// when the writer is attached to something like a terminal, this is used
    /// to fetch the dimensions of the terminal.
    ///
    /// If successful, returns `Ok((width, height))`.
    ///
    /// # Error
    ///
    /// This function will return an error if the output stream is not actually
    /// connected to a TTY instance, or if querying the TTY instance fails.
    pub fn winsize(&mut self) -> IoResult<(int, int)> {
        match self.inner {
            TTY(ref mut tty) => {
                tty.get_winsize().map_err(IoError::from_rtio_error)
            }
            File(..) => {
                Err(IoError {
                    kind: OtherIoError,
                    desc: "stream is not a tty",
                    detail: None,
                })
            }
        }
    }

    /// Controls whether this output stream is a "raw stream" or simply a normal
    /// stream.
    ///
    /// # Error
    ///
    /// This function will return an error if the output stream is not actually
    /// connected to a TTY instance, or if querying the TTY instance fails.
    pub fn set_raw(&mut self, raw: bool) -> IoResult<()> {
        match self.inner {
            TTY(ref mut tty) => {
                tty.set_raw(raw).map_err(IoError::from_rtio_error)
            }
            File(..) => {
                Err(IoError {
                    kind: OtherIoError,
                    desc: "stream is not a tty",
                    detail: None,
                })
            }
        }
    }

    /// Returns whether this stream is attached to a TTY instance or not.
    pub fn isatty(&self) -> bool {
        match self.inner {
            TTY(..) => true,
            File(..) => false,
        }
    }
}

impl Writer for StdWriter {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        // As with stdin on windows, stdout often can't handle writes of large
        // sizes. For an example, see #14940. For this reason, chunk the output
        // buffer on windows, but on unix we can just write the whole buffer all
        // at once.
        let max_size = if cfg!(windows) {64 * 1024} else {uint::MAX};
        for chunk in buf.chunks(max_size) {
            try!(match self.inner {
                TTY(ref mut tty) => tty.write(chunk),
                File(ref mut file) => file.write(chunk),
            }.map_err(IoError::from_rtio_error))
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    iotest!(fn smoke() {
        // Just make sure we can acquire handles
        stdin();
        stdout();
        stderr();
    })

    iotest!(fn capture_stdout() {
        use io::{ChanReader, ChanWriter};

        let (tx, rx) = channel();
        let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
        spawn(proc() {
            set_stdout(box w);
            println!("hello!");
        });
        assert_eq!(r.read_to_string().unwrap(), "hello!\n".to_string());
    })

    iotest!(fn capture_stderr() {
        use realstd::comm::channel;
        use realstd::io::{Writer, ChanReader, ChanWriter, Reader};

        let (tx, rx) = channel();
        let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
        spawn(proc() {
            ::realstd::io::stdio::set_stderr(box w);
            fail!("my special message");
        });
        let s = r.read_to_string().unwrap();
        assert!(s.as_slice().contains("my special message"));
    })
}
<commit_msg>auto merge of #16220 : tshepang/rust/temp, r=steveklabnik<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.

/*! Non-blocking access to stdin, stdout, and stderr.

This module provides bindings to the local event loop's TTY interface, using it
to offer synchronous but non-blocking versions of stdio. These handles can be
inspected for information about terminal dimensions or for related information
about the stream or terminal to which it is attached.

# Example

```rust
# #![allow(unused_must_use)]
use std::io;

let mut out = io::stdout();
out.write(b"Hello, world!");
```

*/

use failure::local_stderr;
use fmt;
use io::{Reader, Writer, IoResult, IoError, OtherIoError,
         standard_error, EndOfFile, LineBufferedWriter, BufferedReader};
use iter::Iterator;
use kinds::Send;
use libc;
use option::{Option, Some, None};
use boxed::Box;
use result::{Ok, Err};
use rt;
use rt::local::Local;
use rt::task::Task;
use rt::rtio::{DontClose, IoFactory, LocalIo, RtioFileStream, RtioTTY};
use slice::ImmutableVector;
use str::StrSlice;
use uint;

// And so begins the tale of acquiring a uv handle to a stdio stream on all
// platforms in all situations. Our story begins by splitting the world into two
// categories, windows and unix. Then one day the creators of unix said let
// there be redirection! And henceforth there was redirection away from the
// console for standard I/O streams.
//
// After this day, the world split into four factions:
//
// 1. Unix with stdout on a terminal.
// 2. Unix with stdout redirected.
// 3. Windows with stdout on a terminal.
// 4. Windows with stdout redirected.
//
// Many years passed, and then one day the nation of libuv decided to unify this
// world. After months of toiling, uv created three ideas: TTY, Pipe, File.
// These three ideas propagated throughout the lands and the four great factions
// decided to settle among them.
//
// The groups of 1, 2, and 3 all worked very hard towards the idea of TTY. Upon
// doing so, they even enhanced themselves further then their Pipe/File
// brethren, becoming the dominant powers.
//
// The group of 4, however, decided to work independently. They abandoned the
// common TTY belief throughout, and even abandoned the fledgling Pipe belief.
// The members of the 4th faction decided to only align themselves with File.
//
// tl;dr; TTY works on everything but when windows stdout is redirected, in that
//        case pipe also doesn't work, but magically file does!
enum StdSource {
    TTY(Box<RtioTTY + Send>),
    File(Box<RtioFileStream + Send>),
}

fn src<T>(fd: libc::c_int, readable: bool, f: |StdSource| -> T) -> T {
    LocalIo::maybe_raise(|io| {
        Ok(match io.tty_open(fd, readable) {
            Ok(tty) => f(TTY(tty)),
            Err(_) => f(File(io.fs_from_raw_fd(fd, DontClose))),
        })
    }).map_err(IoError::from_rtio_error).unwrap()
}

local_data_key!(local_stdout: Box<Writer + Send>)

/// Creates a new non-blocking handle to the stdin of the current process.
///
/// The returned handled is buffered by default with a `BufferedReader`. If
/// buffered access is not desired, the `stdin_raw` function is provided to
/// provided unbuffered access to stdin.
///
/// Care should be taken when creating multiple handles to the stdin of a
/// process. Because this is a buffered reader by default, it's possible for
/// pending input to be unconsumed in one reader and unavailable to other
/// readers. It is recommended that only one handle at a time is created for the
/// stdin of a process.
///
/// See `stdout()` for more notes about this function.
pub fn stdin() -> BufferedReader<StdReader> {
    // The default buffer capacity is 64k, but apparently windows doesn't like
    // 64k reads on stdin. See #13304 for details, but the idea is that on
    // windows we use a slightly smaller buffer that's been seen to be
    // acceptable.
    if cfg!(windows) {
        BufferedReader::with_capacity(8 * 1024, stdin_raw())
    } else {
        BufferedReader::new(stdin_raw())
    }
}

/// Creates a new non-blocking handle to the stdin of the current process.
///
/// Unlike `stdin()`, the returned reader is *not* a buffered reader.
///
/// See `stdout()` for more notes about this function.
pub fn stdin_raw() -> StdReader {
    src(libc::STDIN_FILENO, true, |src| StdReader { inner: src })
}

/// Creates a line-buffered handle to the stdout of the current process.
///
/// Note that this is a fairly expensive operation in that at least one memory
/// allocation is performed. Additionally, this must be called from a runtime
/// task context because the stream returned will be a non-blocking object using
/// the local scheduler to perform the I/O.
///
/// Care should be taken when creating multiple handles to an output stream for
/// a single process. While usage is still safe, the output may be surprising if
/// no synchronization is performed to ensure a sane output.
pub fn stdout() -> LineBufferedWriter<StdWriter> {
    LineBufferedWriter::new(stdout_raw())
}

/// Creates an unbuffered handle to the stdout of the current process
///
/// See notes in `stdout()` for more information.
pub fn stdout_raw() -> StdWriter {
    src(libc::STDOUT_FILENO, false, |src| StdWriter { inner: src })
}

/// Creates a line-buffered handle to the stderr of the current process.
///
/// See `stdout()` for notes about this function.
pub fn stderr() -> LineBufferedWriter<StdWriter> {
    LineBufferedWriter::new(stderr_raw())
}

/// Creates an unbuffered handle to the stderr of the current process
///
/// See notes in `stdout()` for more information.
pub fn stderr_raw() -> StdWriter {
    src(libc::STDERR_FILENO, false, |src| StdWriter { inner: src })
}

/// Resets the task-local stdout handle to the specified writer
///
/// This will replace the current task's stdout handle, returning the old
/// handle. All future calls to `print` and friends will emit their output to
/// this specified handle.
///
/// Note that this does not need to be called for all new tasks; the default
/// output handle is to the process's stdout stream.
pub fn set_stdout(stdout: Box<Writer + Send>) -> Option<Box<Writer + Send>> {
    local_stdout.replace(Some(stdout)).and_then(|mut s| {
        let _ = s.flush();
        Some(s)
    })
}

/// Resets the task-local stderr handle to the specified writer
///
/// This will replace the current task's stderr handle, returning the old
/// handle. Currently, the stderr handle is used for printing failure messages
/// during task failure.
///
/// Note that this does not need to be called for all new tasks; the default
/// output handle is to the process's stderr stream.
pub fn set_stderr(stderr: Box<Writer + Send>) -> Option<Box<Writer + Send>> {
    local_stderr.replace(Some(stderr)).and_then(|mut s| {
        let _ = s.flush();
        Some(s)
    })
}

// Helper to access the local task's stdout handle
//
// Note that this is not a safe function to expose because you can create an
// aliased pointer very easily:
//
//  with_task_stdout(|io1| {
//      with_task_stdout(|io2| {
//          // io1 aliases io2
//      })
//  })
fn with_task_stdout(f: |&mut Writer| -> IoResult<()>) {
    let result = if Local::exists(None::<Task>) {
        let mut my_stdout = local_stdout.replace(None).unwrap_or_else(|| {
            box stdout() as Box<Writer + Send>
        });
        let result = f(my_stdout);
        local_stdout.replace(Some(my_stdout));
        result
    } else {
        let mut io = rt::Stdout;
        f(&mut io as &mut Writer)
    };
    match result {
        Ok(()) => {}
        Err(e) => fail!("failed printing to stdout: {}", e),
    }
}

/// Flushes the local task's stdout handle.
///
/// By default, this stream is a line-buffering stream, so flushing may be
/// necessary to ensure that all output is printed to the screen (if there are
/// no newlines printed).
///
/// Note that logging macros do not use this stream. Using the logging macros
/// will emit output to stderr, and while they are line buffered the log
/// messages are always terminated in a newline (no need to flush).
pub fn flush() {
    with_task_stdout(|io| io.flush())
}

/// Prints a string to the stdout of the current process. No newline is emitted
/// after the string is printed.
pub fn print(s: &str) {
    with_task_stdout(|io| io.write(s.as_bytes()))
}

/// Prints a string to the stdout of the current process. A literal
/// `\n` character is printed to the console after the string.
pub fn println(s: &str) {
    with_task_stdout(|io| {
        io.write(s.as_bytes()).and_then(|()| io.write([b'\n']))
    })
}

/// Similar to `print`, but takes a `fmt::Arguments` structure to be compatible
/// with the `format_args!` macro.
pub fn print_args(fmt: &fmt::Arguments) {
    with_task_stdout(|io| write!(io, "{}", fmt))
}

/// Similar to `println`, but takes a `fmt::Arguments` structure to be
/// compatible with the `format_args!` macro.
pub fn println_args(fmt: &fmt::Arguments) {
    with_task_stdout(|io| writeln!(io, "{}", fmt))
}

/// Representation of a reader of a standard input stream
pub struct StdReader {
    inner: StdSource
}

impl StdReader {
    /// Returns whether this stream is attached to a TTY instance or not.
    pub fn isatty(&self) -> bool {
        match self.inner {
            TTY(..) => true,
            File(..) => false,
        }
    }
}

impl Reader for StdReader {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        let ret = match self.inner {
            TTY(ref mut tty) => {
                // Flush the task-local stdout so that weird issues like a
                // print!'d prompt not being shown until after the user hits
                // enter.
                flush();
                tty.read(buf)
            },
            File(ref mut file) => file.read(buf).map(|i| i as uint),
        }.map_err(IoError::from_rtio_error);
        match ret {
            // When reading a piped stdin, libuv will return 0-length reads when
            // stdin reaches EOF. For pretty much all other streams it will
            // return an actual EOF error, but apparently for stdin it's a
            // little different. Hence, here we convert a 0 length read to an
            // end-of-file indicator so the caller knows to stop reading.
            Ok(0) => { Err(standard_error(EndOfFile)) }
            ret @ Ok(..) | ret @ Err(..) => ret,
        }
    }
}

/// Representation of a writer to a standard output stream
pub struct StdWriter {
    inner: StdSource
}

impl StdWriter {
    /// Gets the size of this output window, if possible. This is typically used
    /// when the writer is attached to something like a terminal, this is used
    /// to fetch the dimensions of the terminal.
    ///
    /// If successful, returns `Ok((width, height))`.
    ///
    /// # Error
    ///
    /// This function will return an error if the output stream is not actually
    /// connected to a TTY instance, or if querying the TTY instance fails.
    pub fn winsize(&mut self) -> IoResult<(int, int)> {
        match self.inner {
            TTY(ref mut tty) => {
                tty.get_winsize().map_err(IoError::from_rtio_error)
            }
            File(..) => {
                Err(IoError {
                    kind: OtherIoError,
                    desc: "stream is not a tty",
                    detail: None,
                })
            }
        }
    }

    /// Controls whether this output stream is a "raw stream" or simply a normal
    /// stream.
    ///
    /// # Error
    ///
    /// This function will return an error if the output stream is not actually
    /// connected to a TTY instance, or if querying the TTY instance fails.
    pub fn set_raw(&mut self, raw: bool) -> IoResult<()> {
        match self.inner {
            TTY(ref mut tty) => {
                tty.set_raw(raw).map_err(IoError::from_rtio_error)
            }
            File(..) => {
                Err(IoError {
                    kind: OtherIoError,
                    desc: "stream is not a tty",
                    detail: None,
                })
            }
        }
    }

    /// Returns whether this stream is attached to a TTY instance or not.
    pub fn isatty(&self) -> bool {
        match self.inner {
            TTY(..) => true,
            File(..) => false,
        }
    }
}

impl Writer for StdWriter {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        // As with stdin on windows, stdout often can't handle writes of large
        // sizes. For an example, see #14940. For this reason, chunk the output
        // buffer on windows, but on unix we can just write the whole buffer all
        // at once.
        let max_size = if cfg!(windows) {64 * 1024} else {uint::MAX};
        for chunk in buf.chunks(max_size) {
            try!(match self.inner {
                TTY(ref mut tty) => tty.write(chunk),
                File(ref mut file) => file.write(chunk),
            }.map_err(IoError::from_rtio_error))
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    iotest!(fn smoke() {
        // Just make sure we can acquire handles
        stdin();
        stdout();
        stderr();
    })

    iotest!(fn capture_stdout() {
        use io::{ChanReader, ChanWriter};

        let (tx, rx) = channel();
        let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
        spawn(proc() {
            set_stdout(box w);
            println!("hello!");
        });
        assert_eq!(r.read_to_string().unwrap(), "hello!\n".to_string());
    })

    iotest!(fn capture_stderr() {
        use realstd::comm::channel;
        use realstd::io::{Writer, ChanReader, ChanWriter, Reader};

        let (tx, rx) = channel();
        let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
        spawn(proc() {
            ::realstd::io::stdio::set_stderr(box w);
            fail!("my special message");
        });
        let s = r.read_to_string().unwrap();
        assert!(s.as_slice().contains("my special message"));
    })
}
<|endoftext|>


<commit_before>
extern crate sysfs_gpio;
extern crate sysfs_pwm;

use self::sysfs_gpio::{Direction, Pin};
use self::sysfs_pwm::{Pwm};
use ::std::error::Error;
use std::thread;
use std::time;

use super::{PinProxyContract,PwmProxyContract,DirectionProxied,ProxyError,ProxyResult};

pub struct PinProxy {
	pin : Pin,
}

impl PinProxyContract for PinProxy
{
	fn new(pin_num: u64) -> PinProxy {
		PinProxy{ pin: Pin::new(pin_num) }
	}

	fn export(&self) ->  ProxyResult<()>{
		match self.pin.export()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn unexport(&self) ->  ProxyResult<()> {
		match self.pin.unexport()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_value(&self, value: u8) ->  ProxyResult<()> {
		match self.pin.set_value(value)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_direction(&self, dir: DirectionProxied) ->  ProxyResult<()>{
		let dirmapped =  match dir {
										DirectionProxied::In =>  Direction::In,
										DirectionProxied::Out => Direction::Out,
										DirectionProxied::High => Direction::High,
										DirectionProxied::Low => Direction::Low,
									};
		match self.pin.set_direction(dirmapped)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}
}

pub struct PwmProxy {
	pwm : Pwm,
}

impl PwmProxyContract for PwmProxy
{
	fn new(chip: u32, number: u32) -> ProxyResult<PwmProxy>{

		match Pwm::new(chip, number) {
			Ok(pwm) => Ok(PwmProxy{ pwm: pwm}),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn export(&self) ->  ProxyResult<()>{
		match self.pwm.export()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn unexport(&self) ->  ProxyResult<()> {
		match self.pwm.unexport()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn enable(&self, enable: bool) -> ProxyResult<()>
	{
		match self.pwm.enable(enable)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{} caused by {}",result.description(),result.cause().unwrap());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_duty_cycle_ns(&self, duty_cycle_ns: u32) -> ProxyResult<()>
	{
		match self.pwm.set_duty_cycle_ns(duty_cycle_ns)
		{
			Ok(()) => {println!("setting dutycycle {}",duty_cycle_ns); Ok(())},
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_period_ns(&self, period_ns: u32) -> ProxyResult<()>
	{
		match self.pwm.set_period_ns(period_ns)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn get_period_ns(&self) -> ProxyResult<u32>
	{
		match self.pwm.get_period_ns()
		{
			Ok(result) => Ok(result),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}

	}

	fn increase_to_max(&self, step : f32)
	{
		println!("step {}",step);
		let mut duty_cycle = 0.0;
		match self.pwm.get_period_ns()
		{
			Ok(period_ns) => {
			println!("period {}",period_ns);
				while duty_cycle < 1.0 {
					println!("duty cycle {}",duty_cycle);
					println!("set duty cycle ns{}",(duty_cycle * period_ns as f32) as u32);
					self.pwm.set_duty_cycle_ns((duty_cycle * period_ns as f32) as u32).unwrap();
					duty_cycle += step;
					thread::sleep(time::Duration::from_millis(300));
				}
				self.pwm.set_duty_cycle_ns(period_ns).unwrap()
			}
			Err(result) => {println!("{}",result.description())}
		}
	}

	fn decrease_to_minimum(&self, step : f32)
	{
		println!("step {}",step);
		let mut duty_cycle = 1.0;
		match self.pwm.get_period_ns()
		{
			Ok(period_ns) => {
			println!("period {}",period_ns);
				while duty_cycle > 0.0 {
					println!("duty cycle {}",duty_cycle);
					println!("set duty cycle ns{}",(duty_cycle * period_ns as f32) as u32);
					self.pwm.set_duty_cycle_ns((duty_cycle * period_ns as f32) as u32).unwrap();
					duty_cycle -= step;
					thread::sleep(time::Duration::from_millis(300));
				}
				self.pwm.set_duty_cycle_ns(0).unwrap()
			}
			Err(result) => {println!("{}",result.description())}
		}
	}
}<commit_msg>modif<commit_after>
extern crate sysfs_gpio;
extern crate sysfs_pwm;

use self::sysfs_gpio::{Direction, Pin};
use self::sysfs_pwm::{Pwm};
use ::std::error::Error;
use std::thread;
use std::time;

use super::{PinProxyContract,PwmProxyContract,DirectionProxied,ProxyError,ProxyResult};

pub struct PinProxy {
	pin : Pin,
}

impl PinProxyContract for PinProxy
{
	fn new(pin_num: u64) -> PinProxy {
		PinProxy{ pin: Pin::new(pin_num) }
	}

	fn export(&self) ->  ProxyResult<()>{
		match self.pin.export()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn unexport(&self) ->  ProxyResult<()> {
		match self.pin.unexport()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_value(&self, value: u8) ->  ProxyResult<()> {
		match self.pin.set_value(value)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_direction(&self, dir: DirectionProxied) ->  ProxyResult<()>{
		let dirmapped =  match dir {
										DirectionProxied::In =>  Direction::In,
										DirectionProxied::Out => Direction::Out,
										DirectionProxied::High => Direction::High,
										DirectionProxied::Low => Direction::Low,
									};
		match self.pin.set_direction(dirmapped)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}
}

pub struct PwmProxy {
	pwm : Pwm,
}

impl PwmProxyContract for PwmProxy
{
	fn new(chip: u32, number: u32) -> ProxyResult<PwmProxy>{

		match Pwm::new(chip, number) {
			Ok(pwm) => Ok(PwmProxy{ pwm: pwm}),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn export(&self) ->  ProxyResult<()>{
		match self.pwm.export()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn unexport(&self) ->  ProxyResult<()> {
		match self.pwm.unexport()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn enable(&self, enable: bool) -> ProxyResult<()>
	{
		match self.pwm.enable(enable)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{} caused by {}",result.description(),result.cause().unwrap());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_duty_cycle_ns(&self, duty_cycle_ns: u32) -> ProxyResult<()>
	{
		match self.pwm.set_duty_cycle_ns(duty_cycle_ns)
		{
			Ok(()) => {println!("setting dutycycle {}",duty_cycle_ns); Ok(())},
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_period_ns(&self, period_ns: u32) -> ProxyResult<()>
	{
		match self.pwm.set_period_ns(period_ns)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn get_period_ns(&self) -> ProxyResult<u32>
	{
		match self.pwm.get_period_ns()
		{
			Ok(result) => Ok(result),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}

	}

	fn increase_to_max(&self, step : f32)
	{
		println!("step {}",step);
		let mut duty_cycle = 0.0;
		match self.pwm.get_period_ns()
		{
			Ok(period_ns) => {
			println!("period {}",period_ns);
				while duty_cycle < 1.0 {
					println!("duty cycle {}",duty_cycle);
					println!("set duty cycle ns{}",(duty_cycle * period_ns as f32) as u32);
					self.pwm.set_duty_cycle_ns((duty_cycle * period_ns as f32) as u32).unwrap();
					duty_cycle += step;
					thread::sleep(time::Duration::from_millis(300));
				}
				self.pwm.set_duty_cycle_ns(period_ns).unwrap()
			}
			Err(result) => {println!("{}",result.description())}
		}
	}

	fn decrease_to_minimum(&self, step : f32)
	{
		println!("step {}",step);
		let mut duty_cycle = 1.0;
		match self.pwm.get_period_ns()
		{
			Ok(period_ns) => {
			println!("period {}",period_ns);
				while duty_cycle > 0.0 {
					println!("duty cycle {}",duty_cycle);
					println!("set duty cycle ns{}",(duty_cycle * period_ns as f32) as u32);
					self.pwm.set_duty_cycle_ns((duty_cycle * period_ns as f32) as u32).unwrap();
					duty_cycle -= step;
					thread::sleep(time::Duration::from_millis(500));
				}
				self.pwm.set_duty_cycle_ns(0).unwrap()
			}
			Err(result) => {println!("{}",result.description())}
		}
	}
}<|endoftext|>


<commit_before>
extern crate sysfs_gpio;
extern crate sysfs_pwm;

use self::sysfs_gpio::{Direction, Pin};
use self::sysfs_pwm::{Pwm};
use ::std::error::Error;

use super::{PinProxyContract,PwmProxyContract,DirectionProxied,ProxyError,ProxyResult};

pub struct PinProxy {
	pin : Pin,
}

impl PinProxyContract for PinProxy
{
	fn new(pin_num: u64) -> PinProxy {
		PinProxy{ pin: Pin::new(pin_num) }
	}

	fn export(&self) ->  ProxyResult<()>{
		match self.pin.export()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn unexport(&self) ->  ProxyResult<()> {
		match self.pin.unexport()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_value(&self, value: u8) ->  ProxyResult<()> {
		match self.pin.set_value(value)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_direction(&self, dir: DirectionProxied) ->  ProxyResult<()>{
		let dirmapped =  match dir {
										DirectionProxied::In =>  Direction::In,
										DirectionProxied::Out => Direction::Out,
										DirectionProxied::High => Direction::High,
										DirectionProxied::Low => Direction::Low,
									};
		match self.pin.set_direction(dirmapped)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}
}

pub struct PwmProxy {
	pwm : Pwm,
}

impl PwmProxyContract for PwmProxy
{
	fn new(chip: u32, number: u32) -> ProxyResult<PwmProxy>{

		match Pwm::new(chip, number) {
			Ok(pwm) => Ok(PwmProxy{ pwm: pwm}),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn export(&self) ->  ProxyResult<()>{
		match self.pwm.export()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn unexport(&self) ->  ProxyResult<()> {
		match self.pwm.unexport()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn enable(&self, enable: bool) -> ProxyResult<()>
	{
		match self.pwm.enable(enable)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{} caused by {}",result.description(),result.cause().unwrap());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_duty_cycle_ns(&self, duty_cycle_ns: u32) -> ProxyResult<()>
	{
		match self.pwm.set_duty_cycle_ns(duty_cycle_ns)
		{
			Ok(()) => {println!("setting dutycycle {}",duty_cycle_ns); Ok(())},
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_period_ns(&self, period_ns: u32) -> ProxyResult<()>
	{
		match self.pwm.set_period_ns(period_ns)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn get_period_ns(&self) -> ProxyResult<u32>
	{
		match self.pwm.get_period_ns()
		{
			Ok(result) => Ok(result),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}

	}

	fn increase_to_max(&self, duration_ms: u32, update_period_ms: u32)
	{
			let step: f32 = duration_ms as f32 / update_period_ms as f32;
			let mut duty_cycle = 0.0;
			match self.pwm.get_period_ns()
			{
				Ok(period_ns) => {
				println!("period {}",period_ns);
					while duty_cycle < 1.0 {
					println!("duty cycle {}",duty_cycle);
						self.pwm.set_duty_cycle_ns((duty_cycle * period_ns as f32) as u32).unwrap();
						duty_cycle += step;
					}
					self.pwm.set_duty_cycle_ns(period_ns).unwrap()
				}
				Err(result) => {println!("{}",result.description())}
			}
	}

	fn decrease_to_minimum(&self, duration_ms: u32, update_period_ms: u32)
	{
		let step: f32 = duration_ms as f32 / update_period_ms as f32;
			let mut duty_cycle = 1.0;
			match self.pwm.get_period_ns()
			{
				Ok(period_ns) => {
				println!("period {}",period_ns);
					while duty_cycle > 0.0 {
					println!("duty cycle {}",duty_cycle);
						self.pwm.set_duty_cycle_ns((duty_cycle * period_ns as f32) as u32).unwrap();
						duty_cycle -= step;
					}
					self.pwm.set_duty_cycle_ns(0).unwrap()
				}
				Err(result) => {println!("{}",result.description())}
			}
	}

}<commit_msg>logging<commit_after>
extern crate sysfs_gpio;
extern crate sysfs_pwm;

use self::sysfs_gpio::{Direction, Pin};
use self::sysfs_pwm::{Pwm};
use ::std::error::Error;

use super::{PinProxyContract,PwmProxyContract,DirectionProxied,ProxyError,ProxyResult};

pub struct PinProxy {
	pin : Pin,
}

impl PinProxyContract for PinProxy
{
	fn new(pin_num: u64) -> PinProxy {
		PinProxy{ pin: Pin::new(pin_num) }
	}

	fn export(&self) ->  ProxyResult<()>{
		match self.pin.export()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn unexport(&self) ->  ProxyResult<()> {
		match self.pin.unexport()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_value(&self, value: u8) ->  ProxyResult<()> {
		match self.pin.set_value(value)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_direction(&self, dir: DirectionProxied) ->  ProxyResult<()>{
		let dirmapped =  match dir {
										DirectionProxied::In =>  Direction::In,
										DirectionProxied::Out => Direction::Out,
										DirectionProxied::High => Direction::High,
										DirectionProxied::Low => Direction::Low,
									};
		match self.pin.set_direction(dirmapped)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}
}

pub struct PwmProxy {
	pwm : Pwm,
}

impl PwmProxyContract for PwmProxy
{
	fn new(chip: u32, number: u32) -> ProxyResult<PwmProxy>{

		match Pwm::new(chip, number) {
			Ok(pwm) => Ok(PwmProxy{ pwm: pwm}),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn export(&self) ->  ProxyResult<()>{
		match self.pwm.export()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn unexport(&self) ->  ProxyResult<()> {
		match self.pwm.unexport()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn enable(&self, enable: bool) -> ProxyResult<()>
	{
		match self.pwm.enable(enable)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{} caused by {}",result.description(),result.cause().unwrap());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_duty_cycle_ns(&self, duty_cycle_ns: u32) -> ProxyResult<()>
	{
		match self.pwm.set_duty_cycle_ns(duty_cycle_ns)
		{
			Ok(()) => {println!("setting dutycycle {}",duty_cycle_ns); Ok(())},
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_period_ns(&self, period_ns: u32) -> ProxyResult<()>
	{
		match self.pwm.set_period_ns(period_ns)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn get_period_ns(&self) -> ProxyResult<u32>
	{
		match self.pwm.get_period_ns()
		{
			Ok(result) => Ok(result),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}

	}

	fn increase_to_max(&self, duration_ms: u32, update_period_ms: u32)
	{
			let step: f32 = duration_ms as f32 / update_period_ms as f32;
			println!("step {}",step);
			let mut duty_cycle = 0.0;
			match self.pwm.get_period_ns()
			{
				Ok(period_ns) => {
				println!("period {}",period_ns);
					while duty_cycle < 1.0 {
						println!("duty cycle {}",duty_cycle);
						println!("set duty cycle ns{}",(duty_cycle * period_ns as f32) as u32);
						self.pwm.set_duty_cycle_ns((duty_cycle * period_ns as f32) as u32).unwrap();
						duty_cycle += step;
					}
					self.pwm.set_duty_cycle_ns(period_ns).unwrap()
				}
				Err(result) => {println!("{}",result.description())}
			}
	}

	fn decrease_to_minimum(&self, duration_ms: u32, update_period_ms: u32)
	{
		let step: f32 = duration_ms as f32 / update_period_ms as f32;
		println!("step {}",step);
		let mut duty_cycle = 1.0;
		match self.pwm.get_period_ns()
		{
			Ok(period_ns) => {
			println!("period {}",period_ns);
				while duty_cycle > 0.0 {
					println!("duty cycle {}",duty_cycle);
					println!("set duty cycle ns{}",(duty_cycle * period_ns as f32) as u32);
						self.pwm.set_duty_cycle_ns((duty_cycle * period_ns as f32) as u32).unwrap();
						duty_cycle -= step;
				}
				self.pwm.set_duty_cycle_ns(0).unwrap()
			}
			Err(result) => {println!("{}",result.description())}
		}
	}
}<|endoftext|>


<commit_before>//! Utilities to do with connections between a Minecraft or Forge client and Netherrack

extern crate chrono;
use self::chrono::duration::Duration;

/*use super::packet::{ PacketHeader,
                     ID_HANDSHAKE_CTS_HANDSHAKING,
                     ID_STATUS_CTS_REQUEST, ID_STATUS_CTS_PING
                   };*/

use std::net::{Shutdown, TcpStream};

use std::io::Read;

//use super::deque_buffer::DequeBuffer;

/// An enum describing the current connection's state
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum ConnectionState {

    /// Connection is in handshake mode
    HANDSHAKE,

    /// Connection is in login mode
    LOGIN,

    /// Connection is in status mode
    STATUS,

    /// Connection is in play mode
    PLAY

}

/// A struct defining a game connection
#[derive(Debug)]
pub struct GameConnection {

    /// The TCP stream bound to this GameConnection
    pub stream: TcpStream,

    /// The state of this GameConnection
    pub state: ConnectionState,

    /// Whether the client has the Forge Mod Loader injected into it
    ///
    /// This may change in 1.9 as FML is being destroyed and Forge is becoming the norm
    pub forge_enabled: bool,

    /// A boolean declaring if this GameConnection is connected
    pub connected: bool

}

impl GameConnection {

    /// Creates a new GameConnection
    pub fn new(stream: TcpStream) -> GameConnection {
        GameConnection {
            stream: stream,
            state: ConnectionState::HANDSHAKE,
            forge_enabled: false,
            connected: true //HURR DURR
        }
    }

    pub fn disconnect(&mut self) {
        //TODO: Check to see if in ConnectionState::PLAY, otherwise
        let result = self.stream.shutdown(Shutdown::Both);

        if result.is_ok() == false {
            error!("Error disconnecting: {:?}", result);
        }

        self.connected = false;

        ::std::thread::yield_now();

    }

    /// Starts listening on the connection
    pub fn start_listening(&mut self) {

        trace!("Got a new client from {}!", self.stream.peer_addr().unwrap());

        let mut timeout_duration = Duration::zero();

        loop {

            if timeout_duration.num_seconds() >= 1 {
                info!("Client at {} timed out, dropping connection", self.stream.peer_addr().unwrap());
                self.disconnect();
                break;
            }

            if !self.connected {
                debug!("Client at {} was forcibly disconnected, maybe for a good reason", self.stream.peer_addr().unwrap());
                break;
            }

            timeout_duration = timeout_duration + Duration::milliseconds(2);
            ::std::thread::sleep_ms(2);
        /*
            let mut raw_buffer = vec![0u8; 512];

            match self.stream.read(&mut raw_buffer) {

                Err(error) => {
                    // Connection dropped out or something broke
                    // In the future, we use the customized NetherrackStream to see if we're in GAME mode, and if so, get the attached player and start saving their information and get rid of them
                    // For now, we just exit the loop
                    error!("Got an error! {}", error);

                    self.disconnect();
                    break;
                }
                Ok(count) => {
                    if count == 0 {
                        //Nothing in stream, let's sleep for a few milliseconds and try again
                        timeout_duration = timeout_duration + Duration::milliseconds(2);
                        ::std::thread::sleep_ms(2);
                    } else {

                        timeout_duration = Duration::zero();

                        // Now truncate the raw buffer - Don't worry, it will reallocate to 512 on the next networking loop
                        raw_buffer.truncate(count);

                        let mut backing: VecDeque<u8> = VecDeque::<u8>::with_capacity(count);

                        for b in raw_buffer {

                            backing.push_back(b);
                        }

                        let mut buffer = DequeBuffer::from(backing);

                        //drop(raw_buffer);

                        let length_result = buffer.read_unsigned_varint_32();
                        let id_result = buffer.read_unsigned_varint_32();

                        if length_result.is_err() || id_result.is_err() {
                            error!("Error while reading packet ID or length! Oh no, dropping connection");

                            self.disconnect();
                            break;
                        }

                        let packet_header = PacketHeader::new(length_result.unwrap(), id_result.unwrap());

                        if self.state == ConnectionState::HANDSHAKE {

                            match packet_header.id {

                                ID_HANDSHAKE_CTS_HANDSHAKING => {
                                    super::packet::incoming::handshake::HandshakePacket::decode(packet_header, self, &mut buffer).handle(self);
                                },
                                _ => debug!("Incoming handshake packet unhandled; ID: {}, Length: {}", packet_header.id, packet_header.length)

                            }

                        } else if self.state == ConnectionState::LOGIN {

                            match packet_header.id {

                                _ => debug!("Incoming login packet unhandled; ID: {}, Length: {}", packet_header.id, packet_header.length)

                            }

                        } else if self.state == ConnectionState::STATUS {

                            match packet_header.id {

                                ID_STATUS_CTS_REQUEST => {
                                    super::packet::incoming::status::StatusRequestPacket::decode(packet_header, self, &mut buffer).handle(self);
                                },
                                ID_STATUS_CTS_PING => {
                                    super::packet::incoming::status::ListPingPacket::decode(packet_header, self, &mut buffer).handle(self);
                                },
                                _ => debug!("Incoming play packet unhandled; ID: {}, Length: {}", packet_header.id, packet_header.length)

                            }

                        } else if self.state == ConnectionState::PLAY {

                            match packet_header.id {

                                _ => debug!("Incoming play packet unhandled; ID: {}, Length: {}", packet_header.id, packet_header.length)

                            }

                        }

                        // This is a memory leak. We need to get the time of last packet and check to see if it's more than 20 seconds ago
                    }
                }

            }*/

        }

    }

}
<commit_msg>Dump changes I've forgotten about<commit_after>//! Utilities to do with connections between a Minecraft or Forge client and Netherrack

extern crate chrono;
use self::chrono::duration::Duration;

/*use super::packet::{ PacketHeader,
                     ID_HANDSHAKE_CTS_HANDSHAKING,
                     ID_STATUS_CTS_REQUEST, ID_STATUS_CTS_PING
                   };*/

use std::net::{Shutdown, TcpStream};

use ::io_operations::reader::Reader;

/// An enum describing the current connection's state
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum ConnectionState {

    /// Connection is in handshake mode
    HANDSHAKE,

    /// Connection is in login mode
    LOGIN,

    /// Connection is in status mode
    STATUS,

    /// Connection is in play mode
    PLAY

}

/// A struct defining a game connection
#[derive(Debug)]
pub struct GameConnection {

    /// The TCP stream bound to this GameConnection
    pub stream: TcpStream,

    /// The state of this GameConnection
    pub state: ConnectionState,

    /// Whether the client has the Forge Mod Loader injected into it
    ///
    /// This may change in 1.9 as FML is being destroyed and Forge is becoming the norm
    pub forge_enabled: bool,

    /// A boolean declaring if this GameConnection is connected
    pub connected: bool

}

impl GameConnection {

    /// Creates a new GameConnection
    pub fn new(stream: TcpStream) -> GameConnection {
        GameConnection {
            stream: stream,
            state: ConnectionState::HANDSHAKE,
            forge_enabled: false,
            connected: true //HURR DURR
        }
    }

    pub fn disconnect(&mut self) {
        //TODO: Check to see if in ConnectionState::PLAY, otherwise
        let result = self.stream.shutdown(Shutdown::Both);

        if result.is_ok() == false {
            error!("Error disconnecting: {:?}", result);
        }

        self.connected = false;

        ::std::thread::yield_now();

    }

    /// Starts listening on the connection
    pub fn start_listening(&mut self) {

        trace!("Got a new client from {}!", self.stream.peer_addr().unwrap());

        let mut timeout_duration = Duration::zero();

        loop {

            //First, let's start off the timeout timer.
            timeout_duration = timeout_duration + Duration::milliseconds(2);
            ::std::thread::sleep_ms(2);

            if timeout_duration.num_seconds() >= 1 {
                info!("Client at {} timed out, dropping connection", self.stream.peer_addr().unwrap());
                self.disconnect();
                break;
            }

            if !self.connected {
                debug!("Client at {} was forcibly disconnected, maybe for a good reason", self.stream.peer_addr().unwrap());
                break;
            }

            match self.stream.read_unsigned_byte() {
                Err(error) => {

                    if error != "Could not read one byte" {
                        error!("Error: {}", error);
                        self.disconnect();
                    }
                }

                Ok(value) => {
                    timeout_duration = Duration::zero();
                    info!("Value is {}", value);
                }
            }

        /*
            let mut raw_buffer = vec![0u8; 512];

            match self.stream.read(&mut raw_buffer) {

                Err(error) => {
                    // Connection dropped out or something broke
                    // In the future, we use the customized NetherrackStream to see if we're in GAME mode, and if so, get the attached player and start saving their information and get rid of them
                    // For now, we just exit the loop
                    error!("Got an error! {}", error);

                    self.disconnect();
                    break;
                }
                Ok(count) => {
                    if count == 0 {
                        //Nothing in stream, let's sleep for a few milliseconds and try again
                        timeout_duration = timeout_duration + Duration::milliseconds(2);
                        ::std::thread::sleep_ms(2);
                    } else {

                        timeout_duration = Duration::zero();

                        // Now truncate the raw buffer - Don't worry, it will reallocate to 512 on the next networking loop
                        raw_buffer.truncate(count);

                        let mut backing: VecDeque<u8> = VecDeque::<u8>::with_capacity(count);

                        for b in raw_buffer {

                            backing.push_back(b);
                        }

                        let mut buffer = DequeBuffer::from(backing);

                        //drop(raw_buffer);

                        let length_result = buffer.read_unsigned_varint_32();
                        let id_result = buffer.read_unsigned_varint_32();

                        if length_result.is_err() || id_result.is_err() {
                            error!("Error while reading packet ID or length! Oh no, dropping connection");

                            self.disconnect();
                            break;
                        }

                        let packet_header = PacketHeader::new(length_result.unwrap(), id_result.unwrap());

                        if self.state == ConnectionState::HANDSHAKE {

                            match packet_header.id {

                                ID_HANDSHAKE_CTS_HANDSHAKING => {
                                    super::packet::incoming::handshake::HandshakePacket::decode(packet_header, self, &mut buffer).handle(self);
                                },
                                _ => debug!("Incoming handshake packet unhandled; ID: {}, Length: {}", packet_header.id, packet_header.length)

                            }

                        } else if self.state == ConnectionState::LOGIN {

                            match packet_header.id {

                                _ => debug!("Incoming login packet unhandled; ID: {}, Length: {}", packet_header.id, packet_header.length)

                            }

                        } else if self.state == ConnectionState::STATUS {

                            match packet_header.id {

                                ID_STATUS_CTS_REQUEST => {
                                    super::packet::incoming::status::StatusRequestPacket::decode(packet_header, self, &mut buffer).handle(self);
                                },
                                ID_STATUS_CTS_PING => {
                                    super::packet::incoming::status::ListPingPacket::decode(packet_header, self, &mut buffer).handle(self);
                                },
                                _ => debug!("Incoming play packet unhandled; ID: {}, Length: {}", packet_header.id, packet_header.length)

                            }

                        } else if self.state == ConnectionState::PLAY {

                            match packet_header.id {

                                _ => debug!("Incoming play packet unhandled; ID: {}, Length: {}", packet_header.id, packet_header.length)

                            }

                        }

                        // This is a memory leak. We need to get the time of last packet and check to see if it's more than 20 seconds ago
                    }
                }

            }*/

        }

    }

}
<|endoftext|>