<commit_before>use crate::task::local_waker_ref_from_nonlocal;
use futures_core::future::Future;
use futures_core::task::{LocalWaker, Poll, Wake, Waker};
use slab::Slab;
use std::cell::UnsafeCell;
use std::fmt;
use std::marker::Unpin;
use std::pin::Pin;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use std::sync::{Arc, Mutex};

/// A future that is cloneable and can be polled in multiple threads.
/// Use the [`shared`](crate::FutureExt::shared) combinator method to convert
/// any future into a `Shared` future.
#[must_use = "futures do nothing unless polled"]
pub struct Shared<Fut: Future> {
    inner: Option<Arc<Inner<Fut>>>,
    waker_key: usize,
}

struct Inner<Fut: Future> {
    future_or_output: UnsafeCell<FutureOrOutput<Fut>>,
    notifier: Arc<Notifier>,
}

struct Notifier {
    state: AtomicUsize,
    wakers: Mutex<Option<Slab<Option<Waker>>>>,
}

// The future itself is polled behind the `Arc`, so it won't be moved
// when `Shared` is moved.
impl<Fut: Future> Unpin for Shared<Fut> {}

impl<Fut: Future> fmt::Debug for Shared<Fut> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Shared")
            .field("inner", &self.inner)
            .field("waker_key", &self.waker_key)
            .finish()
    }
}

impl<Fut: Future> fmt::Debug for Inner<Fut> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Inner").finish()
    }
}

enum FutureOrOutput<Fut: Future> {
    Future(Fut),
    Output(Fut::Output),
}

unsafe impl<Fut> Send for Inner<Fut>
where
    Fut: Future + Send,
    Fut::Output: Send + Sync,
{}

unsafe impl<Fut> Sync for Inner<Fut>
where
    Fut: Future + Send,
    Fut::Output: Send + Sync,
{}

const IDLE: usize = 0;
const POLLING: usize = 1;
const REPOLL: usize = 2;
const COMPLETE: usize = 3;
const POISONED: usize = 4;

const NULL_WAKER_KEY: usize = usize::max_value();

impl<Fut: Future> Shared<Fut> {
    pub(super) fn new(future: Fut) -> Shared<Fut> {
        let inner = Inner {
            future_or_output: UnsafeCell::new(FutureOrOutput::Future(future)),
            notifier: Arc::new(Notifier {
                state: AtomicUsize::new(IDLE),
                wakers: Mutex::new(Some(Slab::new())),
            }),
        };

        Shared {
            inner: Some(Arc::new(inner)),
            waker_key: NULL_WAKER_KEY,
        }
    }
}

impl<Fut> Shared<Fut>
where
    Fut: Future,
    Fut::Output: Clone,
{
    /// Returns [`Some`] containing a reference to this [`Shared`]'s output if
    /// it has already been computed by a clone or [`None`] if it hasn't been
    /// computed yet or this [`Shared`] already returned its output from
    /// [`poll`](Future::poll).
    pub fn peek(&self) -> Option<&Fut::Output> {
        if let Some(inner) = self.inner.as_ref() {
            match inner.notifier.state.load(SeqCst) {
                COMPLETE => unsafe { return Some(inner.output()) },
                POISONED => panic!("inner future panicked during poll"),
                _ => {}
            }
        }
        None
    }

    /// Registers the current task to receive a wakeup when `Inner` is awoken.
    fn set_waker(&mut self, lw: &LocalWaker) {
        // Acquire the lock first before checking COMPLETE to ensure there
        // isn't a race.
        let mut wakers_guard = if let Some(inner) = self.inner.as_ref() {
            inner.notifier.wakers.lock().unwrap()
        } else {
            return;
        };

        let wakers = if let Some(wakers) = wakers_guard.as_mut() {
            wakers
        } else {
            return;
        };

        if self.waker_key == NULL_WAKER_KEY {
            self.waker_key = wakers.insert(Some(lw.clone().into_waker()));
        } else {
            let waker_slot = &mut wakers[self.waker_key];
            let needs_replacement = if let Some(old_waker) = waker_slot {
                // If there's still an unwoken waker in the slot, only replace
                // if the current one wouldn't wake the same task.
                !lw.will_wake_nonlocal(old_waker)
            } else {
                true
            };
            if needs_replacement {
                *waker_slot = Some(lw.clone().into_waker());
            }
        }
        debug_assert!(self.waker_key != NULL_WAKER_KEY);
    }

    /// Safety: callers must first ensure that `self.inner.state`
    /// is `COMPLETE`
    unsafe fn take_or_clone_output(&mut self) -> Fut::Output {
        let inner = self.inner.take().unwrap();

        match Arc::try_unwrap(inner) {
            Ok(inner) => match inner.future_or_output.into_inner() {
                FutureOrOutput::Output(item) => item,
                FutureOrOutput::Future(_) => unreachable!(),
            },
            Err(inner) => inner.output().clone(),
        }
    }
}

impl<Fut> Inner<Fut>
where
    Fut: Future,
    Fut::Output: Clone,
{
    /// Safety: callers must first ensure that `self.inner.state`
    /// is `COMPLETE`
    unsafe fn output(&self) -> &Fut::Output {
        match &*self.future_or_output.get() {
            FutureOrOutput::Output(ref item) => &item,
            FutureOrOutput::Future(_) => unreachable!(),
        }
    }
}

impl<Fut: Future> Future for Shared<Fut>
where
    Fut::Output: Clone,
{
    type Output = Fut::Output;

    fn poll(mut self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
        let this = &mut *self;

        this.set_waker(lw);

        let inner = if let Some(inner) = this.inner.as_ref() {
            inner
        } else {
            panic!("Shared future polled again after completion");
        };

        match inner.notifier.state.compare_and_swap(IDLE, POLLING, SeqCst) {
            IDLE => {
                // Lock acquired, fall through
            }
            POLLING | REPOLL => {
                // Another task is currently polling, at this point we just want
                // to ensure that the waker for this task is registered

                return Poll::Pending;
            }
            COMPLETE => {
                // Safety: We're in the COMPLETE state
                return unsafe { Poll::Ready(this.take_or_clone_output()) };
            }
            POISONED => panic!("inner future panicked during poll"),
            _ => unreachable!(),
        }

        let waker = local_waker_ref_from_nonlocal(&inner.notifier);
        let lw = &waker;

        struct Reset<'a>(&'a AtomicUsize);

        impl<'a> Drop for Reset<'a> {
            fn drop(&mut self) {
                use std::thread;

                if thread::panicking() {
                    self.0.store(POISONED, SeqCst);
                }
            }
        }

        let _reset = Reset(&inner.notifier.state);

        let output = loop {
            let future = unsafe {
                match &mut *inner.future_or_output.get() {
                    FutureOrOutput::Future(fut) => Pin::new_unchecked(fut),
                    _ => unreachable!(),
                }
            };

            let poll = future.poll(&lw);

            match poll {
                Poll::Pending => {
                    let state = &inner.notifier.state;
                    match state.compare_and_swap(POLLING, IDLE, SeqCst) {
                        POLLING => {
                            // Success
                            return Poll::Pending;
                        }
                        REPOLL => {
                            // Was woken since: Gotta poll again!
                            let prev = state.swap(POLLING, SeqCst);
                            assert_eq!(prev, REPOLL);
                        }
                        _ => unreachable!(),
                    }
                }
                Poll::Ready(output) => break output,
            }
        };

        unsafe {
            *inner.future_or_output.get() =
                FutureOrOutput::Output(output);
        }

        inner.notifier.state.store(COMPLETE, SeqCst);

        // Wake all tasks and drop the slab
        let mut wakers_guard = inner.notifier.wakers.lock().unwrap();
        let wakers = &mut wakers_guard.take().unwrap();
        for (_key, opt_waker) in wakers {
            if let Some(waker) = opt_waker.take() {
                waker.wake();
            }
        }

        drop(_reset); // Make borrow checker happy
        drop(wakers_guard);

        // Safety: We're in the COMPLETE state
        unsafe { Poll::Ready(this.take_or_clone_output()) }
    }
}

impl<Fut> Clone for Shared<Fut>
where
    Fut: Future,
{
    fn clone(&self) -> Self {
        Shared {
            inner: self.inner.clone(),
            waker_key: NULL_WAKER_KEY,
        }
    }
}

impl<Fut> Drop for Shared<Fut>
where
    Fut: Future,
{
    fn drop(&mut self) {
        if self.waker_key != NULL_WAKER_KEY {
            if let Some(ref inner) = self.inner {
                if let Ok(mut wakers) = inner.notifier.wakers.lock() {
                    if let Some(wakers) = wakers.as_mut() {
                        wakers.remove(self.waker_key);
                    }
                }
            }
        }
    }
}

impl Wake for Notifier {
    fn wake(arc_self: &Arc<Self>) {
        arc_self.state.compare_and_swap(POLLING, REPOLL, SeqCst);

        let wakers = &mut *arc_self.wakers.lock().unwrap();
        if let Some(wakers) = wakers.as_mut() {
            for (_key, opt_waker) in wakers {
                if let Some(waker) = opt_waker.take() {
                    waker.wake();
                }
            }
        }
    }
}
<commit_msg>Add FusedFuture impl for Shared<commit_after>use crate::task::local_waker_ref_from_nonlocal;
use futures_core::future::{FusedFuture, Future};
use futures_core::task::{LocalWaker, Poll, Wake, Waker};
use slab::Slab;
use std::cell::UnsafeCell;
use std::fmt;
use std::marker::Unpin;
use std::pin::Pin;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use std::sync::{Arc, Mutex};

/// A future that is cloneable and can be polled in multiple threads.
/// Use the [`shared`](crate::FutureExt::shared) combinator method to convert
/// any future into a `Shared` future.
#[must_use = "futures do nothing unless polled"]
pub struct Shared<Fut: Future> {
    inner: Option<Arc<Inner<Fut>>>,
    waker_key: usize,
}

struct Inner<Fut: Future> {
    future_or_output: UnsafeCell<FutureOrOutput<Fut>>,
    notifier: Arc<Notifier>,
}

struct Notifier {
    state: AtomicUsize,
    wakers: Mutex<Option<Slab<Option<Waker>>>>,
}

// The future itself is polled behind the `Arc`, so it won't be moved
// when `Shared` is moved.
impl<Fut: Future> Unpin for Shared<Fut> {}

impl<Fut: Future> fmt::Debug for Shared<Fut> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Shared")
            .field("inner", &self.inner)
            .field("waker_key", &self.waker_key)
            .finish()
    }
}

impl<Fut: Future> fmt::Debug for Inner<Fut> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Inner").finish()
    }
}

