<commit_before>//! Defines the BSDF which acts as a container for composing the various BRDFs
//! and BTDFs that describe the surface's properties

use std::cmp;
use enum_set::EnumSet;

use linalg::{self, Normal, Vector, Point};
use film::Colorf;
use geometry::DifferentialGeometry;
use bxdf::{BxDF, BxDFType};
use sampler::Sample;

/// The BSDF contains the various BRDFs and BTDFs that describe the surface's properties
/// at some point. It also transforms incident and outgoing light directions into
/// shading space to make the BxDFs easier to implement.
/// TODO: We really need the memory pool. Each time we get the bsdf from a
/// material we need to allocate a decent amount of stuff since they each need
/// their own tangent, bitangent and differential geometry reference.
pub struct BSDF<'a> {
    /// The hit point
    pub p: Point,
    /// Shading normal, may be perturbed by bump mapping
    pub n: Normal,
    /// The actual geometry normal
    pub ng: Normal,
    /// Tangent vector for the surface
    pub tan: Vector,
    /// Bitangent vector for the surface
    pub bitan: Vector,
    /// Refractive index of the geometry
    pub eta: f32,
    bxdfs: &'a [&'a BxDF],
}

impl<'a> BSDF<'a> {
    /// Create a new BSDF using the BxDFs passed to shade the differential geometry with
    /// refractive index `eta`
    pub fn new<'b>(bxdfs: &'a [&'a BxDF], eta: f32, dg: &DifferentialGeometry<'b>) -> BSDF<'a> {
        let n = dg.n.normalized();
        let mut bitan = dg.dp_du.normalized();
        let tan = linalg::cross(&n, &bitan);
        bitan = linalg::cross(&tan, &n);
        BSDF { p: dg.p, n: n, ng: dg.ng, tan: tan, bitan: bitan, bxdfs: bxdfs, eta: eta }
    }
    /// Return the total number of BxDFs
    pub fn num_bxdfs(&self) -> usize { self.bxdfs.len() }
    /// Return the number of BxDFs matching the flags
    pub fn num_matching(&self, flags: EnumSet<BxDFType>) -> usize {
        self.bxdfs.iter().filter(|x| x.matches(flags)).count()
    }
    /// Transform the vector from world space to shading space
    pub fn to_shading(&self, v: &Vector) -> Vector {
        Vector::new(linalg::dot(v, &self.bitan), linalg::dot(v, &self.tan),
                    linalg::dot(v, &self.n))
    }
    /// Transform the vectro from shading space to world space
    pub fn from_shading(&self, v: &Vector) -> Vector {
        Vector::new(self.bitan.x * v.x + self.tan.x * v.y + self.n.x * v.z,
                    self.bitan.y * v.x + self.tan.y * v.y + self.n.y * v.z,
                    self.bitan.z * v.x + self.tan.z * v.y + self.n.z * v.z)
    }
    /// Evaluate the BSDF for the outgoing and incident light directions
    /// `w_o` and `w_i` in world space, sampling the desired subset of BxDFs
    /// selected by the flags passed. `wo_world` and `wi_world` should point from
    /// the hit point in the outgoing and incident light directions respectively.
    pub fn eval(&self, wo_world: &Vector, wi_world: &Vector, mut flags: EnumSet<BxDFType>) -> Colorf {
        let w_o = self.to_shading(wo_world).normalized();
        let w_i = self.to_shading(wi_world).normalized();
        // Determine if we should evaluate reflection or transmission based on the
        // geometry normal and the light directions
        if w_o.z * w_i.z > 0.0 {
            flags.remove(&BxDFType::Transmission);
        } else {
            flags.remove(&BxDFType::Reflection);
        }
        // Find all matching BxDFs and add their contribution to the material's color
        self.bxdfs.iter().filter_map(|x| if x.matches(flags) { Some(x.eval(&w_o, &w_i)) } else { None })
            .fold(Colorf::broadcast(0.0), |x, y| x + y)
    }
    /// Sample a component of the BSDF to get an incident light direction for light
    /// leaving the surface along `w_o`.
    /// `samples` are the 3 random values to use when sampling a component of the BSDF
    /// and a the chosen BSDF
    /// Returns the color, direction, pdf and the type of BxDF that was sampled.
    pub fn sample(&self, wo_world: &Vector, flags: EnumSet<BxDFType>, samples: &Sample)
        -> (Colorf, Vector, f32, EnumSet<BxDFType>)
    {
        let n_matching = self.num_matching(flags);
        if n_matching == 0 {
            return (Colorf::broadcast(0.0), Vector::broadcast(0.0), 0.0, EnumSet::new());
        }
        let comp = cmp::min((samples.one_d * n_matching as f32) as usize, n_matching - 1);
        let bxdf = self.matching_at(comp, flags);
        let w_o = self.to_shading(wo_world).normalized();
        let (mut f, w_i, mut pdf) = bxdf.sample(&w_o, &samples.two_d);
        if w_i.length_sqr() == 0.0 {
            return (Colorf::broadcast(0.0), Vector::broadcast(0.0), 0.0, EnumSet::new());
        }
        let wi_world = self.from_shading(&w_i).normalized();

        // TODO: We re-use our functions but actually do a lot of redundant computation. I'm not
        // sure that the compiler will eliminate it. Should just copy in the code from pdf and eval
        if !bxdf.bxdf_type().contains(&BxDFType::Specular) && n_matching > 1 {
            pdf = self.pdf(wo_world, &wi_world, flags);
        }
        if n_matching > 1 {
            pdf /= n_matching as f32;
        }

        if !bxdf.bxdf_type().contains(&BxDFType::Specular) {
            f = self.eval(wo_world, &wi_world, flags);
        }
        (f, wi_world, pdf, bxdf.bxdf_type())
    }
    /// Compute the pdf for sampling the pair of incident and outgoing light directions for
    /// the BxDFs matching the flags set
    pub fn pdf(&self, wo_world: &Vector, wi_world: &Vector, flags: EnumSet<BxDFType>) -> f32 {
        let w_o = self.to_shading(wo_world).normalized();
        let w_i = self.to_shading(wi_world).normalized();
        let (pdf_val, n_comps) = self.bxdfs.iter()
            .filter_map(|x| if x.matches(flags) { Some(x.pdf(&w_o, &w_i)) } else { None })
            .fold((0.0, 0), |(p, n), y| (p + y, n + 1));
        if n_comps > 0 {
            pdf_val / n_comps as f32
        } else {
            0.0
        }
    }
    /// Get the `i`th BxDF that matches the flags passed. There should not be fewer than i
    /// BxDFs that match the flags
    fn matching_at(&self, i: usize, flags: EnumSet<BxDFType>) -> &BxDF {
        let mut it = self.bxdfs.iter().filter(|x| x.matches(flags)).skip(i);
        match it.next() {
            Some(b) => *b,
            None => panic!("Out of bounds index for BxDF type {:?}", flags)
        }
    }
}

<commit_msg>don't divide PDF twice by num matching components<commit_after>//! Defines the BSDF which acts as a container for composing the various BRDFs
//! and BTDFs that describe the surface's properties

use std::cmp;
use enum_set::EnumSet;

use linalg::{self, Normal, Vector, Point};
use film::Colorf;
use geometry::DifferentialGeometry;
use bxdf::{BxDF, BxDFType};
use sampler::Sample;

/// The BSDF contains the various BRDFs and BTDFs that describe the surface's properties
/// at some point. It also transforms incident and outgoing light directions into
/// shading space to make the BxDFs easier to implement.
/// TODO: We really need the memory pool. Each time we get the bsdf from a
/// material we need to allocate a decent amount of stuff since they each need
/// their own tangent, bitangent and differential geometry reference.
pub struct BSDF<'a> {
    /// The hit point
    pub p: Point,
    /// Shading normal, may be perturbed by bump mapping
    pub n: Normal,
    /// The actual geometry normal
    pub ng: Normal,
    /// Tangent vector for the surface
    pub tan: Vector,
    /// Bitangent vector for the surface
    pub bitan: Vector,
    /// Refractive index of the geometry
    pub eta: f32,
    bxdfs: &'a [&'a BxDF],
}

impl<'a> BSDF<'a> {
    /// Create a new BSDF using the BxDFs passed to shade the differential geometry with
    /// refractive index `eta`
    pub fn new<'b>(bxdfs: &'a [&'a BxDF], eta: f32, dg: &DifferentialGeometry<'b>) -> BSDF<'a> {
        let n = dg.n.normalized();
        let mut bitan = dg.dp_du.normalized();
        let tan = linalg::cross(&n, &bitan);
        bitan = linalg::cross(&tan, &n);
        BSDF { p: dg.p, n: n, ng: dg.ng, tan: tan, bitan: bitan, bxdfs: bxdfs, eta: eta }
    }
    /// Return the total number of BxDFs
    pub fn num_bxdfs(&self) -> usize { self.bxdfs.len() }
    /// Return the number of BxDFs matching the flags
    pub fn num_matching(&self, flags: EnumSet<BxDFType>) -> usize {
        self.bxdfs.iter().filter(|x| x.matches(flags)).count()
    }
    /// Transform the vector from world space to shading space
    pub fn to_shading(&self, v: &Vector) -> Vector {
        Vector::new(linalg::dot(v, &self.bitan), linalg::dot(v, &self.tan),
                    linalg::dot(v, &self.n))
    }
    /// Transform the vectro from shading space to world space
    pub fn from_shading(&self, v: &Vector) -> Vector {
        Vector::new(self.bitan.x * v.x + self.tan.x * v.y + self.n.x * v.z,
                    self.bitan.y * v.x + self.tan.y * v.y + self.n.y * v.z,
                    self.bitan.z * v.x + self.tan.z * v.y + self.n.z * v.z)
    }
    /// Evaluate the BSDF for the outgoing and incident light directions
    /// `w_o` and `w_i` in world space, sampling the desired subset of BxDFs
    /// selected by the flags passed. `wo_world` and `wi_world` should point from
    /// the hit point in the outgoing and incident light directions respectively.
    pub fn eval(&self, wo_world: &Vector, wi_world: &Vector, mut flags: EnumSet<BxDFType>) -> Colorf {
        let w_o = self.to_shading(wo_world).normalized();
        let w_i = self.to_shading(wi_world).normalized();
        // Determine if we should evaluate reflection or transmission based on the
        // geometry normal and the light directions
        if w_o.z * w_i.z > 0.0 {
            flags.remove(&BxDFType::Transmission);
        } else {
            flags.remove(&BxDFType::Reflection);
        }
        // Find all matching BxDFs and add their contribution to the material's color
        self.bxdfs.iter().filter_map(|x| if x.matches(flags) { Some(x.eval(&w_o, &w_i)) } else { None })
            .fold(Colorf::broadcast(0.0), |x, y| x + y)
    }
    /// Sample a component of the BSDF to get an incident light direction for light
    /// leaving the surface along `w_o`.
    /// `samples` are the 3 random values to use when sampling a component of the BSDF
    /// and a the chosen BSDF
    /// Returns the color, direction, pdf and the type of BxDF that was sampled.
    pub fn sample(&self, wo_world: &Vector, flags: EnumSet<BxDFType>, samples: &Sample)
        -> (Colorf, Vector, f32, EnumSet<BxDFType>)
    {
        let n_matching = self.num_matching(flags);
        if n_matching == 0 {
            return (Colorf::broadcast(0.0), Vector::broadcast(0.0), 0.0, EnumSet::new());
        }
        let comp = cmp::min((samples.one_d * n_matching as f32) as usize, n_matching - 1);
        let bxdf = self.matching_at(comp, flags);
        let w_o = self.to_shading(wo_world).normalized();
        let (mut f, w_i, mut pdf) = bxdf.sample(&w_o, &samples.two_d);
        if w_i.length_sqr() == 0.0 {
            return (Colorf::broadcast(0.0), Vector::broadcast(0.0), 0.0, EnumSet::new());
        }
        let wi_world = self.from_shading(&w_i).normalized();

        // TODO: We re-use our functions but actually do a lot of redundant computation. I'm not
        // sure that the compiler will eliminate it. Should just copy in the code from pdf and eval
        if !bxdf.bxdf_type().contains(&BxDFType::Specular) && n_matching > 1 {
            pdf = self.pdf(wo_world, &wi_world, flags);
        }

        if !bxdf.bxdf_type().contains(&BxDFType::Specular) {
            f = self.eval(wo_world, &wi_world, flags);
        }
        (f, wi_world, pdf, bxdf.bxdf_type())
    }
    /// Compute the pdf for sampling the pair of incident and outgoing light directions for
    /// the BxDFs matching the flags set
    pub fn pdf(&self, wo_world: &Vector, wi_world: &Vector, flags: EnumSet<BxDFType>) -> f32 {
        let w_o = self.to_shading(wo_world).normalized();
        let w_i = self.to_shading(wi_world).normalized();
        let (pdf_val, n_comps) = self.bxdfs.iter()
            .filter_map(|x| if x.matches(flags) { Some(x.pdf(&w_o, &w_i)) } else { None })
            .fold((0.0, 0), |(p, n), y| (p + y, n + 1));
        if n_comps > 0 {
            pdf_val / n_comps as f32
        } else {
            0.0
        }
    }
    /// Get the `i`th BxDF that matches the flags passed. There should not be fewer than i
    /// BxDFs that match the flags
    fn matching_at(&self, i: usize, flags: EnumSet<BxDFType>) -> &BxDF {
        let mut it = self.bxdfs.iter().filter(|x| x.matches(flags)).skip(i);
        match it.next() {
            Some(b) => *b,
            None => panic!("Out of bounds index for BxDF type {:?}", flags)
        }
    }
}