enum FutureOrOutput<Fut: Future> {
    Future(Fut),
    Output(Fut::Output),
}

unsafe impl<Fut> Send for Inner<Fut>
where
    Fut: Future + Send,
    Fut::Output: Send + Sync,
{}

unsafe impl<Fut> Sync for Inner<Fut>
where
    Fut: Future + Send,
    Fut::Output: Send + Sync,
{}

const IDLE: usize = 0;
const POLLING: usize = 1;
const REPOLL: usize = 2;
const COMPLETE: usize = 3;
const POISONED: usize = 4;

const NULL_WAKER_KEY: usize = usize::max_value();

impl<Fut: Future> Shared<Fut> {
    pub(super) fn new(future: Fut) -> Shared<Fut> {
        let inner = Inner {
            future_or_output: UnsafeCell::new(FutureOrOutput::Future(future)),
            notifier: Arc::new(Notifier {
                state: AtomicUsize::new(IDLE),
                wakers: Mutex::new(Some(Slab::new())),
            }),
        };

        Shared {
            inner: Some(Arc::new(inner)),
            waker_key: NULL_WAKER_KEY,
        }
    }
}

impl<Fut> Shared<Fut>
where
    Fut: Future,
    Fut::Output: Clone,
{
    /// Returns [`Some`] containing a reference to this [`Shared`]'s output if
    /// it has already been computed by a clone or [`None`] if it hasn't been
    /// computed yet or this [`Shared`] already returned its output from
    /// [`poll`](Future::poll).
    pub fn peek(&self) -> Option<&Fut::Output> {
        if let Some(inner) = self.inner.as_ref() {
            match inner.notifier.state.load(SeqCst) {
                COMPLETE => unsafe { return Some(inner.output()) },
                POISONED => panic!("inner future panicked during poll"),
                _ => {}
            }
        }
        None
    }

    /// Registers the current task to receive a wakeup when `Inner` is awoken.
    fn set_waker(&mut self, lw: &LocalWaker) {
        // Acquire the lock first before checking COMPLETE to ensure there
        // isn't a race.
        let mut wakers_guard = if let Some(inner) = self.inner.as_ref() {
            inner.notifier.wakers.lock().unwrap()
        } else {
            return;
        };

        let wakers = if let Some(wakers) = wakers_guard.as_mut() {
            wakers
        } else {
            return;
        };

        if self.waker_key == NULL_WAKER_KEY {
            self.waker_key = wakers.insert(Some(lw.clone().into_waker()));
        } else {
            let waker_slot = &mut wakers[self.waker_key];
            let needs_replacement = if let Some(old_waker) = waker_slot {
                // If there's still an unwoken waker in the slot, only replace
                // if the current one wouldn't wake the same task.
                !lw.will_wake_nonlocal(old_waker)
            } else {
                true
            };
            if needs_replacement {
                *waker_slot = Some(lw.clone().into_waker());
            }
        }
        debug_assert!(self.waker_key != NULL_WAKER_KEY);
    }

    /// Safety: callers must first ensure that `self.inner.state`
    /// is `COMPLETE`
    unsafe fn take_or_clone_output(&mut self) -> Fut::Output {
        let inner = self.inner.take().unwrap();

        match Arc::try_unwrap(inner) {
            Ok(inner) => match inner.future_or_output.into_inner() {
                FutureOrOutput::Output(item) => item,
                FutureOrOutput::Future(_) => unreachable!(),
            },
            Err(inner) => inner.output().clone(),
        }
    }
}

impl<Fut> Inner<Fut>
where
    Fut: Future,
    Fut::Output: Clone,
{
    /// Safety: callers must first ensure that `self.inner.state`
    /// is `COMPLETE`
    unsafe fn output(&self) -> &Fut::Output {
        match &*self.future_or_output.get() {
            FutureOrOutput::Output(ref item) => &item,
            FutureOrOutput::Future(_) => unreachable!(),
        }
    }
}

impl<Fut: Future> FusedFuture for Shared<Fut> {
    fn is_terminated(&self) -> bool {
        self.inner.is_none()
    }
}

impl<Fut: Future> Future for Shared<Fut>
where
    Fut::Output: Clone,
{
    type Output = Fut::Output;

    fn poll(mut self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
        let this = &mut *self;

        this.set_waker(lw);

        let inner = if let Some(inner) = this.inner.as_ref() {
            inner
        } else {
            panic!("Shared future polled again after completion");
        };

        match inner.notifier.state.compare_and_swap(IDLE, POLLING, SeqCst) {
            IDLE => {
                // Lock acquired, fall through
            }
            POLLING | REPOLL => {
                // Another task is currently polling, at this point we just want
                // to ensure that the waker for this task is registered

                return Poll::Pending;
            }
            COMPLETE => {
                // Safety: We're in the COMPLETE state
                return unsafe { Poll::Ready(this.take_or_clone_output()) };
            }
            POISONED => panic!("inner future panicked during poll"),
            _ => unreachable!(),
        }

        let waker = local_waker_ref_from_nonlocal(&inner.notifier);
        let lw = &waker;

        struct Reset<'a>(&'a AtomicUsize);

        impl<'a> Drop for Reset<'a> {
            fn drop(&mut self) {
                use std::thread;

                if thread::panicking() {
                    self.0.store(POISONED, SeqCst);
                }
            }
        }

        let _reset = Reset(&inner.notifier.state);

        let output = loop {
            let future = unsafe {
                match &mut *inner.future_or_output.get() {
                    FutureOrOutput::Future(fut) => Pin::new_unchecked(fut),
                    _ => unreachable!(),
                }
            };

            let poll = future.poll(&lw);

            match poll {
                Poll::Pending => {
                    let state = &inner.notifier.state;
                    match state.compare_and_swap(POLLING, IDLE, SeqCst) {
                        POLLING => {
                            // Success
                            return Poll::Pending;
                        }
                        REPOLL => {
                            // Was woken since: Gotta poll again!
                            let prev = state.swap(POLLING, SeqCst);
                            assert_eq!(prev, REPOLL);
                        }
                        _ => unreachable!(),
                    }
                }
                Poll::Ready(output) => break output,
            }
        };

        unsafe {
            *inner.future_or_output.get() =
                FutureOrOutput::Output(output);
        }

        inner.notifier.state.store(COMPLETE, SeqCst);

        // Wake all tasks and drop the slab
        let mut wakers_guard = inner.notifier.wakers.lock().unwrap();
        let wakers = &mut wakers_guard.take().unwrap();
        for (_key, opt_waker) in wakers {
            if let Some(waker) = opt_waker.take() {
                waker.wake();
            }
        }

        drop(_reset); // Make borrow checker happy
        drop(wakers_guard);

        // Safety: We're in the COMPLETE state
        unsafe { Poll::Ready(this.take_or_clone_output()) }
    }
}

impl<Fut> Clone for Shared<Fut>
where
    Fut: Future,
{
    fn clone(&self) -> Self {
        Shared {
            inner: self.inner.clone(),
            waker_key: NULL_WAKER_KEY,
        }
    }
}

impl<Fut> Drop for Shared<Fut>
where
    Fut: Future,
{
    fn drop(&mut self) {
        if self.waker_key != NULL_WAKER_KEY {
            if let Some(ref inner) = self.inner {
                if let Ok(mut wakers) = inner.notifier.wakers.lock() {
                    if let Some(wakers) = wakers.as_mut() {
                        wakers.remove(self.waker_key);
                    }
                }
            }
        }
    }
}