<|endoftext|>


<commit_before>use runtime::container::Container;
use runtime::divert::PushPopType;
use runtime::RuntimeObject;

use std::collections::HashMap;
use std::rc::Rc;

#[derive(Clone)]
pub struct Element {
    container: Rc<Container>,
    index: usize,
    in_expression_evaluation: bool,
    /*temporary_variables: HashMap<String, RuntimeObject>,*/
    stack_push_type: PushPopType
}

impl Element {
    pub fn new(stack_push_type: PushPopType, container: Rc<Container>, index: usize) -> Element {
        Element {
            container: container,
            index: index,
            stack_push_type: stack_push_type,
            in_expression_evaluation: false
        }
    }

    pub fn current_runtime_object(&self) -> Option<&RuntimeObject> {
        self.container.content().get(self.index)
    }

    pub fn stack_push_type(&self) -> PushPopType {
        self.stack_push_type
    }

    pub fn in_expression_evaluation(&self) -> bool {
        self.in_expression_evaluation
    }

    pub fn set_container(&mut self, container: Rc<Container>) {
        self.container = container;
    }

    pub fn set_index(&mut self, index: usize) {
        self.index = index;
    }

    pub fn set_runtime_object(&mut self, container: Rc<Container>, index: usize) {
        self.container = container;
        self.index = index;
    }

    pub fn set_in_expression_evaluation(&mut self, in_expression_evaluation: bool) {
        self.in_expression_evaluation = in_expression_evaluation;
    }
}

#[derive(Clone)]
pub struct Thread {
    stack: Vec<Element>
}

impl<'ru> Thread {
    pub fn new() -> Thread {
        Thread {
            stack: Vec::new()
        }
    }

    pub fn stack(&self) -> &Vec<Element> {
        &self.stack
    }

    pub fn push(&mut self, element: Element) {
        self.stack.push(element);
    }

    pub fn pop(&mut self) -> Option<Element> {
        self.stack.pop()
    }

    pub fn pop_if<F>(&mut self, f: F) -> Option<Element>
        where F: FnOnce(&Element) -> bool {
        let mut should_pop = match self.stack.last() {
            Some(element) => f(element),
            _ => false
        };

        // Need to do this because at the moment rust does not support Non-lexical borrow scopes
        // See https://github.com/rust-lang/rfcs/issues/811
        if should_pop {
            return self.stack.pop();
        }

        None
    }

}

#[derive(Clone)]
pub struct CallStack {
    threads: Vec<Thread>
}

impl<'ru> CallStack {
    pub fn new(root_container: Rc<Container>) -> CallStack {
        let mut threads = Vec::new();
        let mut thread = Thread::new();

        thread.push(Element::new(PushPopType::Tunnel, root_container, 0));
        threads.push(thread);

        CallStack {
            threads: threads
        }
    }

    pub fn current_thread(&self) -> Option<&Thread> {
        self.threads.last()
    }

    pub fn current_stack(&self) -> Option<&Vec<Element>> {
        self.current_thread().map(|thread| thread.stack())
    }

    pub fn current_element(&self) -> Option<&Element> {
        self.current_stack().and_then(|stack| stack.last())
    }

    pub fn current_runtime_object(&self) -> Option<&RuntimeObject> {
        match self.current_element() {
            Some(element) => element.current_runtime_object(),
            _ => None
        }
    }

    pub fn depth(&self) -> usize {
        match self.current_stack() {
            Some(stack) => stack.len(),
            _ => 0
        }
    }

    pub fn get_thread(&self, index: usize) -> Option<&Thread> {
        self.threads.get(index)
    }

    pub fn push_thread(&mut self) -> bool {
        if let Some(thread) = self.threads.last().map(|thread| thread.clone()) {
            self.threads.push(thread);
            return true;
        }

        false
    }

    pub fn pop_thread(&mut self) -> bool {
        match self.threads.pop() {
            Some(_) => true,
            _ => false
        }
    }

    pub fn reset(&mut self, thread: Thread) {
        self.threads.clear();
        self.threads.push(thread);
    }
}<commit_msg>Fix build issue due to removal of Container::content()<commit_after>use runtime::container::Container;
use runtime::divert::PushPopType;
use runtime::RuntimeObject;

use std::collections::HashMap;
use std::rc::Rc;

#[derive(Clone)]
pub struct Element {
    container: Rc<Container>,
    index: usize,
    in_expression_evaluation: bool,
    /*temporary_variables: HashMap<String, RuntimeObject>,*/
    stack_push_type: PushPopType
}

impl Element {
    pub fn new(stack_push_type: PushPopType, container: Rc<Container>, index: usize) -> Element {
        Element {
            container: container,
            index: index,
            stack_push_type: stack_push_type,
            in_expression_evaluation: false
        }
    }

    pub fn current_runtime_object(&self) -> Option<&RuntimeObject> {
        self.container.get(self.index)
    }

    pub fn stack_push_type(&self) -> PushPopType {
        self.stack_push_type
    }

    pub fn in_expression_evaluation(&self) -> bool {
        self.in_expression_evaluation
    }

    pub fn set_container(&mut self, container: Rc<Container>) {
        self.container = container;
    }

    pub fn set_index(&mut self, index: usize) {
        self.index = index;
    }

    pub fn set_runtime_object(&mut self, container: Rc<Container>, index: usize) {
        self.container = container;
        self.index = index;
    }

    pub fn set_in_expression_evaluation(&mut self, in_expression_evaluation: bool) {
        self.in_expression_evaluation = in_expression_evaluation;
    }
}

#[derive(Clone)]
pub struct Thread {
    stack: Vec<Element>
}

impl<'ru> Thread {
    pub fn new() -> Thread {
        Thread {
            stack: Vec::new()
        }
    }

    pub fn stack(&self) -> &Vec<Element> {
        &self.stack
    }

    pub fn push(&mut self, element: Element) {
        self.stack.push(element);
    }

    pub fn pop(&mut self) -> Option<Element> {
        self.stack.pop()
    }

    pub fn pop_if<F>(&mut self, f: F) -> Option<Element>
        where F: FnOnce(&Element) -> bool {
        let mut should_pop = match self.stack.last() {
            Some(element) => f(element),
            _ => false
        };

        // Need to do this because at the moment rust does not support Non-lexical borrow scopes
        // See https://github.com/rust-lang/rfcs/issues/811
        if should_pop {
            return self.stack.pop();
        }

        None
    }

}

#[derive(Clone)]
pub struct CallStack {
    threads: Vec<Thread>
}

impl<'ru> CallStack {
    pub fn new(root_container: Rc<Container>) -> CallStack {
        let mut threads = Vec::new();
        let mut thread = Thread::new();

        thread.push(Element::new(PushPopType::Tunnel, root_container, 0));
        threads.push(thread);

        CallStack {
            threads: threads
        }
    }

    pub fn current_thread(&self) -> Option<&Thread> {
        self.threads.last()
    }

    pub fn current_stack(&self) -> Option<&Vec<Element>> {
        self.current_thread().map(|thread| thread.stack())
    }

    pub fn current_element(&self) -> Option<&Element> {
        self.current_stack().and_then(|stack| stack.last())
    }

    pub fn current_runtime_object(&self) -> Option<&RuntimeObject> {
        match self.current_element() {
            Some(element) => element.current_runtime_object(),
            _ => None
        }
    }

    pub fn depth(&self) -> usize {
        match self.current_stack() {
            Some(stack) => stack.len(),
            _ => 0
        }
    }

    pub fn get_thread(&self, index: usize) -> Option<&Thread> {
        self.threads.get(index)
    }

    pub fn push_thread(&mut self) -> bool {
        if let Some(thread) = self.threads.last().map(|thread| thread.clone()) {
            self.threads.push(thread);
            return true;
        }

        false
    }

    pub fn pop_thread(&mut self) -> bool {
        match self.threads.pop() {
            Some(_) => true,
            _ => false
        }
    }

    pub fn reset(&mut self, thread: Thread) {
        self.threads.clear();
        self.threads.push(thread);
    }
}<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! OS-based thread local storage
//!
//! This module provides an implementation of OS-based thread local storage,
//! using the native OS-provided facilities (think `TlsAlloc` or
//! `pthread_setspecific`). The interface of this differs from the other types
//! of thread-local-storage provided in this crate in that OS-based TLS can only
//! get/set pointers,
//!
//! This module also provides two flavors of TLS. One is intended for static
//! initialization, and does not contain a `Drop` implementation to deallocate
//! the OS-TLS key. The other is a type which does implement `Drop` and hence
//! has a safe interface.
//!
//! # Usage
//!
//! This module should likely not be used directly unless other primitives are
//! being built on. types such as `thread_local::scoped::Key` are likely much
//! more useful in practice than this OS-based version which likely requires
//! unsafe code to interoperate with.
//!
//! # Example
//!
//! Using a dynamically allocated TLS key. Note that this key can be shared
//! among many threads via an `Arc`.
//!
//! ```rust,ignore
//! let key = Key::new(None);
//! assert!(key.get().is_null());
//! key.set(1 as *mut u8);
//! assert!(!key.get().is_null());
//!
//! drop(key); // deallocate this TLS slot.
//! ```
//!
//! Sometimes a statically allocated key is either required or easier to work
//! with, however.
//!
//! ```rust,ignore
//! static KEY: StaticKey = INIT;
//!
//! unsafe {
//!     assert!(KEY.get().is_null());
//!     KEY.set(1 as *mut u8);
//! }
//! ```

#![allow(non_camel_case_types)]

use prelude::*;

use kinds::marker;
use rustrt::exclusive::Exclusive;
use sync::atomic::{mod, AtomicUint};
use sync::{Once, ONCE_INIT};

use sys::thread_local as imp;

/// A type for TLS keys that are statically allocated.
///
/// This type is entirely `unsafe` to use as it does not protect against
/// use-after-deallocation or use-during-deallocation.
///
/// The actual OS-TLS key is lazily allocated when this is used for the first
/// time. The key is also deallocated when the Rust runtime exits or `destroy`
/// is called, whichever comes first.
///
/// # Example
///
/// ```ignore
/// use tls::os::{StaticKey, INIT};
///
/// static KEY: StaticKey = INIT;
///
/// unsafe {
///     assert!(KEY.get().is_null());
///     KEY.set(1 as *mut u8);
/// }
/// ```
pub struct StaticKey {
    /// Inner static TLS key (internals), created with by `INIT_INNER` in this
    /// module.
    pub inner: StaticKeyInner,
    /// Destructor for the TLS value.
    ///
    /// See `Key::new` for information about when the destructor runs and how
    /// it runs.
    pub dtor: Option<unsafe extern fn(*mut u8)>,
}

/// Inner contents of `StaticKey`, created by the `INIT_INNER` constant.
pub struct StaticKeyInner {
    key: AtomicUint,
    nc: marker::NoCopy,
}

/// A type for a safely managed OS-based TLS slot.
///
/// This type allocates an OS TLS key when it is initialized and will deallocate
/// the key when it falls out of scope. When compared with `StaticKey`, this
/// type is entirely safe to use.
///
/// Implementations will likely, however, contain unsafe code as this type only
/// operates on `*mut u8`, an unsafe pointer.
///
/// # Example
///
/// ```rust,ignore
/// use tls::os::Key;
///
/// let key = Key::new(None);
/// assert!(key.get().is_null());
/// key.set(1 as *mut u8);
/// assert!(!key.get().is_null());
///
/// drop(key); // deallocate this TLS slot.
/// ```
pub struct Key {
    key: imp::Key,
}

/// Constant initialization value for static TLS keys.
///
/// This value specifies no destructor by default.
pub const INIT: StaticKey = StaticKey {
    inner: INIT_INNER,
    dtor: None,
};

/// Constant initialization value for the inner part of static TLS keys.
///
/// This value allows specific configuration of the destructor for a TLS key.
pub const INIT_INNER: StaticKeyInner = StaticKeyInner {
    key: atomic::INIT_ATOMIC_UINT,
    nc: marker::NoCopy,
};

static INIT_KEYS: Once = ONCE_INIT;
static mut KEYS: *mut Exclusive<Vec<imp::Key>> = 0 as *mut _;

impl StaticKey {
    /// Gets the value associated with this TLS key
    ///
    /// This will lazily allocate a TLS key from the OS if one has not already
    /// been allocated.
    #[inline]
    pub unsafe fn get(&self) -> *mut u8 { imp::get(self.key()) }

    /// Sets this TLS key to a new value.
    ///
    /// This will lazily allocate a TLS key from the OS if one has not already
    /// been allocated.
    #[inline]
    pub unsafe fn set(&self, val: *mut u8) { imp::set(self.key(), val) }

    /// Deallocates this OS TLS key.
    ///
    /// This function is unsafe as there is no guarantee that the key is not
    /// currently in use by other threads or will not ever be used again.
    ///
    /// Note that this does *not* run the user-provided destructor if one was
    /// specified at definition time. Doing so must be done manually.
    pub unsafe fn destroy(&self) {
        match self.inner.key.swap(0, atomic::SeqCst) {
            0 => {}
            n => { imp::destroy(n as imp::Key) }
        }
    }

    #[inline]
    unsafe fn key(&self) -> imp::Key {
        match self.inner.key.load(atomic::Relaxed) {
            0 => self.lazy_init() as imp::Key,
            n => n as imp::Key
        }
    }

    unsafe fn lazy_init(&self) -> uint {
        // POSIX allows the key created here to be 0, but the compare_and_swap
        // below relies on using 0 as a sentinel value to check who won the
        // race to set the shared TLS key. As far as I know, there is no
        // guaranteed value that cannot be returned as a posix_key_create key,
        // so there is no value we can initialize the inner key with to
        // prove that it has not yet been set. As such, we'll continue using a
        // value of 0, but with some gyrations to make sure we have a non-0
        // value returned from the creation routine.
        // TODO: this is clearly a hack, and should be cleaned up.
        let key1 = imp::create(self.dtor);
        let key = if key1 != 0 {
            key1
        } else {
            let key2 = imp::create(self.dtor);
            imp::destroy(key1);
            key2
        };
        assert!(key != 0);
        match self.inner.key.compare_and_swap(0, key as uint, atomic::SeqCst) {
            // The CAS succeeded, so we've created the actual key
            0 => key as uint,
            // If someone beat us to the punch, use their key instead
            n => { imp::destroy(key); n }
        }
    }
}

impl Key {
    /// Create a new managed OS TLS key.
    ///
    /// This key will be deallocated when the key falls out of scope.
    ///
    /// The argument provided is an optionally-specified destructor for the
    /// value of this TLS key. When a thread exits and the value for this key
    /// is non-null the destructor will be invoked. The TLS value will be reset
    /// to null before the destructor is invoked.
    ///
    /// Note that the destructor will not be run when the `Key` goes out of
    /// scope.
    #[inline]
    pub fn new(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
        Key { key: unsafe { imp::create(dtor) } }
    }

    /// See StaticKey::get
    #[inline]
    pub fn get(&self) -> *mut u8 {
        unsafe { imp::get(self.key) }
    }

    /// See StaticKey::set
    #[inline]
    pub fn set(&self, val: *mut u8) {
        unsafe { imp::set(self.key, val) }
    }
}

impl Drop for Key {
    fn drop(&mut self) {
        unsafe { imp::destroy(self.key) }
    }
}

#[cfg(test)]
mod tests {
    use prelude::*;
    use super::{Key, StaticKey, INIT_INNER};

    fn assert_sync<T: Sync>() {}
    fn assert_send<T: Send>() {}

    #[test]
    fn smoke() {
        assert_sync::<Key>();
        assert_send::<Key>();

        let k1 = Key::new(None);
        let k2 = Key::new(None);
        assert!(k1.get().is_null());
        assert!(k2.get().is_null());
        k1.set(1 as *mut _);
        k2.set(2 as *mut _);
        assert_eq!(k1.get() as uint, 1);
        assert_eq!(k2.get() as uint, 2);
    }

    #[test]
    fn statik() {
        static K1: StaticKey = StaticKey { inner: INIT_INNER, dtor: None };
        static K2: StaticKey = StaticKey { inner: INIT_INNER, dtor: None };

        unsafe {
            assert!(K1.get().is_null());
            assert!(K2.get().is_null());
            K1.set(1 as *mut _);
            K2.set(2 as *mut _);
            assert_eq!(K1.get() as uint, 1);
            assert_eq!(K2.get() as uint, 2);
        }
    }
}

<commit_msg>prefer "FIXME" to "TODO".<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! OS-based thread local storage
//!
//! This module provides an implementation of OS-based thread local storage,
//! using the native OS-provided facilities (think `TlsAlloc` or
//! `pthread_setspecific`). The interface of this differs from the other types
//! of thread-local-storage provided in this crate in that OS-based TLS can only
//! get/set pointers,
//!
//! This module also provides two flavors of TLS. One is intended for static
//! initialization, and does not contain a `Drop` implementation to deallocate
//! the OS-TLS key. The other is a type which does implement `Drop` and hence
//! has a safe interface.
//!
//! # Usage
//!
//! This module should likely not be used directly unless other primitives are
//! being built on. types such as `thread_local::scoped::Key` are likely much
//! more useful in practice than this OS-based version which likely requires
//! unsafe code to interoperate with.
//!
//! # Example
//!
//! Using a dynamically allocated TLS key. Note that this key can be shared
//! among many threads via an `Arc`.
//!
//! ```rust,ignore
//! let key = Key::new(None);
//! assert!(key.get().is_null());
//! key.set(1 as *mut u8);
//! assert!(!key.get().is_null());
//!
//! drop(key); // deallocate this TLS slot.
//! ```
//!
//! Sometimes a statically allocated key is either required or easier to work
//! with, however.
//!
//! ```rust,ignore
//! static KEY: StaticKey = INIT;
//!
//! unsafe {
//!     assert!(KEY.get().is_null());
//!     KEY.set(1 as *mut u8);
//! }
//! ```

#![allow(non_camel_case_types)]

use prelude::*;

use kinds::marker;
use rustrt::exclusive::Exclusive;
use sync::atomic::{mod, AtomicUint};
use sync::{Once, ONCE_INIT};

use sys::thread_local as imp;

/// A type for TLS keys that are statically allocated.
///
/// This type is entirely `unsafe` to use as it does not protect against
/// use-after-deallocation or use-during-deallocation.
///
/// The actual OS-TLS key is lazily allocated when this is used for the first
/// time. The key is also deallocated when the Rust runtime exits or `destroy`
/// is called, whichever comes first.
///
/// # Example
///
/// ```ignore
/// use tls::os::{StaticKey, INIT};
///
/// static KEY: StaticKey = INIT;
///
/// unsafe {
///     assert!(KEY.get().is_null());
///     KEY.set(1 as *mut u8);
/// }
/// ```
pub struct StaticKey {
    /// Inner static TLS key (internals), created with by `INIT_INNER` in this
    /// module.
    pub inner: StaticKeyInner,
    /// Destructor for the TLS value.
    ///
    /// See `Key::new` for information about when the destructor runs and how
    /// it runs.
    pub dtor: Option<unsafe extern fn(*mut u8)>,
}

/// Inner contents of `StaticKey`, created by the `INIT_INNER` constant.
pub struct StaticKeyInner {
    key: AtomicUint,
    nc: marker::NoCopy,
}

/// A type for a safely managed OS-based TLS slot.
///
/// This type allocates an OS TLS key when it is initialized and will deallocate
/// the key when it falls out of scope. When compared with `StaticKey`, this
/// type is entirely safe to use.
///
/// Implementations will likely, however, contain unsafe code as this type only
/// operates on `*mut u8`, an unsafe pointer.
///
/// # Example
///
/// ```rust,ignore
/// use tls::os::Key;
///
/// let key = Key::new(None);
/// assert!(key.get().is_null());
/// key.set(1 as *mut u8);
/// assert!(!key.get().is_null());
///
/// drop(key); // deallocate this TLS slot.
/// ```
pub struct Key {
    key: imp::Key,
}

/// Constant initialization value for static TLS keys.
///
/// This value specifies no destructor by default.
pub const INIT: StaticKey = StaticKey {
    inner: INIT_INNER,
    dtor: None,
};

/// Constant initialization value for the inner part of static TLS keys.
///
/// This value allows specific configuration of the destructor for a TLS key.
pub const INIT_INNER: StaticKeyInner = StaticKeyInner {
    key: atomic::INIT_ATOMIC_UINT,
    nc: marker::NoCopy,
};

static INIT_KEYS: Once = ONCE_INIT;
static mut KEYS: *mut Exclusive<Vec<imp::Key>> = 0 as *mut _;

impl StaticKey {
    /// Gets the value associated with this TLS key
    ///
    /// This will lazily allocate a TLS key from the OS if one has not already
    /// been allocated.
    #[inline]
    pub unsafe fn get(&self) -> *mut u8 { imp::get(self.key()) }

    /// Sets this TLS key to a new value.
    ///
    /// This will lazily allocate a TLS key from the OS if one has not already
    /// been allocated.
    #[inline]
    pub unsafe fn set(&self, val: *mut u8) { imp::set(self.key(), val) }

    /// Deallocates this OS TLS key.
    ///
    /// This function is unsafe as there is no guarantee that the key is not
    /// currently in use by other threads or will not ever be used again.
    ///
    /// Note that this does *not* run the user-provided destructor if one was
    /// specified at definition time. Doing so must be done manually.
    pub unsafe fn destroy(&self) {
        match self.inner.key.swap(0, atomic::SeqCst) {
            0 => {}
            n => { imp::destroy(n as imp::Key) }
        }
    }

    #[inline]
    unsafe fn key(&self) -> imp::Key {
        match self.inner.key.load(atomic::Relaxed) {
            0 => self.lazy_init() as imp::Key,
            n => n as imp::Key
        }
    }

    unsafe fn lazy_init(&self) -> uint {
        // POSIX allows the key created here to be 0, but the compare_and_swap
        // below relies on using 0 as a sentinel value to check who won the
        // race to set the shared TLS key. As far as I know, there is no
        // guaranteed value that cannot be returned as a posix_key_create key,
        // so there is no value we can initialize the inner key with to
        // prove that it has not yet been set. As such, we'll continue using a
        // value of 0, but with some gyrations to make sure we have a non-0
        // value returned from the creation routine.
        // FIXME: this is clearly a hack, and should be cleaned up.
        let key1 = imp::create(self.dtor);
        let key = if key1 != 0 {
            key1
        } else {
            let key2 = imp::create(self.dtor);
            imp::destroy(key1);
            key2
        };
        assert!(key != 0);
        match self.inner.key.compare_and_swap(0, key as uint, atomic::SeqCst) {
            // The CAS succeeded, so we've created the actual key
            0 => key as uint,
            // If someone beat us to the punch, use their key instead
            n => { imp::destroy(key); n }
        }
    }
}