impl Wake for Notifier {
    fn wake(arc_self: &Arc<Self>) {
        arc_self.state.compare_and_swap(POLLING, REPOLL, SeqCst);

        let wakers = &mut *arc_self.wakers.lock().unwrap();
        if let Some(wakers) = wakers.as_mut() {
            for (_key, opt_waker) in wakers {
                if let Some(waker) = opt_waker.take() {
                    waker.wake();
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//
// Mnemosyne: a functional systems programming language.
// (c) 2015 Hawk Weisman
//
// Mnemosyne is released under the MIT License. Please refer to
// the LICENSE file at the top-level directory of this distribution
// or at https://github.com/hawkw/mnemosyne/.
//
#![crate_name = "mnemosyne"]
#![crate_type = "lib"]
#![feature(rustc_private)]
#![feature(static_recursion)]
#![feature(box_syntax, box_patterns)]

//! # Mnemosyne core
//!
//! This crate contains the core Mnemosyne programming language components.
//! This includes the mnemosyne abstract syntax tree (`semantic::ast`),
//! functions for performing semantic analysis (`semantic`), functions
//! for compiling abstract syntax trees to LLVM bytecode (`compile`), and
//! assorted utility code such as a positional reference type and a
//! `ForkTable` data structure for use as a symbol table.
//!
//! The Mnemosyne parser is contained in a separate crate in order to improve
//! compile times.

extern crate rustc;
extern crate libc;
extern crate combine;
#[macro_use] extern crate itertools;

/// Macro for formatting an internal compiler error panic.
///
/// This should be used instead of the Rust standard library's `panic!()`
/// macro in the event of an unrecoverable internal compiler error.
#[macro_use]
macro_rules! ice {
    ($msg:expr) => (
        panic!( "[internal error] {}\n \
                 [internal error] Something has gone horribly wrong.\n \
                 [internal error] Please contact the Mnemosyne implementors.\n\
                 {}, {}"
              , $msg
              , mnemosyne_version(), llvm_version()
              )
          );
    ($fmt:expr, $($arg:tt)+) => (
        panic!( "[internal error] {}\n \
                 [internal error] Something has gone horribly wrong.\n \
                 [internal error] Please contact the Mnemosyne implementors.\n\
                 {}, {}"
              , format_args!($fmt, $($arg)+)
              , mnemosyne_version(), llvm_version()
              )
          )
}

pub mod position;
pub mod semantic;
pub mod compile;
pub mod forktable;
pub mod chars;
pub mod errors;

pub use semantic::ast;

use rustc::lib::llvm::{LLVMVersionMajor, LLVMVersionMinor};

use std::fmt::Debug;

const VERSION_MAJOR: u32 = 0;
const VERSION_MINOR: u32 = 1;

/// Returns the LLVM version as a String
pub fn llvm_version() -> String {
    unsafe { format!("LLVM v{}.{}", LLVMVersionMajor(), LLVMVersionMinor()) }
}

/// Returns the Mnemosyne version as a String
pub fn mnemosyne_version() -> String {
    format!("Mnemosyne v{}.{}", VERSION_MAJOR, VERSION_MINOR)
}
<commit_msg>Export ICE macro to non-core crates<commit_after>//
// Mnemosyne: a functional systems programming language.
// (c) 2015 Hawk Weisman
//
// Mnemosyne is released under the MIT License. Please refer to
// the LICENSE file at the top-level directory of this distribution
// or at https://github.com/hawkw/mnemosyne/.
//
#![crate_name = "mnemosyne"]
#![crate_type = "lib"]
#![feature(rustc_private)]
#![feature(static_recursion)]
#![feature(box_syntax, box_patterns)]

//! # Mnemosyne core
//!
//! This crate contains the core Mnemosyne programming language components.
//! This includes the mnemosyne abstract syntax tree (`semantic::ast`),
//! functions for performing semantic analysis (`semantic`), functions
//! for compiling abstract syntax trees to LLVM bytecode (`compile`), and
//! assorted utility code such as a positional reference type and a
//! `ForkTable` data structure for use as a symbol table.
//!
//! The Mnemosyne parser is contained in a separate crate in order to improve
//! compile times.

extern crate rustc;
extern crate libc;
extern crate combine;
#[macro_use] extern crate itertools;

/// Macro for formatting an internal compiler error panic.
///
/// This should be used instead of the Rust standard library's `panic!()`
/// macro in the event of an unrecoverable internal compiler error.
#[macro_export]
macro_rules! ice {
    ($msg:expr) => (
        panic!( "[internal error] {}\n \
                 [internal error] Something has gone horribly wrong.\n \
                 [internal error] Please contact the Mnemosyne implementors.\n\
                 {}, {}"
              , $msg
              , mnemosyne_version(), llvm_version()
              )
          );
    ($fmt:expr, $($arg:tt)+) => (
        panic!( "[internal error] {}\n \
                 [internal error] Something has gone horribly wrong.\n \
                 [internal error] Please contact the Mnemosyne implementors.\n\
                 {}, {}"
              , format_args!($fmt, $($arg)+)
              , mnemosyne_version(), llvm_version()
              )
          )
}

pub mod position;
pub mod semantic;
pub mod compile;
pub mod forktable;
pub mod chars;
pub mod errors;

pub use semantic::ast;

use rustc::lib::llvm::{LLVMVersionMajor, LLVMVersionMinor};

use std::fmt::Debug;

const VERSION_MAJOR: u32 = 0;
const VERSION_MINOR: u32 = 1;

/// Returns the LLVM version as a String
pub fn llvm_version() -> String {
    unsafe { format!("LLVM v{}.{}", LLVMVersionMajor(), LLVMVersionMinor()) }
}

/// Returns the Mnemosyne version as a String
pub fn mnemosyne_version() -> String {
    format!("Mnemosyne v{}.{}", VERSION_MAJOR, VERSION_MINOR)
}
<|endoftext|>


<commit_before>/// The `mutate` trait returns a mutation version of a type that implements it.
///
/// Implementer should try to create persisted data-structures

extern crate rand;

use self::rand::Rng;
use super::super::structure::{Program,Condition,Expression,Sensor,Command};

pub trait Mutate {
    fn mutate(&self) -> Self;
}

enum MutateType {
    ThisLevel,
    NextLevel,
}

impl rand::Rand for MutateType {
    fn rand<R: rand::Rng>(_: &mut R) -> Self {
        pick![
            1, MutateType::ThisLevel,
            1, MutateType::NextLevel
        ]
    }
}

impl Mutate for Program {
    fn mutate(&self) -> Program {
        let mutate_type: MutateType = rand::random();
        match mutate_type {
            MutateType::ThisLevel => {
                let mutation: Program = rand::random();
                mutation
            },
            MutateType::NextLevel => {
                match *self {
                    Program::If(ref condition, ref left, ref right) => {
                        let mut rng = rand::thread_rng();
                        match rng.gen_range(0, 3) {
                            0 => { /* mutate condition */
                                      let mutation: Condition = condition.mutate();
                                      Program::If(mutation, left.clone(), right.clone())
                            },
                            1 => { /* mutate left */
                                      let mutation: Program = left.mutate();
                                      Program::If(condition.clone(), Box::new(mutation), right.clone())
                            },
                            2 => { /* mutate right */
                                      let mutation: Program = right.mutate();
                                      Program::If(condition.clone(), left.clone(), Box::new(mutation))
                            },
                            _ => { panic!(/* this should not happen */)},
                        }
                    },
                    Program::Command(ref command) => {
                        let mutation: Command = command.mutate();
                        Program::Command(mutation)
                    }
                }
            },
        }
    }
}

impl Mutate for Condition {
    fn mutate(&self) -> Condition {
        let mutate_type: MutateType = rand::random();
        match mutate_type {
            MutateType::ThisLevel => {
                let mutation: Condition = rand::random();
                mutation
            },
            MutateType::NextLevel => {
                match *self {
                    Condition::True => Condition::False,
                    Condition::False => Condition::True,
                    Condition::Not(ref condition) => {
                        let mutation: Condition = condition.mutate();
                        Condition::Not(Box::new(mutation))
                    },
                    Condition::Or(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Condition = left.mutate();
                            Condition::Or(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Condition = right.mutate();
                            Condition::Or(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::And(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Condition = left.mutate();
                            Condition::And(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Condition = right.mutate();
                            Condition::And(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::Less(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Condition::Less(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Condition::Less(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::LessEqual(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Condition::LessEqual(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Condition::LessEqual(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::Equal(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Condition::Equal(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Condition::Equal(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::GreaterEqual(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Condition::GreaterEqual(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Condition::GreaterEqual(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::Greater(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Condition::Greater(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Condition::Greater(left.clone(), Box::new(mutation))
                        }
                    }
                }
            }
        }
    }
}

impl Mutate for Expression {
    fn mutate(&self) -> Expression {
        let mutate_type: MutateType = rand::random();
        match mutate_type {
            MutateType::ThisLevel => {
                let mutation: Expression = rand::random();
                mutation
            },
            MutateType::NextLevel => {
                match *self {
                    Expression::Constant(_) => {
                        let mutation: f32 = rand::random();
                        Expression::Constant(mutation)
                    },
                    Expression::Sensor(ref sensor) => {
                        let mutation: Sensor = sensor.mutate();
                        Expression::Sensor(mutation)
                    },
                    Expression::Plus(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Expression::Plus(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Expression::Plus(left.clone(),Box::new(mutation))
                        }
                    },
                    Expression::Minus(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Expression::Minus(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Expression::Minus(left.clone(), Box::new(mutation))
                        }
                    },
                    Expression::Multiply(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Expression::Multiply(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Expression::Multiply(left.clone(), Box::new(mutation))
                        }
                    },
                    Expression::Divide(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Expression::Divide(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Expression::Divide(left.clone(), Box::new(mutation))
                        }
                    },
                }
            }
        }
    }
}

impl Mutate for Sensor {
    fn mutate(&self) -> Sensor {
        let mutation: Sensor = rand::random();
        mutation
    }
}

impl Mutate for Command {
    fn mutate(&self) -> Command {
        let mutation: Command = rand::random();
        mutation
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use structure::{Expression,Sensor};

    #[derive(PartialEq,Debug)]
    enum Dummy {
        A, B,
    }

    impl super::Mutate for Dummy {
        fn mutate(&self) -> Dummy {
            match *self {
                Dummy::A => Dummy::B,
                Dummy::B => Dummy::A
            }
        }
    }

    #[test]
    fn should_mutate_mutate_dummy() {
        let original = Dummy::A;

        let mutation = original.mutate();

        assert_eq!(mutation, Dummy::B);
    }

    #[test]
    fn should_mutate_expression_without_panicing() {
        let constant: Expression = Expression::Constant(0.0);
        constant.mutate();

        let sensor: Expression = Expression::Sensor(Sensor::Vx);
        sensor.mutate();
    }
}
<commit_msg>Let mutate accept a rand::Rng<commit_after>/// The `mutate` trait returns a mutation version of a type that implements it.
///
/// Implementer should try to create persisted data-structures

extern crate rand;

use self::rand::Rng;
use super::super::structure::{Program,Condition,Expression,Sensor,Command};

pub trait Mutate {
    fn mutate<R: rand::Rng>(&self, rng: &mut R) -> Self;
}

enum MutateType {
    ThisLevel,
    NextLevel,
}

impl rand::Rand for MutateType {
    fn rand<R: rand::Rng>(_: &mut R) -> Self {
        pick![
            1, MutateType::ThisLevel,
            1, MutateType::NextLevel
        ]
    }
}

impl Mutate for Program {
    fn mutate<R: rand::Rng>(&self, rng: &mut R) -> Program {
        let mutate_type: MutateType = rand::random();
        match mutate_type {
            MutateType::ThisLevel => {
                let mutation: Program = rand::random();
                mutation
            },
            MutateType::NextLevel => {
                match *self {
                    Program::If(ref condition, ref left, ref right) => {
                        match rng.gen_range(0, 3) {
                            0 => { /* mutate condition */
                                      let mutation: Condition = condition.mutate(rng);
                                      Program::If(mutation, left.clone(), right.clone())
                            },
                            1 => { /* mutate left */
                                      let mutation: Program = left.mutate(rng);
                                      Program::If(condition.clone(), Box::new(mutation), right.clone())
                            },
                            2 => { /* mutate right */
                                      let mutation: Program = right.mutate(rng);
                                      Program::If(condition.clone(), left.clone(), Box::new(mutation))
                            },
                            _ => { panic!(/* this should not happen */)},
                        }
                    },
                    Program::Command(ref command) => {
                        let mutation: Command = command.mutate(rng);
                        Program::Command(mutation)
                    }
                }
            },
        }
    }
}

impl Mutate for Condition {
    fn mutate<R: rand::Rng>(&self, rng: &mut R) -> Condition {
        let mutate_type: MutateType = rand::random();
        match mutate_type {
            MutateType::ThisLevel => {
                let mutation: Condition = rand::random();
                mutation
            },
            MutateType::NextLevel => {
                match *self {
                    Condition::True => Condition::False,
                    Condition::False => Condition::True,
                    Condition::Not(ref condition) => {
                        let mutation: Condition = condition.mutate(rng);
                        Condition::Not(Box::new(mutation))
                    },
                    Condition::Or(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Condition = left.mutate(rng);
                            Condition::Or(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Condition = right.mutate(rng);
                            Condition::Or(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::And(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Condition = left.mutate(rng);
                            Condition::And(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Condition = right.mutate(rng);
                            Condition::And(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::Less(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate(rng);
                            Condition::Less(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate(rng);
                            Condition::Less(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::LessEqual(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate(rng);
                            Condition::LessEqual(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate(rng);
                            Condition::LessEqual(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::Equal(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate(rng);
                            Condition::Equal(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate(rng);
                            Condition::Equal(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::GreaterEqual(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate(rng);
                            Condition::GreaterEqual(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate(rng);
                            Condition::GreaterEqual(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::Greater(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate(rng);
                            Condition::Greater(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate(rng);
                            Condition::Greater(left.clone(), Box::new(mutation))
                        }
                    }
                }
            }
        }
    }
}

impl Mutate for Expression {
    fn mutate<R: rand::Rng>(&self, rng: &mut R) -> Expression {
        let mutate_type: MutateType = rand::random();
        match mutate_type {
            MutateType::ThisLevel => {
                let mutation: Expression = rand::random();
                mutation
            },
            MutateType::NextLevel => {
                match *self {
                    Expression::Constant(_) => {
                        let mutation: f32 = rand::random();
                        Expression::Constant(mutation)
                    },
                    Expression::Sensor(ref sensor) => {
                        let mutation: Sensor = sensor.mutate(rng);
                        Expression::Sensor(mutation)
                    },
                    Expression::Plus(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate(rng);
                            Expression::Plus(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate(rng);
                            Expression::Plus(left.clone(),Box::new(mutation))
                        }
                    },
                    Expression::Minus(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate(rng);
                            Expression::Minus(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate(rng);
                            Expression::Minus(left.clone(), Box::new(mutation))
                        }
                    },
                    Expression::Multiply(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate(rng);
                            Expression::Multiply(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate(rng);
                            Expression::Multiply(left.clone(), Box::new(mutation))
                        }
                    },
                    Expression::Divide(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate(rng);
                            Expression::Divide(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate(rng);
                            Expression::Divide(left.clone(), Box::new(mutation))
                        }
                    },
                }
            }
        }
    }
}

impl Mutate for Sensor {
    fn mutate<R: rand::Rng>(&self, rng: &mut R) -> Sensor {
        let mutation: Sensor = rand::random();
        mutation
    }
}

impl Mutate for Command {
    fn mutate<R: rand::Rng>(&self, rng: &mut R) -> Command {
        let mutation: Command = rand::random();
        mutation
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::rand::Rng;
    use structure::{Expression,Sensor};

    #[derive(PartialEq,Debug)]
    enum Dummy {
        A, B,
    }

    impl super::Mutate for Dummy {
        fn mutate<R: super::rand::Rng>(&self, rng: &mut R) -> Dummy {
            match *self {
                Dummy::A => Dummy::B,
                Dummy::B => Dummy::A
            }
        }
    }

    #[test]
    fn should_mutate_mutate_dummy() {
        let original = Dummy::A;
        let mut rng = super::rand::thread_rng();

        let mutation = original.mutate(&mut rng);

        assert_eq!(mutation, Dummy::B);
    }

    #[test]
    fn should_mutate_expression_without_panicing() {
        let mut rng = super::rand::thread_rng();
        let constant: Expression = Expression::Constant(0.0);
        constant.mutate(&mut rng);

        let sensor: Expression = Expression::Sensor(Sensor::Vx);
        sensor.mutate(&mut rng);
    }
}
<|endoftext|>


<commit_before>use super::book::Deal;
use std::ops;
use std::fmt;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct TradeStats {
  pub sum_sell: f64,
  pub sum_buy: f64,
  pub sum_sell_dest: f64,
  pub sum_buy_dest: f64,
  pub num_sell: u16,
  pub num_buy: u16,
}

// TradeStats operations

impl Default for TradeStats {
  fn default() -> TradeStats {
    TradeStats { sum_sell: 0.0, sum_sell_dest: 0.0, sum_buy: 0.0, sum_buy_dest: 0.0, num_sell: 0, num_buy: 0 }
  }
}

impl TradeStats {
  pub fn new(deals: &Vec<&Deal>) -> TradeStats {
    deals.into_iter().fold(TradeStats::default(), |acc, deal| acc + *deal)
  }
}

impl<'a> ops::Add<&'a TradeStats> for TradeStats {
  type Output = TradeStats;
  fn add(self, other: &TradeStats) -> TradeStats {
    TradeStats {
      sum_sell: self.sum_sell + other.sum_sell,
      sum_sell_dest: self.sum_sell_dest + other.sum_sell_dest,
      sum_buy: self.sum_buy + other.sum_buy,
      sum_buy_dest: self.sum_buy_dest + other.sum_buy_dest,
      num_sell: self.num_sell + other.num_sell,
      num_buy: self.num_buy + other.num_buy,
    }
  }
}

impl<'a> ops::Add<&'a Deal> for TradeStats {
  type Output = TradeStats;
  fn add(self, other: &Deal) -> TradeStats {
    let (buy, num_buy, buy_dest, sell, num_sell, sell_dest) =
      if other.amount > 0.0 { (other.amount, 1, other.amount*other.rate, 0.0, 0, 0.0) }
      else                  { (0.0, 0, 0.0, -other.amount, 1, -other.amount*other.rate) };
    TradeStats {
      sum_sell: self.sum_sell + sell,
      sum_sell_dest: self.sum_sell_dest + sell_dest,
      sum_buy: self.sum_buy + buy,
      sum_buy_dest: self.sum_buy_dest + buy_dest,
      num_sell: self.num_sell + num_sell,
      num_buy: self.num_buy + num_buy,
    }
  }
}

impl<'a> ops::Sub<&'a TradeStats> for TradeStats {
  type Output = TradeStats;
  fn sub(self, other: &TradeStats) -> TradeStats {
    let (mut sum_sell, mut sum_sell_dest, mut sum_buy, mut sum_buy_dest) = (0.0, 0.0, 0.0, 0.0);
    let num_sell = self.num_sell - other.num_sell;
    let num_buy = self.num_buy - other.num_buy;
    if num_sell > 0 {
      sum_sell = self.sum_sell - other.sum_sell;
      sum_sell_dest = self.sum_sell_dest - other.sum_sell_dest;
    };
    if num_buy > 0 {
      sum_buy = self.sum_buy - other.sum_buy;
      sum_buy_dest = self.sum_buy_dest - other.sum_buy_dest;
    };
    TradeStats { sum_sell, sum_sell_dest, sum_buy, sum_buy_dest, num_sell, num_buy }
  }
}

impl fmt::Display for TradeStats {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "SELL {} to {} rate {} num {} | BUY {} to {} rate {} num {}",
      self.sum_sell, self.sum_sell_dest, self.sum_sell_dest/self.sum_sell, self.num_sell,
      self.sum_buy, self.sum_buy_dest, self.sum_buy_dest/self.sum_buy, self.num_buy)
  }
}

pub trait TimeStats {
  fn update_stats_1s(&mut self)  -> Vec<&Deal>;
}

/**
 ** TESTS TESTS TESTS
 **/

#[cfg(test)]
mod tests {
  use super::TradeStats;
  use ::data::book::Deal;

  #[test]
  fn stats_default() {
    let default = TradeStats::default();
    assert_eq!(default.sum_buy, 0.0);
  }

  #[test]
  fn stats_new() {
    let deal = Deal { id: 1, rate: 0.1, amount: 10.0 };
    let deals = vec![&deal];
    let stats = TradeStats::new(&deals);
    assert_eq!(stats.sum_buy, 10.0);
  }

  #[test]
  fn stats_add_deal() {
    let deal = Deal { id: 1, rate: 0.1, amount: 10.0 };
    let stats = TradeStats::default() + &deal;
    assert_eq!(stats.sum_buy, 10.0);
  }

  #[test]
  fn stats_deals() {
    let deal1 = Deal { id: 1, rate: 0.1, amount: 10.0 };
    let deal2 = Deal { id: 2, rate: 0.1, amount: -10.0 };
    let stats = TradeStats::new(&vec![&deal1, &deal2]);
    assert_eq!((stats.sum_buy, stats.num_buy, stats.sum_buy_dest), (10.0, 1, 1.0));
    assert_eq!((stats.sum_sell, stats.num_sell, stats.sum_sell_dest), (10.0, 1, 1.0));
  }

  #[test]
  fn stats_sub() {
    let deal1 = Deal { id: 1, rate: 0.1, amount: 10.0 };
    let deal2 = Deal { id: 2, rate: 0.1, amount: -10.0 };
    let stats1 = TradeStats::new(&vec![&deal1, &deal2]);
    let stats2 = TradeStats::new(&vec![&deal2]);
    let stats = stats1 - &stats2;
    assert_eq!((stats.sum_buy, stats.num_buy), (10.0, 1));
    assert_eq!((stats.sum_sell, stats.num_sell), (0.0, 0));
  }

  #[test]
  fn stats_sub_exact() {
    let deal1 = Deal { id: 1, rate: 0.1, amount: 10.0 };
    let deal2 = Deal { id: 2, rate: 0.1, amount: -10.0 };
    let stats1 = TradeStats::new(&vec![&deal1, &deal2]);
    let stats2 = stats1.clone();
    let stats = stats1 - &stats2;
    assert_eq!(stats, TradeStats::default());
  }
}<commit_msg>fix tests<commit_after>use super::book::Deal;
use std::ops;
use std::fmt;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct TradeStats {
  pub sum_sell: f64,
  pub sum_buy: f64,
  pub sum_sell_dest: f64,
  pub sum_buy_dest: f64,
  pub num_sell: u16,
  pub num_buy: u16,
}

// TradeStats operations

impl Default for TradeStats {
  fn default() -> TradeStats {
    TradeStats { sum_sell: 0.0, sum_sell_dest: 0.0, sum_buy: 0.0, sum_buy_dest: 0.0, num_sell: 0, num_buy: 0 }
  }
}

impl TradeStats {
  pub fn new(deals: &Vec<&Deal>) -> TradeStats {
    deals.into_iter().fold(TradeStats::default(), |acc, deal| acc + *deal)
  }
}

impl<'a> ops::Add<&'a TradeStats> for TradeStats {
  type Output = TradeStats;
  fn add(self, other: &TradeStats) -> TradeStats {
    TradeStats {
      sum_sell: self.sum_sell + other.sum_sell,
      sum_sell_dest: self.sum_sell_dest + other.sum_sell_dest,
      sum_buy: self.sum_buy + other.sum_buy,
      sum_buy_dest: self.sum_buy_dest + other.sum_buy_dest,
      num_sell: self.num_sell + other.num_sell,
      num_buy: self.num_buy + other.num_buy,
    }
  }
}

impl<'a> ops::Add<&'a Deal> for TradeStats {
  type Output = TradeStats;
  fn add(self, other: &Deal) -> TradeStats {
    let (buy, num_buy, buy_dest, sell, num_sell, sell_dest) =
      if other.amount > 0.0 { (other.amount, 1, other.amount*other.rate, 0.0, 0, 0.0) }
      else                  { (0.0, 0, 0.0, -other.amount, 1, -other.amount*other.rate) };
    TradeStats {
      sum_sell: self.sum_sell + sell,
      sum_sell_dest: self.sum_sell_dest + sell_dest,
      sum_buy: self.sum_buy + buy,
      sum_buy_dest: self.sum_buy_dest + buy_dest,
      num_sell: self.num_sell + num_sell,
      num_buy: self.num_buy + num_buy,
    }
  }
}

impl<'a> ops::Sub<&'a TradeStats> for TradeStats {
  type Output = TradeStats;
  fn sub(self, other: &TradeStats) -> TradeStats {
    let (mut sum_sell, mut sum_sell_dest, mut sum_buy, mut sum_buy_dest) = (0.0, 0.0, 0.0, 0.0);
    let num_sell = self.num_sell - other.num_sell;
    let num_buy = self.num_buy - other.num_buy;
    if num_sell > 0 {
      sum_sell = self.sum_sell - other.sum_sell;
      sum_sell_dest = self.sum_sell_dest - other.sum_sell_dest;
    };
    if num_buy > 0 {
      sum_buy = self.sum_buy - other.sum_buy;
      sum_buy_dest = self.sum_buy_dest - other.sum_buy_dest;
    };
    TradeStats { sum_sell, sum_sell_dest, sum_buy, sum_buy_dest, num_sell, num_buy }
  }
}

impl fmt::Display for TradeStats {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "SELL {} to {} rate {} num {} | BUY {} to {} rate {} num {}",
      self.sum_sell, self.sum_sell_dest, self.sum_sell_dest/self.sum_sell, self.num_sell,
      self.sum_buy, self.sum_buy_dest, self.sum_buy_dest/self.sum_buy, self.num_buy)
  }
}

pub trait TimeStats {
  fn update_stats_1s(&mut self)  -> Vec<&Deal>;
}

/**
 ** TESTS TESTS TESTS
 **/

#[cfg(test)]
mod tests {
  use super::TradeStats;
  use ::data::book::Deal;
  use time::{Timespec};

  const TIME: Timespec = Timespec { sec: 1, nsec: 0 } ;

  #[test]
  fn stats_default() {
    let default = TradeStats::default();
    assert_eq!(default.sum_buy, 0.0);
  }

  #[test]
  fn stats_new() {
    let deal = Deal { time: TIME, id: 1, rate: 0.1, amount: 10.0 };
    let deals = vec![&deal];
    let stats = TradeStats::new(&deals);
    assert_eq!(stats.sum_buy, 10.0);
  }

  #[test]
  fn stats_add_deal() {
    let deal = Deal { time: TIME, id: 1, rate: 0.1, amount: 10.0 };
    let stats = TradeStats::default() + &deal;
    assert_eq!(stats.sum_buy, 10.0);
  }

  #[test]
  fn stats_deals() {
    let deal1 = Deal { time: TIME, id: 1, rate: 0.1, amount: 10.0 };
    let deal2 = Deal { time: TIME, id: 2, rate: 0.1, amount: -10.0 };
    let stats = TradeStats::new(&vec![&deal1, &deal2]);
    assert_eq!((stats.sum_buy, stats.num_buy, stats.sum_buy_dest), (10.0, 1, 1.0));
    assert_eq!((stats.sum_sell, stats.num_sell, stats.sum_sell_dest), (10.0, 1, 1.0));
  }

  #[test]
  fn stats_sub() {
    let deal1 = Deal { time: TIME, id: 1, rate: 0.1, amount: 10.0 };
    let deal2 = Deal { time: TIME, id: 2, rate: 0.1, amount: -10.0 };
    let stats1 = TradeStats::new(&vec![&deal1, &deal2]);
    let stats2 = TradeStats::new(&vec![&deal2]);
    let stats = stats1 - &stats2;
    assert_eq!((stats.sum_buy, stats.num_buy), (10.0, 1));
    assert_eq!((stats.sum_sell, stats.num_sell), (0.0, 0));
  }

  #[test]
  fn stats_sub_exact() {
    let deal1 = Deal { time: TIME, id: 1, rate: 0.1, amount: 10.0 };
    let deal2 = Deal { time: TIME, id: 2, rate: 0.1, amount: -10.0 };
    let stats1 = TradeStats::new(&vec![&deal1, &deal2]);
    let stats2 = stats1.clone();
    let stats = stats1 - &stats2;
    assert_eq!(stats, TradeStats::default());
  }
}<|endoftext|>


<commit_before>use gc::swiper::Region;

pub struct LargeObjectSpace {
    total: Region,
}

impl LargeObjectSpace {
    pub fn new(total: Region) -> LargeObjectSpace {
        LargeObjectSpace {
            total: total,
        }
    }
}<commit_msg>large allocs are connected as double-linked list<commit_after>use gc::Address;
use gc::swiper::Region;

pub struct LargeObjectSpace {
    total: Region,
}

impl LargeObjectSpace {
    pub fn new(total: Region) -> LargeObjectSpace {
        LargeObjectSpace {
            total: total,
        }
    }
}

struct LargeAlloc {
    prev: Address,
    next: Address,
}<|endoftext|>


<commit_before>use std::sync::mpsc;
use specs;
use specs::WriteStorage;
use game::constants::VIEW_DISTANCE;

#[derive(Clone, Debug)]
pub struct CameraInputState {
  pub distance: f32,
  pub x_pos: f32,
  pub y_pos: f32,
}

impl CameraInputState {
  pub fn new() -> CameraInputState {
    CameraInputState {
      distance: VIEW_DISTANCE,
      x_pos: 0.0,
      y_pos: 0.0,
    }
  }
}

impl specs::Component for CameraInputState {
  type Storage = specs::HashMapStorage<CameraInputState>;
}

#[derive(Debug)]
pub enum CameraControl {
  ZoomOut,
  ZoomIn,
  ZoomStop,
  Left,
  Right,
  Up,
  Down,
  XMoveStop,
  YMoveStop,
}

#[derive(Debug)]
pub struct CameraControlSystem {
  queue: mpsc::Receiver<CameraControl>,
  zoom_level: Option<f32>,
  x_move: Option<f32>,
  y_move: Option<f32>,
}

impl CameraControlSystem {
  pub fn new() -> (CameraControlSystem, mpsc::Sender<CameraControl>) {
    let (tx, rx) = mpsc::channel();
    (CameraControlSystem {
      queue: rx,
      zoom_level: None,
      x_move: None,
      y_move: None,
    }, tx)
  }
}

impl<'a> specs::System<'a> for CameraControlSystem {
  type SystemData = (WriteStorage<'a, CameraInputState>);
  fn run(&mut self, mut map_input: Self::SystemData) {
    use specs::Join;

    while let Ok(control) = self.queue.try_recv() {
      match control {
        CameraControl::ZoomIn => self.zoom_level = Some(2.0),
        CameraControl::ZoomOut => self.zoom_level = Some(-2.0),
        CameraControl::ZoomStop => self.zoom_level = None,
        CameraControl::Up => self.y_move = Some(-0.265),
        CameraControl::Down => self.y_move = Some(0.265),
        CameraControl::YMoveStop => self.y_move = None,
        CameraControl::Right => self.x_move = Some(0.265),
        CameraControl::Left => self.x_move = Some(-0.265),
        CameraControl::XMoveStop => self.x_move = None,
      }
    }
    if let Some(zoom) = self.zoom_level {
      for m in (&mut map_input).join() {
        if m.distance > 200.0 && zoom < 0.0 || m.distance < 1000.0 && zoom > 0.0 {
          m.distance += zoom;
        }
      }
    }
  }
}
<commit_msg>Remove dead code<commit_after>use std::sync::mpsc;
use specs;
use specs::WriteStorage;
use game::constants::VIEW_DISTANCE;

#[derive(Clone, Debug)]
pub struct CameraInputState {
  pub distance: f32,
  pub x_pos: f32,
  pub y_pos: f32,
}

impl CameraInputState {
  pub fn new() -> CameraInputState {
    CameraInputState {
      distance: VIEW_DISTANCE,
      x_pos: 0.0,
      y_pos: 0.0,
    }
  }
}

impl specs::Component for CameraInputState {
  type Storage = specs::HashMapStorage<CameraInputState>;
}

#[derive(Debug)]
pub enum CameraControl {
  ZoomOut,
  ZoomIn,
  ZoomStop,
  Left,
  Right,
  Up,
  Down,
  XMoveStop,
  YMoveStop,
}

#[derive(Debug)]
pub struct CameraControlSystem {
  queue: mpsc::Receiver<CameraControl>,
  zoom_level: Option<f32>,
  x_move: Option<f32>,
  y_move: Option<f32>,
}

impl CameraControlSystem {
  pub fn new() -> (CameraControlSystem, mpsc::Sender<CameraControl>) {
    let (tx, rx) = mpsc::channel();
    (CameraControlSystem {
      queue: rx,
      zoom_level: None,
      x_move: None,
      y_move: None,
    }, tx)
  }
}

impl<'a> specs::System<'a> for CameraControlSystem {
  type SystemData = (WriteStorage<'a, CameraInputState>);
  fn run(&mut self, mut map_input: Self::SystemData) {
    use specs::Join;

    while let Ok(control) = self.queue.try_recv() {
      match control {
        CameraControl::ZoomIn => self.zoom_level = Some(2.0),
        CameraControl::ZoomOut => self.zoom_level = Some(-2.0),
        CameraControl::ZoomStop => self.zoom_level = None,
        _ => (),
      }
    }
    if let Some(zoom) = self.zoom_level {
      for m in (&mut map_input).join() {
        if m.distance > 200.0 && zoom < 0.0 || m.distance < 1000.0 && zoom > 0.0 {
          m.distance += zoom;
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::DOMExceptionBinding;
use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionConstants;
use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionMethods;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use util::str::DOMString;

use std::borrow::ToOwned;

#[repr(u16)]
#[derive(Copy, Debug)]
#[jstraceable]
pub enum DOMErrorName {
    IndexSizeError = DOMExceptionConstants::INDEX_SIZE_ERR,
    HierarchyRequestError = DOMExceptionConstants::HIERARCHY_REQUEST_ERR,
    WrongDocumentError = DOMExceptionConstants::WRONG_DOCUMENT_ERR,
    InvalidCharacterError = DOMExceptionConstants::INVALID_CHARACTER_ERR,
    NoModificationAllowedError = DOMExceptionConstants::NO_MODIFICATION_ALLOWED_ERR,
    NotFoundError = DOMExceptionConstants::NOT_FOUND_ERR,
    NotSupportedError = DOMExceptionConstants::NOT_SUPPORTED_ERR,
    InvalidStateError = DOMExceptionConstants::INVALID_STATE_ERR,
    SyntaxError = DOMExceptionConstants::SYNTAX_ERR,
    InvalidModificationError = DOMExceptionConstants::INVALID_MODIFICATION_ERR,
    NamespaceError = DOMExceptionConstants::NAMESPACE_ERR,
    InvalidAccessError = DOMExceptionConstants::INVALID_ACCESS_ERR,
    SecurityError = DOMExceptionConstants::SECURITY_ERR,
    NetworkError = DOMExceptionConstants::NETWORK_ERR,
    AbortError = DOMExceptionConstants::ABORT_ERR,
    URLMismatchError = DOMExceptionConstants::URL_MISMATCH_ERR,
    QuotaExceededError = DOMExceptionConstants::QUOTA_EXCEEDED_ERR,
    TimeoutError = DOMExceptionConstants::TIMEOUT_ERR,
    InvalidNodeTypeError = DOMExceptionConstants::INVALID_NODE_TYPE_ERR,
    DataCloneError = DOMExceptionConstants::DATA_CLONE_ERR,
    EncodingError
}

#[dom_struct]
pub struct DOMException {
    reflector_: Reflector,
    code: DOMErrorName,
}

impl DOMException {
    fn new_inherited(code: DOMErrorName) -> DOMException {
        DOMException {
            reflector_: Reflector::new(),
            code: code,
        }
    }

    pub fn new(global: GlobalRef, code: DOMErrorName) -> Temporary<DOMException> {
        reflect_dom_object(box DOMException::new_inherited(code), global, DOMExceptionBinding::Wrap)
    }
}

impl<'a> DOMExceptionMethods for JSRef<'a, DOMException> {
    // http://dom.spec.whatwg.org/#dom-domexception-code
    fn Code(self) -> u16 {
        match self.code {
            // http://dom.spec.whatwg.org/#concept-throw
            DOMErrorName::EncodingError => 0,
            code => code as u16
        }
    }

    // http://dom.spec.whatwg.org/#error-names-0
    fn Name(self) -> DOMString {
        format!("{:?}", self.code)
    }

    // http://dom.spec.whatwg.org/#error-names-0
    fn Message(self) -> DOMString {
        let message = match self.code {
            DOMErrorName::IndexSizeError => "The index is not in the allowed range.",
            DOMErrorName::HierarchyRequestError => "The operation would yield an incorrect node tree.",
            DOMErrorName::WrongDocumentError => "The object is in the wrong document.",
            DOMErrorName::InvalidCharacterError => "The string contains invalid characters.",
            DOMErrorName::NoModificationAllowedError => "The object can not be modified.",
            DOMErrorName::NotFoundError => "The object can not be found here.",
            DOMErrorName::NotSupportedError => "The operation is not supported.",
            DOMErrorName::InvalidStateError => "The object is in an invalid state.",
            DOMErrorName::SyntaxError => "The string did not match the expected pattern.",
            DOMErrorName::InvalidModificationError => "The object can not be modified in this way.",
            DOMErrorName::NamespaceError => "The operation is not allowed by Namespaces in XML.",
            DOMErrorName::InvalidAccessError => "The object does not support the operation or argument.",
            DOMErrorName::SecurityError => "The operation is insecure.",
            DOMErrorName::NetworkError => "A network error occurred.",
            DOMErrorName::AbortError => "The operation was aborted.",
            DOMErrorName::URLMismatchError => "The given URL does not match another URL.",
            DOMErrorName::QuotaExceededError => "The quota has been exceeded.",
            DOMErrorName::TimeoutError => "The operation timed out.",
            DOMErrorName::InvalidNodeTypeError => "The supplied node is incorrect or has an incorrect ancestor for this operation.",
            DOMErrorName::DataCloneError => "The object can not be cloned.",
            DOMErrorName::EncodingError => "The encoding operation (either encoded or decoding) failed."
        };

        message.to_owned()
    }
}
<commit_msg>auto merge of #5530 : nmzaheer/servo/updateSpecLinks, r=saneyuki<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::DOMExceptionBinding;
use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionConstants;
use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionMethods;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use util::str::DOMString;

use std::borrow::ToOwned;

#[repr(u16)]
#[derive(Copy, Debug)]
#[jstraceable]
pub enum DOMErrorName {
    IndexSizeError = DOMExceptionConstants::INDEX_SIZE_ERR,
    HierarchyRequestError = DOMExceptionConstants::HIERARCHY_REQUEST_ERR,
    WrongDocumentError = DOMExceptionConstants::WRONG_DOCUMENT_ERR,
    InvalidCharacterError = DOMExceptionConstants::INVALID_CHARACTER_ERR,
    NoModificationAllowedError = DOMExceptionConstants::NO_MODIFICATION_ALLOWED_ERR,
    NotFoundError = DOMExceptionConstants::NOT_FOUND_ERR,
    NotSupportedError = DOMExceptionConstants::NOT_SUPPORTED_ERR,
    InvalidStateError = DOMExceptionConstants::INVALID_STATE_ERR,
    SyntaxError = DOMExceptionConstants::SYNTAX_ERR,
    InvalidModificationError = DOMExceptionConstants::INVALID_MODIFICATION_ERR,
    NamespaceError = DOMExceptionConstants::NAMESPACE_ERR,
    InvalidAccessError = DOMExceptionConstants::INVALID_ACCESS_ERR,
    SecurityError = DOMExceptionConstants::SECURITY_ERR,
    NetworkError = DOMExceptionConstants::NETWORK_ERR,
    AbortError = DOMExceptionConstants::ABORT_ERR,
    URLMismatchError = DOMExceptionConstants::URL_MISMATCH_ERR,
    QuotaExceededError = DOMExceptionConstants::QUOTA_EXCEEDED_ERR,
    TimeoutError = DOMExceptionConstants::TIMEOUT_ERR,
    InvalidNodeTypeError = DOMExceptionConstants::INVALID_NODE_TYPE_ERR,
    DataCloneError = DOMExceptionConstants::DATA_CLONE_ERR,
    EncodingError
}

#[dom_struct]
pub struct DOMException {
    reflector_: Reflector,
    code: DOMErrorName,
}

impl DOMException {
    fn new_inherited(code: DOMErrorName) -> DOMException {
        DOMException {
            reflector_: Reflector::new(),
            code: code,
        }
    }

    pub fn new(global: GlobalRef, code: DOMErrorName) -> Temporary<DOMException> {
        reflect_dom_object(box DOMException::new_inherited(code), global, DOMExceptionBinding::Wrap)
    }
}

impl<'a> DOMExceptionMethods for JSRef<'a, DOMException> {
    // http://heycam.github.io/webidl/#dfn-DOMException
    fn Code(self) -> u16 {
        match self.code {
            // http://heycam.github.io/webidl/#dfn-throw
            DOMErrorName::EncodingError => 0,
            code => code as u16
        }
    }

    // http://heycam.github.io/webidl/#idl-DOMException-error-names
    fn Name(self) -> DOMString {
        format!("{:?}", self.code)
    }

    // http://heycam.github.io/webidl/#error-names
    fn Message(self) -> DOMString {
        let message = match self.code {
            DOMErrorName::IndexSizeError => "The index is not in the allowed range.",
            DOMErrorName::HierarchyRequestError => "The operation would yield an incorrect node tree.",
            DOMErrorName::WrongDocumentError => "The object is in the wrong document.",
            DOMErrorName::InvalidCharacterError => "The string contains invalid characters.",
            DOMErrorName::NoModificationAllowedError => "The object can not be modified.",
            DOMErrorName::NotFoundError => "The object can not be found here.",
            DOMErrorName::NotSupportedError => "The operation is not supported.",
            DOMErrorName::InvalidStateError => "The object is in an invalid state.",
            DOMErrorName::SyntaxError => "The string did not match the expected pattern.",
            DOMErrorName::InvalidModificationError => "The object can not be modified in this way.",
            DOMErrorName::NamespaceError => "The operation is not allowed by Namespaces in XML.",
            DOMErrorName::InvalidAccessError => "The object does not support the operation or argument.",
            DOMErrorName::SecurityError => "The operation is insecure.",
            DOMErrorName::NetworkError => "A network error occurred.",
            DOMErrorName::AbortError => "The operation was aborted.",
            DOMErrorName::URLMismatchError => "The given URL does not match another URL.",
            DOMErrorName::QuotaExceededError => "The quota has been exceeded.",
            DOMErrorName::TimeoutError => "The operation timed out.",
            DOMErrorName::InvalidNodeTypeError => "The supplied node is incorrect or has an incorrect ancestor for this operation.",
            DOMErrorName::DataCloneError => "The object can not be cloned.",
            DOMErrorName::EncodingError => "The encoding operation (either encoded or decoding) failed."
        };

        message.to_owned()
    }
}
<|endoftext|>


<commit_before>// The implementation of this crate when jemalloc is turned on

use super::error::{ProfError, ProfResult};
use crate::AllocStats;
use jemalloc_ctl::{stats, Epoch as JeEpoch};
use jemallocator::ffi::malloc_stats_print;
use libc::{self, c_char, c_void};
use std::{io, ptr, slice};

pub type Allocator = jemallocator::Jemalloc;
pub const fn allocator() -> Allocator {
    jemallocator::Jemalloc
}

pub use self::profiling::{activate_prof, deactivate_prof, dump_prof};

pub fn dump_stats() -> String {
    let mut buf = Vec::with_capacity(1024);
    unsafe {
        malloc_stats_print(
            write_cb,
            &mut buf as *mut Vec<u8> as *mut c_void,
            ptr::null(),
        )
    }
    String::from_utf8_lossy(&buf).into_owned()
}

pub fn fetch_stats() -> io::Result<Option<AllocStats>> {
    // Stats are cached. Need to advance epoch to refresh.
    JeEpoch::new()?.advance()?;

    Ok(Some(vec![
        ("allocated", stats::allocated()?),
        ("active", stats::active()?),
        ("metadata", stats::metadata()?),
        ("resident", stats::resident()?),
        ("mapped", stats::mapped()?),
        ("retained", stats::retained()?),
    ]))
}

#[allow(clippy::cast_ptr_alignment)]
extern "C" fn write_cb(printer: *mut c_void, msg: *const c_char) {
    unsafe {
        // This cast from *c_void to *Vec<u8> looks like a bad
        // cast to clippy due to pointer alignment, but we know
        // what type the pointer is.
        let buf = &mut *(printer as *mut Vec<u8>);
        let len = libc::strlen(msg);
        let bytes = slice::from_raw_parts(msg as *const u8, len);
        buf.extend_from_slice(bytes);
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn dump_stats() {
        assert_ne!(super::dump_stats().len(), 0);
    }
}

#[cfg(feature = "mem-profiling")]
mod profiling {
    use std::ffi::CString;

    use jemallocator;
    use libc::c_char;

    use super::{ProfError, ProfResult};

    // C string should end with a '\0'.
    const PROF_ACTIVE: &'static [u8] = b"prof.active\0";
    const PROF_DUMP: &'static [u8] = b"prof.dump\0";

    pub fn activate_prof() -> ProfResult<()> {
        info!("start profiler");
        unsafe {
            if let Err(e) = jemallocator::mallctl_set(PROF_ACTIVE, true) {
                error!("failed to activate profiling: {}", e);
                return Err(ProfError::JemallocError(e));
            }
        }
        Ok(())
    }

    pub fn deactivate_prof() -> ProfResult<()> {
        info!("stop profiler");
        unsafe {
            if let Err(e) = jemallocator::mallctl_set(PROF_ACTIVE, false) {
                error!("failed to deactivate profiling: {}", e);
                return Err(ProfError::JemallocError(e));
            }
        }
        Ok(())
    }

    /// Dump the profile to the `path`.
    pub fn dump_prof(path: &str) -> ProfResult<()> {
        // TODO: return errors in this function
        let mut bytes = CString::new(path).unwrap().into_bytes_with_nul();
        let ptr = bytes.as_mut_ptr() as *mut c_char;
        let res = unsafe { jemallocator::mallctl_set(PROF_DUMP, ptr) };
        match res {
            Err(e) => {
                error!("failed to dump the profile to {:?}: {}", path, e);
                Err(ProfError::JemallocError(e))
            }
            Ok(_) => {
                info!("dump profile to {}", path);
                Ok(())
            }
        }
    }

    #[cfg(test)]
    mod tests {
        use jemallocator;
        use std::fs;
        use tempfile::Builder;

        const OPT_PROF: &'static [u8] = b"opt.prof\0";

        fn is_profiling_on() -> bool {
            let mut prof = false;
            let res = unsafe { jemallocator::mallctl_fetch(OPT_PROF, &mut prof) };
            match res {
                Err(e) => {
                    // Shouldn't be possible since mem-profiling is set
                    panic!("is_profiling_on: {:?}", e);
                }
                Ok(_) => prof,
            }
        }

        // Only trigger this test with jemallocs `opt.prof` set to
        // true ala `MALLOC_CONF="prof:true"`. It can be run by
        // passing `-- --ignored` to `cargo test -p tikv_alloc`.
        //
        // TODO: could probably unignore this by running a second
        // copy of the executable with MALLOC_CONF set.
        //
        // TODO: need a test for the dump_prof(None) case, but
        // the cleanup afterward is not simple.
        #[test]
        #[ignore]
        fn test_profiling_memory() {
            // Make sure somebody has turned on profiling
            assert!(is_profiling_on(), r#"Set MALLOC_CONF="prof:true""#);

            let dir = Builder::new()
                .prefix("test_profiling_memory")
                .tempdir()
                .unwrap();

            let os_path = dir.path().to_path_buf().join("test1.dump").into_os_string();
            let path = os_path.into_string().unwrap();
            super::dump_prof(&path);

            let os_path = dir.path().to_path_buf().join("test2.dump").into_os_string();
            let path = os_path.into_string().unwrap();
            super::dump_prof(&path);

            let files = fs::read_dir(dir.path()).unwrap().count();
            assert_eq!(files, 2);

            // Find the created files and check properties that
            // indicate they contain something interesting
            let mut prof_count = 0;
            for file_entry in fs::read_dir(dir.path()).unwrap() {
                let file_entry = file_entry.unwrap();
                let path = file_entry.path().to_str().unwrap().to_owned();
                if path.contains("test1.dump") || path.contains("test2.dump") {
                    let metadata = file_entry.metadata().unwrap();
                    let file_len = metadata.len();
                    assert!(file_len > 10); // arbitrary number
                    prof_count += 1
                }
            }
            assert!(prof_count == 2);
        }
    }
}

#[cfg(not(feature = "mem-profiling"))]
mod profiling {
    use super::{ProfError, ProfResult};

    pub fn dump_prof(_path: &str) -> ProfResult<()> {
        Err(ProfError::MemProfilingNotEnabled)
    }
    pub fn activate_prof() -> ProfResult<()> {
        Err(ProfError::MemProfilingNotEnabled)
    }
    pub fn deactivate_prof() -> ProfResult<()> {
        Err(ProfError::MemProfilingNotEnabled)
    }
}
<commit_msg>Add jemalloc metrics (#5448)<commit_after>// The implementation of this crate when jemalloc is turned on

use super::error::{ProfError, ProfResult};
use crate::AllocStats;
use jemalloc_ctl::{stats, Epoch as JeEpoch};
use jemallocator::ffi::malloc_stats_print;
use libc::{self, c_char, c_void};
use std::{io, ptr, slice};

pub type Allocator = jemallocator::Jemalloc;
pub const fn allocator() -> Allocator {
    jemallocator::Jemalloc
}

pub use self::profiling::{activate_prof, deactivate_prof, dump_prof};

pub fn dump_stats() -> String {
    let mut buf = Vec::with_capacity(1024);
    unsafe {
        malloc_stats_print(
            write_cb,
            &mut buf as *mut Vec<u8> as *mut c_void,
            ptr::null(),
        )
    }
    String::from_utf8_lossy(&buf).into_owned()
}

pub fn fetch_stats() -> io::Result<Option<AllocStats>> {
    // Stats are cached. Need to advance epoch to refresh.
    JeEpoch::new()?.advance()?;

    Ok(Some(vec![
        ("allocated", stats::allocated()?),
        ("active", stats::active()?),
        ("metadata", stats::metadata()?),
        ("resident", stats::resident()?),
        ("mapped", stats::mapped()?),
        ("retained", stats::retained()?),
        (
            "dirty",
            stats::resident()? - stats::active()? - stats::metadata()?,
        ),
        ("fragmentation", stats::active()? - stats::allocated()?),
    ]))
}

#[allow(clippy::cast_ptr_alignment)]
extern "C" fn write_cb(printer: *mut c_void, msg: *const c_char) {
    unsafe {
        // This cast from *c_void to *Vec<u8> looks like a bad
        // cast to clippy due to pointer alignment, but we know
        // what type the pointer is.
        let buf = &mut *(printer as *mut Vec<u8>);
        let len = libc::strlen(msg);
        let bytes = slice::from_raw_parts(msg as *const u8, len);
        buf.extend_from_slice(bytes);
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn dump_stats() {
        assert_ne!(super::dump_stats().len(), 0);
    }
}

#[cfg(feature = "mem-profiling")]
mod profiling {
    use std::ffi::CString;

    use jemallocator;
    use libc::c_char;

    use super::{ProfError, ProfResult};

    // C string should end with a '\0'.
    const PROF_ACTIVE: &'static [u8] = b"prof.active\0";
    const PROF_DUMP: &'static [u8] = b"prof.dump\0";

    pub fn activate_prof() -> ProfResult<()> {
        info!("start profiler");
        unsafe {
            if let Err(e) = jemallocator::mallctl_set(PROF_ACTIVE, true) {
                error!("failed to activate profiling: {}", e);
                return Err(ProfError::JemallocError(e));
            }
        }
        Ok(())
    }

    pub fn deactivate_prof() -> ProfResult<()> {
        info!("stop profiler");
        unsafe {
            if let Err(e) = jemallocator::mallctl_set(PROF_ACTIVE, false) {
                error!("failed to deactivate profiling: {}", e);
                return Err(ProfError::JemallocError(e));
            }
        }
        Ok(())
    }

    /// Dump the profile to the `path`.
    pub fn dump_prof(path: &str) -> ProfResult<()> {
        // TODO: return errors in this function
        let mut bytes = CString::new(path).unwrap().into_bytes_with_nul();
        let ptr = bytes.as_mut_ptr() as *mut c_char;
        let res = unsafe { jemallocator::mallctl_set(PROF_DUMP, ptr) };
        match res {
            Err(e) => {
                error!("failed to dump the profile to {:?}: {}", path, e);
                Err(ProfError::JemallocError(e))
            }
            Ok(_) => {
                info!("dump profile to {}", path);
                Ok(())
            }
        }
    }

    #[cfg(test)]
    mod tests {
        use jemallocator;
        use std::fs;
        use tempfile::Builder;

        const OPT_PROF: &'static [u8] = b"opt.prof\0";

        fn is_profiling_on() -> bool {
            let mut prof = false;
            let res = unsafe { jemallocator::mallctl_fetch(OPT_PROF, &mut prof) };
            match res {
                Err(e) => {
                    // Shouldn't be possible since mem-profiling is set
                    panic!("is_profiling_on: {:?}", e);
                }
                Ok(_) => prof,
            }
        }

        // Only trigger this test with jemallocs `opt.prof` set to
        // true ala `MALLOC_CONF="prof:true"`. It can be run by
        // passing `-- --ignored` to `cargo test -p tikv_alloc`.
        //
        // TODO: could probably unignore this by running a second
        // copy of the executable with MALLOC_CONF set.
        //
        // TODO: need a test for the dump_prof(None) case, but
        // the cleanup afterward is not simple.
        #[test]
        #[ignore]
        fn test_profiling_memory() {
            // Make sure somebody has turned on profiling
            assert!(is_profiling_on(), r#"Set MALLOC_CONF="prof:true""#);

            let dir = Builder::new()
                .prefix("test_profiling_memory")
                .tempdir()
                .unwrap();

            let os_path = dir.path().to_path_buf().join("test1.dump").into_os_string();
            let path = os_path.into_string().unwrap();
            super::dump_prof(&path);

            let os_path = dir.path().to_path_buf().join("test2.dump").into_os_string();
            let path = os_path.into_string().unwrap();
            super::dump_prof(&path);

            let files = fs::read_dir(dir.path()).unwrap().count();
            assert_eq!(files, 2);

            // Find the created files and check properties that
            // indicate they contain something interesting
            let mut prof_count = 0;
            for file_entry in fs::read_dir(dir.path()).unwrap() {
                let file_entry = file_entry.unwrap();
                let path = file_entry.path().to_str().unwrap().to_owned();
                if path.contains("test1.dump") || path.contains("test2.dump") {
                    let metadata = file_entry.metadata().unwrap();
                    let file_len = metadata.len();
                    assert!(file_len > 10); // arbitrary number
                    prof_count += 1
                }
            }
            assert!(prof_count == 2);
        }
    }
}

#[cfg(not(feature = "mem-profiling"))]
mod profiling {
    use super::{ProfError, ProfResult};

    pub fn dump_prof(_path: &str) -> ProfResult<()> {
        Err(ProfError::MemProfilingNotEnabled)
    }
    pub fn activate_prof() -> ProfResult<()> {
        Err(ProfError::MemProfilingNotEnabled)
    }
    pub fn deactivate_prof() -> ProfResult<()> {
        Err(ProfError::MemProfilingNotEnabled)
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

const DEFAULT_STORE_PATH: &'static str = "";
const DEFAULT_SCHED_CAPACITY: usize = 10240;
const DEFAULT_SCHED_MSG_PER_TICK: usize = 1024;
const DEFAULT_SCHED_CONCURRENCY: usize = 10240;
const DEFAULT_SCHED_WORKER_POOL_SIZE: usize = 4;
const DEFAULT_SCHED_TOO_BUSY_THRESHOLD: usize = 100;

#[derive(Clone, Debug)]
pub struct Config {
    pub path: String,
    pub sched_notify_capacity: usize,
    pub sched_msg_per_tick: usize,
    pub sched_concurrency: usize,
    pub sched_worker_pool_size: usize,
    pub sched_too_busy_threshold: usize,
}

impl Default for Config {
    fn default() -> Config {
        Config {
            path: DEFAULT_STORE_PATH.to_owned(),
            sched_notify_capacity: DEFAULT_SCHED_CAPACITY,
            sched_msg_per_tick: DEFAULT_SCHED_MSG_PER_TICK,
            sched_concurrency: DEFAULT_SCHED_CONCURRENCY,
            sched_worker_pool_size: DEFAULT_SCHED_WORKER_POOL_SIZE,
            sched_too_busy_threshold: DEFAULT_SCHED_TOO_BUSY_THRESHOLD,
        }
    }
}

impl Config {
    pub fn new() -> Config {
        Config::default()
    }
}
<commit_msg>tuning scheduler too busy threshold (#1235)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

const DEFAULT_STORE_PATH: &'static str = "";
const DEFAULT_SCHED_CAPACITY: usize = 10240;
const DEFAULT_SCHED_MSG_PER_TICK: usize = 1024;
const DEFAULT_SCHED_CONCURRENCY: usize = 10240;
const DEFAULT_SCHED_WORKER_POOL_SIZE: usize = 4;
const DEFAULT_SCHED_TOO_BUSY_THRESHOLD: usize = 500;

#[derive(Clone, Debug)]
pub struct Config {
    pub path: String,
    pub sched_notify_capacity: usize,
    pub sched_msg_per_tick: usize,
    pub sched_concurrency: usize,
    pub sched_worker_pool_size: usize,
    pub sched_too_busy_threshold: usize,
}

impl Default for Config {
    fn default() -> Config {
        Config {
            path: DEFAULT_STORE_PATH.to_owned(),
            sched_notify_capacity: DEFAULT_SCHED_CAPACITY,
            sched_msg_per_tick: DEFAULT_SCHED_MSG_PER_TICK,
            sched_concurrency: DEFAULT_SCHED_CONCURRENCY,
            sched_worker_pool_size: DEFAULT_SCHED_WORKER_POOL_SIZE,
            sched_too_busy_threshold: DEFAULT_SCHED_TOO_BUSY_THRESHOLD,
        }
    }
}

impl Config {
    pub fn new() -> Config {
        Config::default()
    }
}
<|endoftext|>


<commit_before>/// Maximum order of the fixed predictors permitted by the format.
pub const MAX_FIXED_ORDER: usize = 4;

/// Maximum LPC order permitted by the format.
pub const MAX_LPC_ORDER: usize   = 32;

/// A single channel of audio data.
pub struct Subframe {
  /// Data containing one of the four different types of subframes.
  pub data: Data,
  /// Number of wasted bits within each sample.
  pub wasted_bits: u32,
}

/// General enum that holds all the different subframe data types.
#[derive(Debug, PartialEq, Eq)]
pub enum Data {
  /// A single value that represents a constant subframe.
  Constant(i32),
  /// An uncompressed subframe.
  Verbatim(Vec<i32>),
  /// Fixed linear prediction subframe.
  Fixed(Fixed),
  /// FIR linear prediction subframe.
  LPC(LPC),
}

/// Fixed linear prediction subframe.
#[derive(Debug, PartialEq, Eq)]
pub struct Fixed {
  /// Residual coding method.
  pub entropy_coding_method: EntropyCodingMethod,
  /// Polynomial order.
  pub order: u8,
  /// Samples used to warm up, or prime, the predictor.
  pub warmup: [i32; MAX_FIXED_ORDER],
  /// Remaining samples after the warm up samples.
  pub residual: Vec<i32>,
}

/// Finite Impulse Response (FIR) linear prediction subframe.
#[derive(Debug, PartialEq, Eq)]
pub struct LPC {
  /// Residual coding method.
  pub entropy_coding_method: EntropyCodingMethod,
  /// FIR order.
  pub order: u8,
  /// Quantized FIR filter coefficient precision in bits.
  pub qlp_coeff_precision: u8,
  /// Quantized linear predictor coefficient shift needed in bits.
  pub quantization_level: i8,
  /// FIR filter coefficients.
  pub qlp_coefficients: [i32; MAX_LPC_ORDER],
  /// Samples used to warm up, or prime, the predictor.
  pub warmup: [i32; MAX_LPC_ORDER],
  /// Remaining samples after the warm up samples.
  pub residual: Vec<i32>,
}

/// Header for the entropy coding method.
#[derive(Debug, PartialEq, Eq)]
pub struct EntropyCodingMethod {
  /// The type of coding method being used.
  pub method_type: CodingMethod,
  /// Data for each entropy coding method partition.
  pub data: PartitionedRice,
}

/// The available entropy coding methods.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum CodingMethod {
  /// Coding partition with a 4-bit Rice parameter.
  PartitionedRice,
  /// Coding partition with a 5-bit Rice parameter.
  PartitionedRice2,
}

/// Header for a Rice partitioned residual.
#[derive(Debug, PartialEq, Eq)]
pub struct PartitionedRice {
  /// Partition order.
  pub order: u32,
  /// Rice parameters and/or raw bits.
  pub contents: PartitionedRiceContents,
}

/// Contents of a Rice partitioned residual.
#[derive(Debug, PartialEq, Eq)]
pub struct PartitionedRiceContents {
  /// Rice parameters for each context.
  pub parameters: Vec<u32>,
  /// Widths for escaped-coded partitions.
  pub raw_bits: Vec<u32>,
}

impl PartitionedRiceContents {
  pub fn new(capacity: usize) -> PartitionedRiceContents {
    let mut parameters = Vec::with_capacity(capacity);
    let mut raw_bits   = Vec::with_capacity(capacity);

    unsafe {
      parameters.set_len(capacity);
      raw_bits.set_len(capacity);
    }

    PartitionedRiceContents {
      parameters: parameters,
      raw_bits: raw_bits,
    }
  }
}
<commit_msg>Change the types within `PartitionedRiceContents`<commit_after>/// Maximum order of the fixed predictors permitted by the format.
pub const MAX_FIXED_ORDER: usize = 4;

/// Maximum LPC order permitted by the format.
pub const MAX_LPC_ORDER: usize   = 32;

/// A single channel of audio data.
pub struct Subframe {
  /// Data containing one of the four different types of subframes.
  pub data: Data,
  /// Number of wasted bits within each sample.
  pub wasted_bits: u32,
}

/// General enum that holds all the different subframe data types.
#[derive(Debug, PartialEq, Eq)]
pub enum Data {
  /// A single value that represents a constant subframe.
  Constant(i32),
  /// An uncompressed subframe.
  Verbatim(Vec<i32>),
  /// Fixed linear prediction subframe.
  Fixed(Fixed),
  /// FIR linear prediction subframe.
  LPC(LPC),
}

/// Fixed linear prediction subframe.
#[derive(Debug, PartialEq, Eq)]
pub struct Fixed {
  /// Residual coding method.
  pub entropy_coding_method: EntropyCodingMethod,
  /// Polynomial order.
  pub order: u8,
  /// Samples used to warm up, or prime, the predictor.
  pub warmup: [i32; MAX_FIXED_ORDER],
  /// Remaining samples after the warm up samples.
  pub residual: Vec<i32>,
}

/// Finite Impulse Response (FIR) linear prediction subframe.
#[derive(Debug, PartialEq, Eq)]
pub struct LPC {
  /// Residual coding method.
  pub entropy_coding_method: EntropyCodingMethod,
  /// FIR order.
  pub order: u8,
  /// Quantized FIR filter coefficient precision in bits.
  pub qlp_coeff_precision: u8,
  /// Quantized linear predictor coefficient shift needed in bits.
  pub quantization_level: i8,
  /// FIR filter coefficients.
  pub qlp_coefficients: [i32; MAX_LPC_ORDER],
  /// Samples used to warm up, or prime, the predictor.
  pub warmup: [i32; MAX_LPC_ORDER],
  /// Remaining samples after the warm up samples.
  pub residual: Vec<i32>,
}

/// Header for the entropy coding method.
#[derive(Debug, PartialEq, Eq)]
pub struct EntropyCodingMethod {
  /// The type of coding method being used.
  pub method_type: CodingMethod,
  /// Data for each entropy coding method partition.
  pub data: PartitionedRice,
}

/// The available entropy coding methods.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum CodingMethod {
  /// Coding partition with a 4-bit Rice parameter.
  PartitionedRice,
  /// Coding partition with a 5-bit Rice parameter.
  PartitionedRice2,
}

/// Header for a Rice partitioned residual.
#[derive(Debug, PartialEq, Eq)]
pub struct PartitionedRice {
  /// Partition order.
  pub order: u32,
  /// Rice parameters and/or raw bits.
  pub contents: PartitionedRiceContents,
}

/// Contents of a Rice partitioned residual.
#[derive(Debug, PartialEq, Eq)]
pub struct PartitionedRiceContents {
  /// Size of `parameters` and `raw_bits` within the data buffer.
  pub capacity: usize,
  /// Data buffer containing both `parameters` and `raw_bits`.
  pub data: Vec<u32>,
}

impl PartitionedRiceContents {
  pub fn new(capacity: usize) -> PartitionedRiceContents {
    let full_capacity = capacity * 2;
    let mut data      = Vec::with_capacity(full_capacity);

    unsafe { data.set_len(full_capacity) }

    PartitionedRiceContents {
      capacity: capacity,
      data: data,
    }
  }
}
<|endoftext|>