impl Key {
    /// Create a new managed OS TLS key.
    ///
    /// This key will be deallocated when the key falls out of scope.
    ///
    /// The argument provided is an optionally-specified destructor for the
    /// value of this TLS key. When a thread exits and the value for this key
    /// is non-null the destructor will be invoked. The TLS value will be reset
    /// to null before the destructor is invoked.
    ///
    /// Note that the destructor will not be run when the `Key` goes out of
    /// scope.
    #[inline]
    pub fn new(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
        Key { key: unsafe { imp::create(dtor) } }
    }

    /// See StaticKey::get
    #[inline]
    pub fn get(&self) -> *mut u8 {
        unsafe { imp::get(self.key) }
    }

    /// See StaticKey::set
    #[inline]
    pub fn set(&self, val: *mut u8) {
        unsafe { imp::set(self.key, val) }
    }
}

impl Drop for Key {
    fn drop(&mut self) {
        unsafe { imp::destroy(self.key) }
    }
}

#[cfg(test)]
mod tests {
    use prelude::*;
    use super::{Key, StaticKey, INIT_INNER};

    fn assert_sync<T: Sync>() {}
    fn assert_send<T: Send>() {}

    #[test]
    fn smoke() {
        assert_sync::<Key>();
        assert_send::<Key>();

        let k1 = Key::new(None);
        let k2 = Key::new(None);
        assert!(k1.get().is_null());
        assert!(k2.get().is_null());
        k1.set(1 as *mut _);
        k2.set(2 as *mut _);
        assert_eq!(k1.get() as uint, 1);
        assert_eq!(k2.get() as uint, 2);
    }

    #[test]
    fn statik() {
        static K1: StaticKey = StaticKey { inner: INIT_INNER, dtor: None };
        static K2: StaticKey = StaticKey { inner: INIT_INNER, dtor: None };

        unsafe {
            assert!(K1.get().is_null());
            assert!(K2.get().is_null());
            K1.set(1 as *mut _);
            K2.set(2 as *mut _);
            assert_eq!(K1.get() as uint, 1);
            assert_eq!(K2.get() as uint, 2);
        }
    }
}

<|endoftext|>


<commit_before>pub fn add(num_l: &str, num_r: &str) -> String {
    let mut sum: Vec<u8> = denormalize(num_l).into();
    sum.extend(denormalize(num_r).bytes());

    sum.sort();
    sum.reverse();

    normalize(&String::from_utf8(sum).unwrap())
}

pub fn denormalize(num: &str) -> String {
    match num {
        "IV" => "IIII",
        "IX" => "VIIII",
        _ => num,
    }.to_string()
}

pub fn normalize(num: &str) -> String {
    match num {
        "IIII" => "IV".to_string(),
        "IIIII" => "V".to_string(),
        "VIIII" => "IX".to_string(),
        "VIIIII" => "X".to_string(),
        "VV" => "X".to_string(),
        _ => num.to_string(),
    }
}

#[cfg(test)]
mod tests {
    use super::add;
    use super::normalize;
    use super::denormalize;

    #[test]
    fn add_i_i() {
        assert_eq!("II", add("I", "I"));
    }

    #[test]
    fn add_i_ii() {
        assert_eq!("III", add("I", "II"));
    }

    #[test]
    fn add_ii_iii_requires_normalization_to_v() {
        assert_eq!("V", add("II", "III"));

    }

    #[test]
    fn add_v_i() {
        assert_eq!("VI", add("V", "I"));
    }

    #[test]
    fn add_i_v_understands_the_relative_order_of_v_and_i() {
        assert_eq!("VI", add("I", "V"));
    }

    #[test]
    fn add_i_iv_denormalizes_before_adding() {
        assert_eq!("V", add("I", "IV"));
    }

    #[test]
    fn denormalize_iv() {
        assert_eq!("IIII", denormalize("IV"));
    }

    #[test]
    fn denormalize_ix() {
        assert_eq!("VIIII", denormalize("IX"));
    }

    #[test]
    fn normalize_iiiii() {
        assert_eq!("V", normalize("IIIII"));
    }

    #[test]
    fn normalize_iiii() {
        assert_eq!("IV", normalize("IIII"));
    }

    #[test]
    fn normalize_vv() {
        assert_eq!("X", normalize("VV"));
    }

    #[test]
    fn normalize_viiii() {
        assert_eq!("IX", normalize("VIIII"));
    }

    #[test]
    fn normalize_viiiii() {
        assert_eq!("X", normalize("VIIIII"));
    }

}
<commit_msg>Acceptance tests working in Rust<commit_after>pub fn add(num_l: &str, num_r: &str) -> String {
    let mut sum: Vec<u8> = denormalize(num_l).into();
    sum.extend(denormalize(num_r).bytes());

    sum.sort();
    sum.reverse();

    normalize(&String::from_utf8(sum).unwrap())
}

pub fn denormalize(num: &str) -> String {
    match num {
        "IV" => "IIII",
        "IX" => "VIIII",
        _ => num,
    }.to_string()
}

fn _factor_out(num: &str, before: &str, after: &str) -> String {
    let parts: Vec<&str> = num.split(before).collect();
    parts.join(after)
}

pub fn normalize(num: &str) -> String {
    let num = _factor_out(num, "IIIII", "V");
    let num = _factor_out(num.as_ref(), "IIII", "IV");
    let num = _factor_out(num.as_ref(), "VIV", "IX");
    match num.as_ref() {
        "VIIII" => "IX".to_string(),
        "VIIIII" => "X".to_string(),
        "VV" => "X".to_string(),
        _ => num,
    }
}

#[cfg(test)]
mod tests {
    use super::add;
    use super::normalize;
    use super::denormalize;

    #[test]
    fn add_i_i() {
        assert_eq!("II", add("I", "I"));
    }

    #[test]
    fn add_i_ii() {
        assert_eq!("III", add("I", "II"));
    }

    #[test]
    fn add_ii_iii_requires_normalization_to_v() {
        assert_eq!("V", add("II", "III"));

    }

    #[test]
    fn add_v_i() {
        assert_eq!("VI", add("V", "I"));
    }

    #[test]
    fn add_i_v_understands_the_relative_order_of_v_and_i() {
        assert_eq!("VI", add("I", "V"));
    }

    #[test]
    fn add_i_iv_denormalizes_before_adding() {
        assert_eq!("V", add("I", "IV"));
    }

    #[test]
    fn denormalize_iv() {
        assert_eq!("IIII", denormalize("IV"));
    }

    #[test]
    fn denormalize_ix() {
        assert_eq!("VIIII", denormalize("IX"));
    }

    #[test]
    fn normalize_iiiii() {
        assert_eq!("V", normalize("IIIII"));
    }

    #[test]
    fn normalize_iiii() {
        assert_eq!("IV", normalize("IIII"));
    }

    #[test]
    fn normalize_vv() {
        assert_eq!("X", normalize("VV"));
    }

    #[test]
    fn normalize_viiii() {
        assert_eq!("IX", normalize("VIIII"));
    }

    #[test]
    fn normalize_viiiii() {
        assert_eq!("X", normalize("VIIIII"));
    }

}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::time::Instant;
use nix::Error as NixErr;
use nix::sys::wait::*;
use nix::sys::signal::Signal;
use nix::errno::Errno;
use nix::unistd::Pid;
use breakpoint::*;
use traces::*;
use ptrace_control::*;
use config::Config;
use errors::RunError;

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum TestState {
    /// Start state. Wait for test to appear and track time to enable timeout
    Start {
        start_time: Instant,
    },
    /// Initialise: once test process appears instrument
    Initialise,
    /// Waiting for breakpoint to be hit or test to end
    Waiting {
        start_time: Instant,
    },
    /// Test process stopped, check coverage
    Stopped,
    /// Test exited normally. Includes the exit code of the test executable.
    End(i32),
}

/// Tracing a process on an OS will have platform specific code.
/// Structs containing the platform specific datastructures should
/// provide this trait with an implementation of the handling of
/// the given states.
pub trait StateData {
    /// Starts the tracing. Returns None while waiting for
    /// start. Statemachine then checks timeout
    fn start(&mut self) -> Result<Option<TestState>, RunError>;
    /// Initialises test for tracing returns next state
    fn init(&mut self) -> Result<TestState, RunError>;
    /// Waits for notification from test executable that there's
    /// something to do. Selects the next appropriate state if there's
    /// something to do otherwise None
    fn wait(&mut self) -> Result<Option<TestState>, RunError>;
    /// Handle a stop in the test executable. Coverage data will
    /// be collected here as well as other OS specific functions
    fn stop(&mut self) -> Result<TestState, RunError>;
}

impl TestState {
    /// Convenience function used to check if the test has finished or errored
    pub fn is_finished(self) -> bool {
        match self {
            TestState::End(_) => true,
            _ => false,
        }
    }

    /// Convenience function for creating start states
    fn start_state() -> TestState {
        TestState::Start{start_time: Instant::now()}
    }

    /// Convenience function for creating wait states
    fn wait_state() -> TestState {
        TestState::Waiting{start_time: Instant::now()}
    }

    /// Updates the state machine state
    pub fn step<T:StateData>(self, data: &mut T, config: &Config) -> Result<TestState, RunError> {
        match self {
            TestState::Start{start_time} => {
                if let Some(s) = data.start()? {
                    Ok(s)
                } else if start_time.elapsed() >= config.test_timeout {
                    Err(RunError::TestRuntime("Error: Timed out when starting test".to_string()))
                } else {
                    Ok(TestState::Start{start_time})
                }
            },
            TestState::Initialise => {
                data.init()
            },
            TestState::Waiting{start_time} => {
                if let Some(s) = data.wait()? {
                    Ok(s)
                } else if start_time.elapsed() >= config.test_timeout {
                    Err(RunError::TestRuntime("Error: Timed out waiting for test response".to_string()))
                } else {
                    Ok(TestState::Waiting{start_time})
                }
            },
            TestState::Stopped => {
                data.stop()
            },
            _ => {
                // Unhandled
                if config.verbose {
                    println!("Tarpaulin error: unhandled test state");
                }
                Ok(TestState::End(-1))
            }
        }
    }
}

pub fn create_state_machine<'a>(test: Pid,
                                traces: &'a mut TraceMap,
                                config: &'a Config) -> (TestState, LinuxData<'a>) {
    let mut data = LinuxData::new(traces, config);
    data.parent = test;
    (TestState::start_state(), data)
}

/// Handle to linux process state
pub struct LinuxData<'a> {
    /// Recent result from waitpid to be handled by statemachine
    wait: WaitStatus,
    /// Current Pid to process
    current: Pid,
    /// Parent PID of test process
    parent: Pid,
    /// Map of addresses to breakpoints
    breakpoints: HashMap<u64, Breakpoint>,
    /// Instrumentation points in code with associated coverage data
    traces: &'a mut TraceMap,
    /// Program config
    config: &'a Config,
    /// Thread count. Hopefully getting rid of in future
    thread_count: isize,
    /// Used to show anomalies noticed so hit counts disabled
    force_disable_hit_count: bool
}

impl <'a> StateData for LinuxData<'a> {

    fn start(&mut self) -> Result<Option<TestState>, RunError> {
        match waitpid(self.current, Some(WaitPidFlag::WNOHANG)) {
            Ok(WaitStatus::StillAlive) => Ok(None),
            Ok(sig @ WaitStatus::Stopped(_, Signal::SIGTRAP)) => {
                if let WaitStatus::Stopped(child, _) = sig {
                    self.current = child;
                }
                self.wait = sig;
                Ok(Some(TestState::Initialise))
            },
            Ok(_) => {
                Err(RunError::TestRuntime("Unexpected signal when starting test".to_string()))
            },
            Err(e) => {
                Err(RunError::TestRuntime(format!("Error when starting test: {}", e)))
            },
        }
    }

    fn init(&mut self) -> Result<TestState, RunError> {
        //TODO: is this recoverable?
        trace_children(self.current)?;
        for trace in self.traces.all_traces() {
            if let Some(addr) = trace.address {
                match Breakpoint::new(self.current, addr) {
                    Ok(bp) => {
                        let _ = self.breakpoints.insert(addr, bp);
                    },
                    Err(e) if e==NixErr::Sys(Errno::EIO) => {
                        return Err(RunError::TestRuntime("ERROR: Tarpaulin cannot find code addresses \
                                  check that pie is disabled for your linker. \
                                  If linking with gcc try adding -C link-args=-no-pie \
                                  to your rust flags".to_string()));
                    }
                    Err(NixErr::UnsupportedOperation) => {
                        debug!("Instrumentation address clash, ignoring 0x{:x}", addr);
                    },
                    Err(_) => {
                        return Err(RunError::TestRuntime("Failed to instrument test executable".to_string()));
                    },
                }
            }
        }

        if continue_exec(self.parent, None).is_ok() {
            return Ok(TestState::wait_state());
        }

        //TODO: Is this correct?
        Ok(TestState::start_state())
    }

    fn wait(&mut self) -> Result<Option<TestState>, RunError> {
        let wait = waitpid(Pid::from_raw(-1), Some(WaitPidFlag::WNOHANG | WaitPidFlag::__WALL));
        match wait {
            Ok(WaitStatus::StillAlive) => {
                self.wait = WaitStatus::StillAlive;
                Ok(None)
            },
            Ok(s) => {
                self.wait = s;
                Ok(Some(TestState::Stopped))
            },
            Err(_) => {
                //TODO: Better error message!
                Err(RunError::TestRuntime("An error occurred while waiting for response from test".to_string()))
            },
        }
    }

    fn stop(&mut self) -> Result<TestState, RunError> {
        match self.wait {
            WaitStatus::PtraceEvent(c,s,e) => {
                match self.handle_ptrace_event(c, s, e) {
                    Ok(s) => Ok(s),
                    Err(e) => {
                        Err(RunError::TestRuntime(format!("Error occurred when handling ptrace event: {}", e)))
                    },
                }
            },
            WaitStatus::Stopped(c, Signal::SIGTRAP) => {
                self.current = c;
                match self.collect_coverage_data() {
                    Ok(s) => Ok(s),
                    Err(e) => {
                        Err(RunError::TestRuntime(format!("Error when collecting coverage: {}", e)))
                    }
                }
            },
            WaitStatus::Stopped(child, Signal::SIGSTOP) => {
                match continue_exec(child, None) {
                    Ok(_) => Ok(TestState::wait_state()),
                    Err(e) => Err(RunError::TestRuntime(format!("Error processing SIGSTOP: {}", e.to_string())))
                }
            },
            WaitStatus::Stopped(_, Signal::SIGSEGV) => {
                Err(RunError::TestRuntime("A segfault occurred while executing tests".to_string()))
            },
            WaitStatus::Stopped(c, s) => {
                let sig = if self.config.forward_signals {
                    Some(s)
                } else {
                    None
                };
                let _ = continue_exec(c, sig);
                Ok(TestState::wait_state())
            },
            WaitStatus::Signaled(_,_,_) => {
                if let Ok(s) = self.handle_signaled() {
                   Ok(s)
                } else {
                    Err(RunError::TestRuntime("Attempting to handle tarpaulin being signaled".to_string()))
                }
            },
            WaitStatus::Exited(child, ec) => {
                for ref mut value in self.breakpoints.values_mut() {
                    value.thread_killed(child);
                }
                if child == self.parent {
                    Ok(TestState::End(ec))
                } else {
                    // Process may have already been destroyed. This is just incase
                    let _ = continue_exec(self.parent, None);
                    Ok(TestState::wait_state())
                }
            },
            //TODO: Seriously, improve this.
            _ => Err(RunError::TestRuntime("Something went wrong stopping the tests!".to_string()))
        }
    }
}

impl <'a>LinuxData<'a> {
    pub fn new(traces: &'a mut TraceMap, config: &'a Config) -> LinuxData<'a> {
        LinuxData {
            wait: WaitStatus::StillAlive,
            current: Pid::from_raw(0),
            parent: Pid::from_raw(0),
            breakpoints: HashMap::new(),
            traces,
            config,
            thread_count: 0,
            force_disable_hit_count: config.count
        }
    }

    fn handle_ptrace_event(&mut self, child: Pid, sig: Signal, event: i32) -> Result<TestState, RunError> {
        use nix::libc::*;

        if sig == Signal::SIGTRAP {
            match event {
                PTRACE_EVENT_CLONE => {
                    if get_event_data(child).is_ok() {
                        self.thread_count += 1;
                        continue_exec(child, None)?;
                        Ok(TestState::wait_state())
                    } else {
                        Err(RunError::TestRuntime("Error occurred upon test executable thread creation".to_string()))
                    }
                },
                PTRACE_EVENT_FORK | PTRACE_EVENT_VFORK => {
                    continue_exec(child, None)?;
                    Ok(TestState::wait_state())
                },
                PTRACE_EVENT_EXEC => {
                    detach_child(child)?;
                    Ok(TestState::wait_state())
                },
                PTRACE_EVENT_EXIT => {
                    self.thread_count -= 1;
                    continue_exec(child, None)?;
                    Ok(TestState::wait_state())
                },
                //TODO: Correct error message?
                _ => Err(RunError::TestRuntime("Something went wrong!".to_string()))
            }
        } else {
            Err(RunError::TestRuntime("Unexpected ptrace event".to_string()))
        }
    }

    fn collect_coverage_data(&mut self) -> Result<TestState, RunError> {
        if let Ok(rip) = current_instruction_pointer(self.current) {
            let rip = (rip - 1) as u64;
            if  self.breakpoints.contains_key(&rip) {
                let bp = &mut self.breakpoints.get_mut(&rip).unwrap();
                let enable = self.config.count && self.thread_count < 2;
                if !enable && self.force_disable_hit_count {
                    println!("Code is mulithreaded, disabling hit count");
                    println!("Results may be improved by not using the '--count' option when running tarpaulin");
                    self.force_disable_hit_count = false;
                }
                // Don't reenable if multithreaded as can't yet sort out segfault issue
                let updated = if let Ok(x) = bp.process(self.current, enable) {
                     x
                } else {
                    // So failed to process a breakpoint.. Still continue to avoid
                    // stalling
                    continue_exec(self.current, None)?;
                    false
                };
                if updated {
                    if let Some(ref mut t) = self.traces.get_trace_mut(rip) {
                        if let CoverageStat::Line(ref mut x) = t.stats {
                            *x += 1;
                        }
                    }
                }
            } else {
                continue_exec(self.current, None)?;
            }
        } else {
            continue_exec(self.current, None)?;
        }
        Ok(TestState::wait_state())
    }

    fn handle_signaled(&mut self) -> Result<TestState, RunError> {
        match self.wait {
            WaitStatus::Signaled(child, Signal::SIGTRAP, true) => {
                continue_exec(child, None)?;
                Ok(TestState::wait_state())
            },
            _ => {
                Err(RunError::StateMachine("Unexpected stop".to_string()))
            },
        }
    }
}

<commit_msg>Updated some error messages.<commit_after>use std::collections::HashMap;
use std::time::Instant;
use nix::Error as NixErr;
use nix::sys::wait::*;
use nix::sys::signal::Signal;
use nix::errno::Errno;
use nix::unistd::Pid;
use breakpoint::*;
use traces::*;
use ptrace_control::*;
use config::Config;
use errors::RunError;

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum TestState {
    /// Start state. Wait for test to appear and track time to enable timeout
    Start {
        start_time: Instant,
    },
    /// Initialise: once test process appears instrument
    Initialise,
    /// Waiting for breakpoint to be hit or test to end
    Waiting {
        start_time: Instant,
    },
    /// Test process stopped, check coverage
    Stopped,
    /// Test exited normally. Includes the exit code of the test executable.
    End(i32),
}

/// Tracing a process on an OS will have platform specific code.
/// Structs containing the platform specific datastructures should
/// provide this trait with an implementation of the handling of
/// the given states.
pub trait StateData {
    /// Starts the tracing. Returns None while waiting for
    /// start. Statemachine then checks timeout
    fn start(&mut self) -> Result<Option<TestState>, RunError>;
    /// Initialises test for tracing returns next state
    fn init(&mut self) -> Result<TestState, RunError>;
    /// Waits for notification from test executable that there's
    /// something to do. Selects the next appropriate state if there's
    /// something to do otherwise None
    fn wait(&mut self) -> Result<Option<TestState>, RunError>;
    /// Handle a stop in the test executable. Coverage data will
    /// be collected here as well as other OS specific functions
    fn stop(&mut self) -> Result<TestState, RunError>;
}

impl TestState {
    /// Convenience function used to check if the test has finished or errored
    pub fn is_finished(self) -> bool {
        match self {
            TestState::End(_) => true,
            _ => false,
        }
    }

    /// Convenience function for creating start states
    fn start_state() -> TestState {
        TestState::Start{start_time: Instant::now()}
    }

    /// Convenience function for creating wait states
    fn wait_state() -> TestState {
        TestState::Waiting{start_time: Instant::now()}
    }

    /// Updates the state machine state
    pub fn step<T:StateData>(self, data: &mut T, config: &Config) -> Result<TestState, RunError> {
        match self {
            TestState::Start{start_time} => {
                if let Some(s) = data.start()? {
                    Ok(s)
                } else if start_time.elapsed() >= config.test_timeout {
                    Err(RunError::TestRuntime("Error: Timed out when starting test".to_string()))
                } else {
                    Ok(TestState::Start{start_time})
                }
            },
            TestState::Initialise => {
                data.init()
            },
            TestState::Waiting{start_time} => {
                if let Some(s) = data.wait()? {
                    Ok(s)
                } else if start_time.elapsed() >= config.test_timeout {
                    Err(RunError::TestRuntime("Error: Timed out waiting for test response".to_string()))
                } else {
                    Ok(TestState::Waiting{start_time})
                }
            },
            TestState::Stopped => {
                data.stop()
            },
            _ => {
                // Unhandled
                if config.verbose {
                    println!("Tarpaulin error: unhandled test state");
                }
                Ok(TestState::End(-1))
            }
        }
    }
}

pub fn create_state_machine<'a>(test: Pid,
                                traces: &'a mut TraceMap,
                                config: &'a Config) -> (TestState, LinuxData<'a>) {
    let mut data = LinuxData::new(traces, config);
    data.parent = test;
    (TestState::start_state(), data)
}

/// Handle to linux process state
pub struct LinuxData<'a> {
    /// Recent result from waitpid to be handled by statemachine
    wait: WaitStatus,
    /// Current Pid to process
    current: Pid,
    /// Parent PID of test process
    parent: Pid,
    /// Map of addresses to breakpoints
    breakpoints: HashMap<u64, Breakpoint>,
    /// Instrumentation points in code with associated coverage data
    traces: &'a mut TraceMap,
    /// Program config
    config: &'a Config,
    /// Thread count. Hopefully getting rid of in future
    thread_count: isize,
    /// Used to show anomalies noticed so hit counts disabled
    force_disable_hit_count: bool
}

impl <'a> StateData for LinuxData<'a> {

    fn start(&mut self) -> Result<Option<TestState>, RunError> {
        match waitpid(self.current, Some(WaitPidFlag::WNOHANG)) {
            Ok(WaitStatus::StillAlive) => Ok(None),
            Ok(sig @ WaitStatus::Stopped(_, Signal::SIGTRAP)) => {
                if let WaitStatus::Stopped(child, _) = sig {
                    self.current = child;
                }
                self.wait = sig;
                Ok(Some(TestState::Initialise))
            },
            Ok(_) => {
                Err(RunError::TestRuntime("Unexpected signal when starting test".to_string()))
            },
            Err(e) => {
                Err(RunError::TestRuntime(format!("Error when starting test: {}", e)))
            },
        }
    }

    fn init(&mut self) -> Result<TestState, RunError> {
        trace_children(self.current)?;
        for trace in self.traces.all_traces() {
            if let Some(addr) = trace.address {
                match Breakpoint::new(self.current, addr) {
                    Ok(bp) => {
                        let _ = self.breakpoints.insert(addr, bp);
                    },
                    Err(e) if e==NixErr::Sys(Errno::EIO) => {
                        return Err(RunError::TestRuntime("ERROR: Tarpaulin cannot find code addresses \
                                  check that pie is disabled for your linker. \
                                  If linking with gcc try adding -C link-args=-no-pie \
                                  to your rust flags".to_string()));
                    }
                    Err(NixErr::UnsupportedOperation) => {
                        debug!("Instrumentation address clash, ignoring 0x{:x}", addr);
                    },
                    Err(_) => {
                        return Err(RunError::TestRuntime("Failed to instrument test executable".to_string()));
                    },
                }
            }
        }

        if continue_exec(self.parent, None).is_ok() {
            return Ok(TestState::wait_state());
        } else {
            Err(RunError::TestRuntime("Test didn't launch correctly".to_string()))
        }
    }

    fn wait(&mut self) -> Result<Option<TestState>, RunError> {
        let wait = waitpid(Pid::from_raw(-1), Some(WaitPidFlag::WNOHANG | WaitPidFlag::__WALL));
        match wait {
            Ok(WaitStatus::StillAlive) => {
                self.wait = WaitStatus::StillAlive;
                Ok(None)
            },
            Ok(s) => {
                self.wait = s;
                Ok(Some(TestState::Stopped))
            },
            Err(e) => {
                Err(RunError::TestRuntime(format!("An error occurred while waiting for response from test: {}", e)))
            },
        }
    }

    fn stop(&mut self) -> Result<TestState, RunError> {
        match self.wait {
            WaitStatus::PtraceEvent(c,s,e) => {
                match self.handle_ptrace_event(c, s, e) {
                    Ok(s) => Ok(s),
                    Err(e) => {
                        Err(RunError::TestRuntime(format!("Error occurred when handling ptrace event: {}", e)))
                    },
                }
            },
            WaitStatus::Stopped(c, Signal::SIGTRAP) => {
                self.current = c;
                match self.collect_coverage_data() {
                    Ok(s) => Ok(s),
                    Err(e) => {
                        Err(RunError::TestRuntime(format!("Error when collecting coverage: {}", e)))
                    }
                }
            },
            WaitStatus::Stopped(child, Signal::SIGSTOP) => {
                match continue_exec(child, None) {
                    Ok(_) => Ok(TestState::wait_state()),
                    Err(e) => Err(RunError::TestRuntime(format!("Error processing SIGSTOP: {}", e.to_string())))
                }
            },
            WaitStatus::Stopped(_, Signal::SIGSEGV) => {
                Err(RunError::TestRuntime("A segfault occurred while executing tests".to_string()))
            },
            WaitStatus::Stopped(c, s) => {
                let sig = if self.config.forward_signals {
                    Some(s)
                } else {
                    None
                };
                let _ = continue_exec(c, sig);
                Ok(TestState::wait_state())
            },
            WaitStatus::Signaled(_,_,_) => {
                if let Ok(s) = self.handle_signaled() {
                   Ok(s)
                } else {
                    Err(RunError::TestRuntime("Attempting to handle tarpaulin being signaled".to_string()))
                }
            },
            WaitStatus::Exited(child, ec) => {
                for ref mut value in self.breakpoints.values_mut() {
                    value.thread_killed(child);
                }
                if child == self.parent {
                    Ok(TestState::End(ec))
                } else {
                    // Process may have already been destroyed. This is just incase
                    let _ = continue_exec(self.parent, None);
                    Ok(TestState::wait_state())
                }
            },
            //TODO: Seriously, improve this.
            _ => Err(RunError::TestRuntime("Something went wrong stopping the tests!".to_string()))
        }
    }
}

impl <'a>LinuxData<'a> {
    pub fn new(traces: &'a mut TraceMap, config: &'a Config) -> LinuxData<'a> {
        LinuxData {
            wait: WaitStatus::StillAlive,
            current: Pid::from_raw(0),
            parent: Pid::from_raw(0),
            breakpoints: HashMap::new(),
            traces,
            config,
            thread_count: 0,
            force_disable_hit_count: config.count
        }
    }

    fn handle_ptrace_event(&mut self, child: Pid, sig: Signal, event: i32) -> Result<TestState, RunError> {
        use nix::libc::*;

        if sig == Signal::SIGTRAP {
            match event {
                PTRACE_EVENT_CLONE => {
                    if get_event_data(child).is_ok() {
                        self.thread_count += 1;
                        continue_exec(child, None)?;
                        Ok(TestState::wait_state())
                    } else {
                        Err(RunError::TestRuntime("Error occurred upon test executable thread creation".to_string()))
                    }
                },
                PTRACE_EVENT_FORK | PTRACE_EVENT_VFORK => {
                    continue_exec(child, None)?;
                    Ok(TestState::wait_state())
                },
                PTRACE_EVENT_EXEC => {
                    detach_child(child)?;
                    Ok(TestState::wait_state())
                },
                PTRACE_EVENT_EXIT => {
                    self.thread_count -= 1;
                    continue_exec(child, None)?;
                    Ok(TestState::wait_state())
                },
                _ => Err(RunError::TestRuntime(format!("Unrecognised ptrace event {}", event)))
            }
        } else {
            Err(RunError::TestRuntime("Unexpected signal".to_string()))
        }
    }

    fn collect_coverage_data(&mut self) -> Result<TestState, RunError> {
        if let Ok(rip) = current_instruction_pointer(self.current) {
            let rip = (rip - 1) as u64;
            if  self.breakpoints.contains_key(&rip) {
                let bp = &mut self.breakpoints.get_mut(&rip).unwrap();
                let enable = self.config.count && self.thread_count < 2;
                if !enable && self.force_disable_hit_count {
                    println!("Code is mulithreaded, disabling hit count");
                    println!("Results may be improved by not using the '--count' option when running tarpaulin");
                    self.force_disable_hit_count = false;
                }
                // Don't reenable if multithreaded as can't yet sort out segfault issue
                let updated = if let Ok(x) = bp.process(self.current, enable) {
                     x
                } else {
                    // So failed to process a breakpoint.. Still continue to avoid
                    // stalling
                    continue_exec(self.current, None)?;
                    false
                };
                if updated {
                    if let Some(ref mut t) = self.traces.get_trace_mut(rip) {
                        if let CoverageStat::Line(ref mut x) = t.stats {
                            *x += 1;
                        }
                    }
                }
            } else {
                continue_exec(self.current, None)?;
            }
        } else {
            continue_exec(self.current, None)?;
        }
        Ok(TestState::wait_state())
    }

    fn handle_signaled(&mut self) -> Result<TestState, RunError> {
        match self.wait {
            WaitStatus::Signaled(child, Signal::SIGTRAP, true) => {
                continue_exec(child, None)?;
                Ok(TestState::wait_state())
            },
            _ => {
                Err(RunError::StateMachine("Unexpected stop".to_string()))
            },
        }
    }
}

<|endoftext|>


<commit_before>use std::env;
use std::path::Path;

use lazy_static::lazy_static;
use raw_cpuid::CpuId;

lazy_static! {
    static ref CPUID: CpuId = CpuId::new();
}

fn has_aesni() -> bool {
    cfg!(feature = "native")
        && CPUID
            .get_feature_info()
            .map_or(false, |features| features.has_aesni())
}

fn has_sse41() -> bool {
    cfg!(feature = "native")
        && CPUID
            .get_feature_info()
            .map_or(false, |features| features.has_sse41())
}

fn has_sse42() -> bool {
    cfg!(feature = "native")
        && CPUID
            .get_feature_info()
            .map_or(false, |features| features.has_sse42())
}

fn has_avx() -> bool {
    cfg!(feature = "native")
        && CPUID
            .get_feature_info()
            .map_or(false, |features| features.has_avx())
}

fn has_avx2() -> bool {
    cfg!(feature = "native")
        && CPUID
            .get_extended_feature_info()
            .map_or(false, |features| features.has_avx2())
}

fn support_aesni() -> bool {
    cfg!(any(feature = "aes", target_feature = "aes")) || has_aesni()
}

fn support_sse41() -> bool {
    cfg!(any(feature = "sse41", target_feature = "sse41")) || has_sse41()
}

fn support_sse42() -> bool {
    cfg!(any(feature = "sse42", target_feature = "sse42")) || has_sse42()
}

fn support_avx() -> bool {
    cfg!(any(feature = "avx", target_feature = "avx")) || has_avx()
}

fn support_avx2() -> bool {
    cfg!(any(feature = "avx2", target_feature = "avx2")) || has_avx2()
}

#[cfg(feature = "gen")]
fn generate_binding(out_file: &Path) {
    println!("generate binding file @ {:?}.", out_file);

    let _ = bindgen::builder()
        .clang_args(&["-x", "c++", "-std=c++11"])
        .clang_args(&[
            "-Dt1ha_EXPORTS",
            "-DXXH_STATIC_LINKING_ONLY",
            "-Isrc/highwayhash",
        ])
        .clang_args(if support_aesni() {
            &[
                "-maes",
                "-DT1HA0_RUNTIME_SELECT=1",
                "-DT1HA0_AESNI_AVAILABLE=1",
            ][..]
        } else {
            &[][..]
        })
        .clang_arg(if cfg!(feature = "native") {
            "-march=native"
        } else {
            ""
        })
        .clang_arg(if support_sse42() { "-msse4.2" } else { "" })
        .clang_arg(if support_avx() { "-mavx" } else { "" })
        .clang_arg(if support_avx2() { "-mavx2" } else { "" })
        .header("src/fasthash.hpp")
        .generate_inline_functions(true)
        .disable_name_namespacing()
        .whitelist_function("^CityHash.*")
        .whitelist_function("^farmhash.*")
        .whitelist_function("^lookup3.*")
        .whitelist_function("^metrohash.*")
        .whitelist_function("^mum_hash.*")
        .whitelist_function("^MurmurHash.*")
        .whitelist_function("^SpookyHasher.*")
        .whitelist_function("^t1ha.*")
        .blacklist_function("^t1ha_selfcheck__.*")
        .whitelist_function("^XXH.*")
        .whitelist_function("^HighwayHash.*")
        .generate()
        .unwrap()
        .write_to_file(out_file)
        .expect("fail to write bindings");
}

#[cfg(not(feature = "gen"))]
fn generate_binding(_out_file: &Path) {
    println!("direct include pregenerated binding file.");
}

fn build_fasthash() {
    let mut build = cc::Build::new();

    build
        .cpp(true)
        .flag("-std=c++11")
        .flag("-Wno-implicit-fallthrough")
        .flag("-Wno-unknown-attributes")
        .include("src/highwayhash")
        .file("src/fasthash.cpp")
        .file("src/smhasher/City.cpp")
        .file("src/smhasher/farmhash-c.c")
        .file("src/smhasher/lookup3.cpp")
        .file("src/smhasher/mum.cc")
        .file("src/smhasher/metrohash64.cpp")
        .file("src/smhasher/metrohash128.cpp")
        .file("src/smhasher/MurmurHash1.cpp")
        .file("src/smhasher/MurmurHash2.cpp")
        .file("src/smhasher/MurmurHash3.cpp")
        .file("src/smhasher/Spooky.cpp")
        .file("src/xxHash/xxhash.c");

    if support_sse42() {
        build
            .flag("-msse4.2")
            .file("src/smhasher/metrohash64crc.cpp")
            .file("src/smhasher/metrohash128crc.cpp");
    }

    build.static_flag(true).compile("fasthash");
}

fn build_t1() {
    let mut build = cc::Build::new();

    build
        .file("src/t1ha/src/t1ha0.c")
        .file("src/t1ha/src/t1ha1.c")
        .file("src/t1ha/src/t1ha2.c");

    if support_aesni() {
        build
            .define("T1HA0_RUNTIME_SELECT", Some("1"))
            .define("T1HA0_AESNI_AVAILABLE", Some("1"))
            .flag("-maes")
            .file("src/t1ha/src/t1ha0_ia32aes_noavx.c")
            .file("src/t1ha/src/t1ha0_ia32aes_avx.c")
            .file("src/t1ha/src/t1ha0_ia32aes_avx2.c");

        if support_avx() {
            build.flag("-mavx");
        }

        if support_avx2() {
            build.flag("-mavx2");
        }
    }

    build.static_flag(true).compile("t1ha");
}

fn build_highway() {
    let mut build = cc::Build::new();

    build
        .cpp(true)
        .flag("-std=c++11")
        .include("src/highwayhash")
        .file("src/highwayhash/highwayhash/arch_specific.cc")
        .file("src/highwayhash/highwayhash/instruction_sets.cc")
        .file("src/highwayhash/highwayhash/os_specific.cc")
        .file("src/highwayhash/highwayhash/hh_portable.cc")
        .file("src/highwayhash/highwayhash/c_bindings.cc");

    if support_sse41() {
        build
            .flag("-msse4.1")
            .file("src/highwayhash/highwayhash/hh_sse41.cc");
    }

    if support_avx2() {
        build
            .flag("-mavx2")
            .file("src/highwayhash/highwayhash/hh_avx2.cc");
    }

    build.static_flag(true).compile("highwayhash");
}

fn main() {
    if has_aesni() {
        println!(r#"cargo:rustc-cfg=feature="aes""#);
    }
    if has_sse41() {
        println!(r#"cargo:rustc-cfg=feature="sse41""#);
    }
    if has_sse42() {
        println!(r#"cargo:rustc-cfg=feature="sse42""#);
    }
    if has_avx() {
        println!(r#"cargo:rustc-cfg=feature="avx""#);
    }
    if has_avx2() {
        println!(r#"cargo:rustc-cfg=feature="avx2""#);
    }

    build_fasthash();
    build_t1();
    build_highway();

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_file = Path::new(&out_dir).join("fasthash.rs");

    println!("cargo:rerun-if-changed=src/fasthash.hpp");
    println!("cargo:rerun-if-changed=src/fasthash.cpp");

    generate_binding(&out_file);
}
<commit_msg>force to add highway SSE4.1/AVX2 support to x64<commit_after>use std::env;
use std::path::Path;

use lazy_static::lazy_static;
use raw_cpuid::CpuId;

lazy_static! {
    static ref CPUID: CpuId = CpuId::new();
}

fn has_aesni() -> bool {
    cfg!(feature = "native")
        && CPUID
            .get_feature_info()
            .map_or(false, |features| features.has_aesni())
}

fn has_sse41() -> bool {
    cfg!(feature = "native")
        && CPUID
            .get_feature_info()
            .map_or(false, |features| features.has_sse41())
}

fn has_sse42() -> bool {
    cfg!(feature = "native")
        && CPUID
            .get_feature_info()
            .map_or(false, |features| features.has_sse42())
}

fn has_avx() -> bool {
    cfg!(feature = "native")
        && CPUID
            .get_feature_info()
            .map_or(false, |features| features.has_avx())
}

fn has_avx2() -> bool {
    cfg!(feature = "native")
        && CPUID
            .get_extended_feature_info()
            .map_or(false, |features| features.has_avx2())
}

fn support_aesni() -> bool {
    cfg!(any(feature = "aes", target_feature = "aes")) || has_aesni()
}

fn support_sse41() -> bool {
    cfg!(any(feature = "sse41", target_feature = "sse41")) || has_sse41()
}

fn support_sse42() -> bool {
    cfg!(any(feature = "sse42", target_feature = "sse42")) || has_sse42()
}

fn support_avx() -> bool {
    cfg!(any(feature = "avx", target_feature = "avx")) || has_avx()
}

fn support_avx2() -> bool {
    cfg!(any(feature = "avx2", target_feature = "avx2")) || has_avx2()
}

#[cfg(feature = "gen")]
fn generate_binding(out_file: &Path) {
    println!("generate binding file @ {:?}.", out_file);

    let _ = bindgen::builder()
        .clang_args(&["-x", "c++", "-std=c++11"])
        .clang_args(&[
            "-Dt1ha_EXPORTS",
            "-DXXH_STATIC_LINKING_ONLY",
            "-Isrc/highwayhash",
        ])
        .clang_args(if support_aesni() {
            &[
                "-maes",
                "-DT1HA0_RUNTIME_SELECT=1",
                "-DT1HA0_AESNI_AVAILABLE=1",
            ][..]
        } else {
            &[][..]
        })
        .clang_arg(if cfg!(feature = "native") {
            "-march=native"
        } else {
            ""
        })
        .clang_arg(if support_sse42() { "-msse4.2" } else { "" })
        .clang_arg(if support_avx() { "-mavx" } else { "" })
        .clang_arg(if support_avx2() { "-mavx2" } else { "" })
        .header("src/fasthash.hpp")
        .generate_inline_functions(true)
        .disable_name_namespacing()
        .whitelist_function("^CityHash.*")
        .whitelist_function("^farmhash.*")
        .whitelist_function("^lookup3.*")
        .whitelist_function("^metrohash.*")
        .whitelist_function("^mum_hash.*")
        .whitelist_function("^MurmurHash.*")
        .whitelist_function("^SpookyHasher.*")
        .whitelist_function("^t1ha.*")
        .blacklist_function("^t1ha_selfcheck__.*")
        .whitelist_function("^XXH.*")
        .whitelist_function("^HighwayHash.*")
        .generate()
        .unwrap()
        .write_to_file(out_file)
        .expect("fail to write bindings");
}

#[cfg(not(feature = "gen"))]
fn generate_binding(_out_file: &Path) {
    println!("direct include pregenerated binding file.");
}

fn build_fasthash() {
    let mut build = cc::Build::new();

    build
        .cpp(true)
        .flag("-std=c++11")
        .flag("-Wno-implicit-fallthrough")
        .flag("-Wno-unknown-attributes")
        .include("src/highwayhash")
        .file("src/fasthash.cpp")
        .file("src/smhasher/City.cpp")
        .file("src/smhasher/farmhash-c.c")
        .file("src/smhasher/lookup3.cpp")
        .file("src/smhasher/mum.cc")
        .file("src/smhasher/metrohash64.cpp")
        .file("src/smhasher/metrohash128.cpp")
        .file("src/smhasher/MurmurHash1.cpp")
        .file("src/smhasher/MurmurHash2.cpp")
        .file("src/smhasher/MurmurHash3.cpp")
        .file("src/smhasher/Spooky.cpp")
        .file("src/xxHash/xxhash.c");

    if support_sse42() {
        build
            .flag("-msse4.2")
            .file("src/smhasher/metrohash64crc.cpp")
            .file("src/smhasher/metrohash128crc.cpp");
    }

    build.static_flag(true).compile("fasthash");
}

fn build_t1() {
    let mut build = cc::Build::new();

    build
        .file("src/t1ha/src/t1ha0.c")
        .file("src/t1ha/src/t1ha1.c")
        .file("src/t1ha/src/t1ha2.c");

    if support_aesni() {
        build
            .define("T1HA0_RUNTIME_SELECT", Some("1"))
            .define("T1HA0_AESNI_AVAILABLE", Some("1"))
            .flag("-maes")
            .file("src/t1ha/src/t1ha0_ia32aes_noavx.c")
            .file("src/t1ha/src/t1ha0_ia32aes_avx.c")
            .file("src/t1ha/src/t1ha0_ia32aes_avx2.c");

        if support_avx() {
            build.flag("-mavx");
        }

        if support_avx2() {
            build.flag("-mavx2");
        }
    }

    build.static_flag(true).compile("t1ha");
}

fn build_highway() {
    let mut build = cc::Build::new();

    build
        .cpp(true)
        .flag("-std=c++11")
        .include("src/highwayhash")
        .file("src/highwayhash/highwayhash/arch_specific.cc")
        .file("src/highwayhash/highwayhash/instruction_sets.cc")
        .file("src/highwayhash/highwayhash/os_specific.cc")
        .file("src/highwayhash/highwayhash/hh_portable.cc")
        .file("src/highwayhash/highwayhash/c_bindings.cc");

    if cfg!(target_arch = "x86_64") {
        if support_sse41() {
            build.flag("-msse4.1");
        }

        if support_avx2() {
            build.flag("-mavx2");
        }

        build
            .file("src/highwayhash/highwayhash/hh_sse41.cc")
            .file("src/highwayhash/highwayhash/hh_avx2.cc");
    }

    build.static_flag(true).compile("highwayhash");
}

fn main() {
    if has_aesni() {
        println!(r#"cargo:rustc-cfg=feature="aes""#);
    }
    if has_sse41() {
        println!(r#"cargo:rustc-cfg=feature="sse41""#);
    }
    if has_sse42() {
        println!(r#"cargo:rustc-cfg=feature="sse42""#);
    }
    if has_avx() {
        println!(r#"cargo:rustc-cfg=feature="avx""#);
    }
    if has_avx2() {
        println!(r#"cargo:rustc-cfg=feature="avx2""#);
    }

    build_fasthash();
    build_t1();
    build_highway();

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_file = Path::new(&out_dir).join("fasthash.rs");

    println!("cargo:rerun-if-changed=src/fasthash.hpp");
    println!("cargo:rerun-if-changed=src/fasthash.cpp");

    generate_binding(&out_file);
}
<|endoftext|>


<commit_before>#[macro_escape];

pub macro_rules! wxApp(
    ($f: ident) => (
        fn start(argc: int, argv: **u8) -> int {
            #[start];

            use std::libc::c_void;
            use std::vec;

            use wx::base::wxClosure;
            use wx::core::ELJApp;

            static nullptr: *mut c_void = 0 as *mut c_void;

            native::start(argc, argv, proc() {
                let closure = wxClosure::new($f as *mut c_void, nullptr);
                let args: ~[*i32] = ~[];
                ELJApp::initializeC(closure, args.len() as i32, args.as_ptr() as *mut *mut i8);
            });
        }
    )
)
<commit_msg>Fix build.<commit_after>#[macro_escape];

pub macro_rules! wxApp(
    ($f: ident) => (
        fn start(argc: int, argv: **u8) -> int {
            #[start];

            use std::libc::c_void;
            use std::vec;

            use wx::base::wxClosure;
            use wx::core::ELJApp;

            static nullptr: *mut c_void = 0 as *mut c_void;

            native::start(argc, argv, proc() {
                let closure = wxClosure::new($f as *mut c_void, nullptr);
                let args: ~[*i32] = ~[];
                ELJApp::initializeC(closure, args.len() as i32, args.as_ptr() as *mut *mut i8);
            })
        }
    )
)
<|endoftext|>


<commit_before>extern crate futures;

use futures::{failed, finished, Future, oneshot, Poll, Task};
use futures::stream::*;

mod support;
use support::*;

fn list() -> Receiver<i32, u32> {
    let (tx, rx) = channel();
    tx.send(Ok(1))
      .and_then(|tx| tx.send(Ok(2)))
      .and_then(|tx| tx.send(Ok(3)))
      .forget();
    return rx
}

fn err_list() -> Receiver<i32, u32> {
    let (tx, rx) = channel();
    tx.send(Ok(1))
      .and_then(|tx| tx.send(Ok(2)))
      .and_then(|tx| tx.send(Err(3)))
      .forget();
    return rx
}

#[test]
fn adapters() {
    assert_done(|| list().map(|a| a + 1).collect(), Ok(vec![2, 3, 4]));
    assert_done(|| err_list().map_err(|a| a + 1).collect(), Err(4));
    assert_done(|| list().fold(0, |a, b| finished::<i32, u32>(a + b)), Ok(6));
    assert_done(|| err_list().fold(0, |a, b| finished::<i32, u32>(a + b)), Err(3));
    assert_done(|| list().filter(|a| *a % 2 == 0).collect(), Ok(vec![2]));
    assert_done(|| list().filter_map(|x| {
        if x % 2 == 0 {
            Some(x + 10)
        } else {
            None
        }
    }).collect(), Ok(vec![12]));
    assert_done(|| list().and_then(|a| Ok(a + 1)).collect(), Ok(vec![2, 3, 4]));
    assert_done(|| list().then(|a| a.map(|e| e + 1)).collect(), Ok(vec![2, 3, 4]));
    assert_done(|| list().and_then(|a| failed::<i32, u32>(a as u32)).collect(),
                Err(1));
    assert_done(|| err_list().or_else(|a| {
        finished::<i32, u32>(a as i32)
    }).collect(), Ok(vec![1, 2, 3]));
    assert_done(|| list().map(|_| list()).flatten().collect(),
                Ok(vec![1, 2, 3, 1, 2, 3, 1, 2, 3]));
    assert_done(|| list().skip_while(|e| Ok(*e % 2 == 1)).collect(),
                Ok(vec![2, 3]));
    assert_done(|| list().take(2).collect(), Ok(vec![1, 2]));
    assert_done(|| list().skip(2).collect(), Ok(vec![3]));
    assert_done(|| list().peekable().collect(), Ok(vec![1, 2, 3]));
}

#[test]
fn fuse() {
    let mut stream = list().fuse();
    let mut task = Task::new();
    assert_eq!(stream.poll(&mut task), Poll::Ok(Some(1)));
    assert_eq!(stream.poll(&mut task), Poll::Ok(Some(2)));
    assert_eq!(stream.poll(&mut task), Poll::Ok(Some(3)));
    assert_eq!(stream.poll(&mut task), Poll::Ok(None));
    assert_eq!(stream.poll(&mut task), Poll::Ok(None));
    assert_eq!(stream.poll(&mut task), Poll::Ok(None));
}

#[test]
fn buffered() {
    let (tx, rx) = channel::<_, u32>();
    let (a, b) = oneshot::<u32>();
    let (c, d) = oneshot::<u32>();

    tx.send(Ok(b.map_err(|_| 2).boxed()))
      .and_then(|tx| tx.send(Ok(d.map_err(|_| 4).boxed())))
      .forget();

    let mut rx = rx.buffered(2);
    sassert_empty(&mut rx);
    c.complete(3);
    sassert_empty(&mut rx);
    a.complete(5);
    sassert_next(&mut rx, 5);
    sassert_next(&mut rx, 3);
    sassert_done(&mut rx);

    let (tx, rx) = channel::<_, u32>();
    let (a, b) = oneshot::<u32>();
    let (c, d) = oneshot::<u32>();

    tx.send(Ok(b.map_err(|_| 2).boxed()))
      .and_then(|tx| tx.send(Ok(d.map_err(|_| 4).boxed())))
      .forget();

    let mut rx = rx.buffered(1);
    sassert_empty(&mut rx);
    c.complete(3);
    sassert_empty(&mut rx);
    a.complete(5);
    sassert_next(&mut rx, 5);
    sassert_next(&mut rx, 3);
    sassert_done(&mut rx);
}

#[test]
fn zip() {
    assert_done(|| list().zip(list()).collect(),
                Ok(vec![(1, 1), (2, 2), (3, 3)]));
    assert_done(|| list().zip(list().take(2)).collect(),
                Ok(vec![(1, 1), (2, 2)]));
    assert_done(|| list().take(2).zip(list()).collect(),
                Ok(vec![(1, 1), (2, 2)]));
    assert_done(|| err_list().zip(list()).collect(), Err(3));
    assert_done(|| list().zip(list().map(|x| x + 1)).collect(),
                Ok(vec![(1, 2), (2, 3), (3, 4)]));
}

#[test]
fn peek() {
    let mut peekable = list().peekable();
    assert_eq!(peekable.peek(&mut Task::new()).unwrap(), Ok(Some(&1)));
    assert_eq!(peekable.peek(&mut Task::new()).unwrap(), Ok(Some(&1)));
    assert_eq!(peekable.poll(&mut Task::new()).unwrap(), Ok(Some(1)));
}
<commit_msg>split adapters tests for streams into individual test methods<commit_after>extern crate futures;

use futures::{failed, finished, Future, oneshot, Poll, Task};
use futures::stream::*;

mod support;
use support::*;

fn list() -> Receiver<i32, u32> {
    let (tx, rx) = channel();
    tx.send(Ok(1))
      .and_then(|tx| tx.send(Ok(2)))
      .and_then(|tx| tx.send(Ok(3)))
      .forget();
    return rx
}

fn err_list() -> Receiver<i32, u32> {
    let (tx, rx) = channel();
    tx.send(Ok(1))
      .and_then(|tx| tx.send(Ok(2)))
      .and_then(|tx| tx.send(Err(3)))
      .forget();
    return rx
}

#[test]
fn map () {
    assert_done(|| list().map(|a| a + 1).collect(), Ok(vec![2, 3, 4]));
}
#[test]
fn map_err () {
    assert_done(|| err_list().map_err(|a| a + 1).collect(), Err(4));
}
#[test]
fn fold () {
    assert_done(|| list().fold(0, |a, b| finished::<i32, u32>(a + b)), Ok(6));
    assert_done(|| err_list().fold(0, |a, b| finished::<i32, u32>(a + b)), Err(3));
}
#[test]
fn filter () {
    assert_done(|| list().filter(|a| *a % 2 == 0).collect(), Ok(vec![2]));
}
#[test]
fn filter_map () {
    assert_done(|| list().filter_map(|x| {
        if x % 2 == 0 {
            Some(x + 10)
        } else {
            None
        }
    }).collect(), Ok(vec![12]));
}
#[test]
fn and_then () {
    assert_done(|| list().and_then(|a| Ok(a + 1)).collect(), Ok(vec![2, 3, 4]));
    assert_done(|| list().and_then(|a| failed::<i32, u32>(a as u32)).collect(),
                Err(1));
}
#[test]
fn then () {
    assert_done(|| list().then(|a| a.map(|e| e + 1)).collect(), Ok(vec![2, 3, 4]));

}

#[test]
fn or_else() {
    assert_done(|| err_list().or_else(|a| {
        finished::<i32, u32>(a as i32)
    }).collect(), Ok(vec![1, 2, 3]));
}

#[test]
fn flatten () {
    assert_done(|| list().map(|_| list()).flatten().collect(),
                Ok(vec![1, 2, 3, 1, 2, 3, 1, 2, 3]));

}

#[test]
fn skip () {
    assert_done(|| list().skip(2).collect(), Ok(vec![3]));
}

#[test]
fn skip_while () {
    assert_done(|| list().skip_while(|e| Ok(*e % 2 == 1)).collect(),
                Ok(vec![2, 3]));
}
#[test]
fn take () {
    assert_done(|| list().take(2).collect(), Ok(vec![1, 2]));
}

#[test]
fn peekable () {
    assert_done(|| list().peekable().collect(), Ok(vec![1, 2, 3]));
}

#[test]
fn fuse() {
    let mut stream = list().fuse();
    let mut task = Task::new();
    assert_eq!(stream.poll(&mut task), Poll::Ok(Some(1)));
    assert_eq!(stream.poll(&mut task), Poll::Ok(Some(2)));
    assert_eq!(stream.poll(&mut task), Poll::Ok(Some(3)));
    assert_eq!(stream.poll(&mut task), Poll::Ok(None));
    assert_eq!(stream.poll(&mut task), Poll::Ok(None));
    assert_eq!(stream.poll(&mut task), Poll::Ok(None));
}

#[test]
fn buffered() {
    let (tx, rx) = channel::<_, u32>();
    let (a, b) = oneshot::<u32>();
    let (c, d) = oneshot::<u32>();

    tx.send(Ok(b.map_err(|_| 2).boxed()))
      .and_then(|tx| tx.send(Ok(d.map_err(|_| 4).boxed())))
      .forget();

    let mut rx = rx.buffered(2);
    sassert_empty(&mut rx);
    c.complete(3);
    sassert_empty(&mut rx);
    a.complete(5);
    sassert_next(&mut rx, 5);
    sassert_next(&mut rx, 3);
    sassert_done(&mut rx);

    let (tx, rx) = channel::<_, u32>();
    let (a, b) = oneshot::<u32>();
    let (c, d) = oneshot::<u32>();

    tx.send(Ok(b.map_err(|_| 2).boxed()))
      .and_then(|tx| tx.send(Ok(d.map_err(|_| 4).boxed())))
      .forget();

    let mut rx = rx.buffered(1);
    sassert_empty(&mut rx);
    c.complete(3);
    sassert_empty(&mut rx);
    a.complete(5);
    sassert_next(&mut rx, 5);
    sassert_next(&mut rx, 3);
    sassert_done(&mut rx);
}

#[test]
fn zip() {
    assert_done(|| list().zip(list()).collect(),
                Ok(vec![(1, 1), (2, 2), (3, 3)]));
    assert_done(|| list().zip(list().take(2)).collect(),
                Ok(vec![(1, 1), (2, 2)]));
    assert_done(|| list().take(2).zip(list()).collect(),
                Ok(vec![(1, 1), (2, 2)]));
    assert_done(|| err_list().zip(list()).collect(), Err(3));
    assert_done(|| list().zip(list().map(|x| x + 1)).collect(),
                Ok(vec![(1, 2), (2, 3), (3, 4)]));
}

#[test]
fn peek() {
    let mut peekable = list().peekable();
    assert_eq!(peekable.peek(&mut Task::new()).unwrap(), Ok(Some(&1)));
    assert_eq!(peekable.peek(&mut Task::new()).unwrap(), Ok(Some(&1)));
    assert_eq!(peekable.poll(&mut Task::new()).unwrap(), Ok(Some(1)));
}
<|endoftext|>


<commit_before>use game::gfx::{Sprite, CopySprite, AnimatedSprite};
use game::data::Rectangle;
use game::constants::{ZOMBIE_POS_W, ZOMBIE_POS_H, ZOMBIE_W, ZOMBIE_H, ZOMBIE_PATH};
use sdl2::render::Renderer;
use views::{Orientation};
use data::{load_zombie};

pub struct Zombie {
  pub sprite: AnimatedSprite,
  pub rect: Rectangle,
  pub current: Orientation,
  pub heading: Orientation,
  pub idle_anim_index: u32,
}

impl Zombie {
  pub fn new(renderer: &mut Renderer) -> Zombie {
    Zombie {
      rect: Rectangle {
        x: ZOMBIE_POS_W,
        y: ZOMBIE_POS_H,
        w: ZOMBIE_W,
        h: ZOMBIE_H,
      },
      sprite: Zombie::get_sprites(renderer, 10.0),
      current: Orientation::Down,
      heading: Orientation::Down,
      idle_anim_index: 0,
    }
  }

  fn get_sprites(renderer: &mut Renderer, fps: f64) -> AnimatedSprite {
    let zombie_spritesheet = Sprite::load(&renderer, ZOMBIE_PATH).unwrap();
    let mut zombie_sprites = Vec::with_capacity(512);
    let zombie_datapoints = load_zombie();

    for x in 0..(zombie_datapoints.len() - 1) {
      zombie_sprites.push(zombie_spritesheet.region(zombie_datapoints[x]).unwrap());
    }

    AnimatedSprite::with_fps(zombie_sprites, fps)
  }

  pub fn update(&mut self, dt: f64) {
    self.sprite.add_time(dt);
  }

  pub fn render(&mut self, renderer: &mut Renderer) {
    renderer.copy_sprite(&self.sprite, self.rect);
  }
}
<commit_msg>Fix zombie rendering<commit_after>use game::gfx::{Sprite, CopySprite, AnimatedSprite};
use game::data::Rectangle;
use game::constants::{ZOMBIE_POS_W, ZOMBIE_POS_H, ZOMBIE_W, ZOMBIE_H, ZOMBIE_PATH};
use sdl2::render::Renderer;
use views::{Orientation};
use data::{load_zombie};

pub struct Zombie {
  pub sprite: AnimatedSprite,
  pub rect: Rectangle,
  pub current: Orientation,
  pub heading: Orientation,
  pub idle_anim_index: u32,
}

impl Zombie {
  pub fn new(renderer: &mut Renderer) -> Zombie {
    Zombie {
      rect: Rectangle {
        x: ZOMBIE_POS_W,
        y: ZOMBIE_POS_H,
        w: ZOMBIE_W,
        h: ZOMBIE_H,
      },
      sprite: Zombie::get_sprites(renderer, 10.0),
      current: Orientation::Down,
      heading: Orientation::Down,
      idle_anim_index: 0,
    }
  }

  fn get_sprites(renderer: &mut Renderer, fps: f64) -> AnimatedSprite {
    let zombie_spritesheet = Sprite::load(&renderer, ZOMBIE_PATH).unwrap();
    let mut zombie_sprites = Vec::with_capacity(512);
    let zombie_datapoints = load_zombie();

    for x in 0..(zombie_datapoints.len() - 1) {
      zombie_sprites.push(zombie_spritesheet.region(zombie_datapoints[x]).unwrap());
    }

    AnimatedSprite::with_fps(zombie_sprites, fps)
  }

  pub fn update(&mut self, dt: f64) {
    self.sprite.add_time(dt);
    self.sprite.set_curr_frames(0, 4);
  }

  pub fn render(&mut self, renderer: &mut Renderer) {
    renderer.copy_sprite(&self.sprite, self.rect);
  }
}
<|endoftext|>