<commit_before>#![feature(env)]
#![feature(core)]
#![feature(old_io)]
#![feature(old_path)]

use std::env;
use std::old_io::Command;
use std::old_io::process::InheritFd;

fn main() {
    let dst = Path::new(env::var("OUT_DIR").unwrap());

    setup();
    configure();
    build();
    install(&dst);
    clean();
    println!("cargo:rustc-flags=-L {} -l termbox:static", dst.join("lib").display());
}

fn setup() {
    let mut cmd = Command::new("git");
    cmd.arg("clone");
    cmd.arg("https://github.com/nsf/termbox");
    cmd.arg(".termbox");
    let cargo_dir = Path::new(env::var("CARGO_MANIFEST_DIR").unwrap());
    cmd.cwd(&cargo_dir);

    run(&mut cmd);
}

fn clean() {
    let mut cmd = Command::new("rm");
    cmd.arg("-rf");
    cmd.arg(".termbox");
    let cargo_dir = Path::new(env::var("CARGO_MANIFEST_DIR").unwrap());
    cmd.cwd(&cargo_dir);
    run(&mut cmd);
}

fn configure() {
    let mut cmd = waf();
    cmd.arg("configure");
    cmd.arg("--prefix=/");

    let target = env::var("TARGET").unwrap();
    let mut cflags;
    if target.as_slice().contains("i686") {
        cflags = "-m32"
    } else if target.as_slice().contains("x86_64") {
        cflags = "-m64 -fPIC"
    } else {
        cflags = ""
    }
    println!("waf configure: setting CFLAGS to: `{}`", cflags);
    env::set_var("CFLAGS", cflags);

    run(&mut cmd);
    env::remove_var("CFLAGS");
}

fn build() {
    let mut cmd = waf();
    cmd.arg("build");
    cmd.arg("--targets=termbox_static");
    run(&mut cmd);
}

fn install(dst: &Path) {
    let mut cmd = waf();
    cmd.arg("install");
    cmd.arg("--targets=termbox_static");
    cmd.arg(format!("--destdir={}", dst.display()));
    run(&mut cmd);
}

fn waf() -> Command {
    let cargo_dir = Path::new(env::var("CARGO_MANIFEST_DIR").unwrap());
    let termbox_dir = cargo_dir.join(".termbox");
    let mut cmd = Command::new("./waf");
    cmd.cwd(&termbox_dir);
    cmd
}

fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    assert!(cmd.stdout(InheritFd(1))
                .stderr(InheritFd(2))
                .status()
                .unwrap()
                .success());
}
<commit_msg>Updated to latest rust<commit_after>#![feature(core)]

use std::env;
use std::path::Path;
use std::process::{Stdio, Command};

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let dst = Path::new(out_dir.as_slice());

    setup();
    configure();
    build();
    install(&dst);
    clean();
    println!("cargo:rustc-flags=-L {} -l termbox:static", dst.join("lib").display());
}

fn setup() {
    let mut cmd = Command::new("git");
    cmd.arg("clone");
    cmd.arg("https://github.com/nsf/termbox");
    cmd.arg(".termbox");
    let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let cargo_dir = Path::new(manifest_dir.as_slice());
    cmd.current_dir(&cargo_dir);

    run(&mut cmd);
}

fn clean() {
    let mut cmd = Command::new("rm");
    cmd.arg("-rf");
    cmd.arg(".termbox");
    let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let cargo_dir = Path::new(manifest_dir.as_slice());
    cmd.current_dir(&cargo_dir);
    run(&mut cmd);
}

fn configure() {
    let mut cmd = waf();
    cmd.arg("configure");
    cmd.arg("--prefix=/");

    let target = env::var("TARGET").unwrap();
    let mut cflags;
    if target.as_slice().contains("i686") {
        cflags = "-m32"
    } else if target.as_slice().contains("x86_64") {
        cflags = "-m64 -fPIC"
    } else {
        cflags = ""
    }
    println!("waf configure: setting CFLAGS to: `{}`", cflags);
    env::set_var("CFLAGS", cflags);

    run(&mut cmd);
    env::remove_var("CFLAGS");
}

fn build() {
    let mut cmd = waf();
    cmd.arg("build");
    cmd.arg("--targets=termbox_static");
    run(&mut cmd);
}

fn install(dst: &Path) {
    let mut cmd = waf();
    cmd.arg("install");
    cmd.arg("--targets=termbox_static");
    cmd.arg(format!("--destdir={}", dst.display()));
    run(&mut cmd);
}

fn waf() -> Command {
    let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let cargo_dir = Path::new(manifest_dir.as_slice());
    let termbox_dir = cargo_dir.join(".termbox");
    let mut cmd = Command::new("./waf");
    cmd.current_dir(&termbox_dir);
    cmd
}

fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    assert!(cmd.stdout(Stdio::inherit())
                .stderr(Stdio::inherit())
                .status()
                .unwrap()
                .success());
}
<|endoftext|>


<commit_before>extern crate cmake;
extern crate pkg_config;

use cmake::Config;
use std::env;
use std::path::PathBuf;

fn main() {
    match pkg_config::find_library("heartbeats-simple") {
        Ok(_) => (),
        Err(_) => {
            let src = PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"), "/heartbeats-simple"));
            let mut config = Config::new(&src);

            // build/install everything - the build is fast and portable enough
            // cmake crate makes it too troublesome to do individual targets since it expects to install
            let dst: PathBuf = config.build();
            // none of the libraries have transitive dependencies
            println!("cargo:rustc-link-lib=static=heartbeats-simple");
            println!("cargo:rustc-link-search=native={}", dst.join("lib").display());
        },
    }
}
<commit_msg>Remove unused import<commit_after>extern crate cmake;
extern crate pkg_config;

use cmake::Config;
use std::path::PathBuf;

fn main() {
    match pkg_config::find_library("heartbeats-simple") {
        Ok(_) => (),
        Err(_) => {
            let src = PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"), "/heartbeats-simple"));
            let mut config = Config::new(&src);

            // build/install everything - the build is fast and portable enough
            // cmake crate makes it too troublesome to do individual targets since it expects to install
            let dst: PathBuf = config.build();
            // none of the libraries have transitive dependencies
            println!("cargo:rustc-link-lib=static=heartbeats-simple");
            println!("cargo:rustc-link-search=native={}", dst.join("lib").display());
        },
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
// Copyright 2016-2017 The Rust Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The binomial distribution.

use Rng;
use distributions::{Distribution, Bernoulli, Cauchy};
use distributions::utils::log_gamma;

/// The binomial distribution `Binomial(n, p)`.
///
/// This distribution has density function:
/// `f(k) = n!/(k! (n-k)!) p^k (1-p)^(n-k)` for `k >= 0`.
///
/// # Example
///
/// ```
/// use rand::distributions::{Binomial, Distribution};
///
/// let bin = Binomial::new(20, 0.3);
/// let v = bin.sample(&mut rand::thread_rng());
/// println!("{} is from a binomial distribution", v);
/// ```
#[derive(Clone, Copy, Debug)]
pub struct Binomial {
    /// Number of trials.
    n: u64,
    /// Probability of success.
    p: f64,
}

impl Binomial {
    /// Construct a new `Binomial` with the given shape parameters `n` (number
    /// of trials) and `p` (probability of success).
    ///
    /// Panics if `p < 0` or `p > 1`.
    pub fn new(n: u64, p: f64) -> Binomial {
        assert!(p >= 0.0, "Binomial::new called with p < 0");
        assert!(p <= 1.0, "Binomial::new called with p > 1");
        Binomial { n, p }
    }
}

impl Distribution<u64> for Binomial {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u64 {
        // Handle these values directly.
        if self.p == 0.0 {
            return 0;
        } else if self.p == 1.0 {
            return self.n;
        }

        // For low n, it is faster to sample directly. For both methods,
        // performance is independent of p. On Intel Haswell CPU this method
        // appears to be faster for approx n < 300.
        if self.n < 300 {
            let mut result = 0;
            let d = Bernoulli::new(self.p);
            for _ in 0 .. self.n {
                result += rng.sample(d) as u32;
            }
            return result as u64;
        }

        // binomial distribution is symmetrical with respect to p -> 1-p, k -> n-k
        // switch p so that it is less than 0.5 - this allows for lower expected values
        // we will just invert the result at the end
        let p = if self.p <= 0.5 {
            self.p
        } else {
            1.0 - self.p
        };

        // prepare some cached values
        let float_n = self.n as f64;
        let ln_fact_n = log_gamma(float_n + 1.0);
        let pc = 1.0 - p;
        let log_p = p.ln();
        let log_pc = pc.ln();
        let expected = self.n as f64 * p;
        let sq = (expected * (2.0 * pc)).sqrt();

        let mut lresult;

        // we use the Cauchy distribution as the comparison distribution
        // f(x) ~ 1/(1+x^2)
        let cauchy = Cauchy::new(0.0, 1.0);
        loop {
            let mut comp_dev: f64;
            loop {
                // draw from the Cauchy distribution
                comp_dev = rng.sample(cauchy);
                // shift the peak of the comparison ditribution
                lresult = expected + sq * comp_dev;
                // repeat the drawing until we are in the range of possible values
                if lresult >= 0.0 && lresult < float_n + 1.0 {
                    break;
                }
            }

            // the result should be discrete
            lresult = lresult.floor();

            let log_binomial_dist = ln_fact_n - log_gamma(lresult+1.0) -
                log_gamma(float_n - lresult + 1.0) + lresult*log_p + (float_n - lresult)*log_pc;
            // this is the binomial probability divided by the comparison probability
            // we will generate a uniform random value and if it is larger than this,
            // we interpret it as a value falling out of the distribution and repeat
            let comparison_coeff = (log_binomial_dist.exp() * sq) * (1.2 * (1.0 + comp_dev*comp_dev));

            if comparison_coeff >= rng.gen() {
                break;
            }
        }

        // invert the result for p < 0.5
        if p != self.p {
            self.n - lresult as u64
        } else {
            lresult as u64
        }
    }
}

#[cfg(test)]
mod test {
    use Rng;
    use distributions::Distribution;
    use super::Binomial;

    fn test_binomial_mean_and_variance<R: Rng>(n: u64, p: f64, rng: &mut R) {
        let binomial = Binomial::new(n, p);

        let expected_mean = n as f64 * p;
        let expected_variance = n as f64 * p * (1.0 - p);

        let mut results = [0.0; 1000];
        for i in results.iter_mut() { *i = binomial.sample(rng) as f64; }

        let mean = results.iter().sum::<f64>() / results.len() as f64;
        assert!((mean as f64 - expected_mean).abs() < expected_mean / 50.0);

        let variance =
            results.iter().map(|x| (x - mean) * (x - mean)).sum::<f64>()
            / results.len() as f64;
        assert!((variance - expected_variance).abs() < expected_variance / 10.0);
    }

    #[test]
    fn test_binomial() {
        let mut rng = ::test::rng(351);
        test_binomial_mean_and_variance(150, 0.1, &mut rng);
        test_binomial_mean_and_variance(70, 0.6, &mut rng);
        test_binomial_mean_and_variance(40, 0.5, &mut rng);
        test_binomial_mean_and_variance(20, 0.7, &mut rng);
        test_binomial_mean_and_variance(20, 0.5, &mut rng);
    }

    #[test]
    fn test_binomial_end_points() {
        let mut rng = ::test::rng(352);
        assert_eq!(rng.sample(Binomial::new(20, 0.0)), 0);
        assert_eq!(rng.sample(Binomial::new(20, 1.0)), 20);
    }

    #[test]
    #[should_panic]
    fn test_binomial_invalid_lambda_neg() {
        Binomial::new(20, -10.0);
    }
}
<commit_msg>Binomial: Faster sampling for n * p < 10<commit_after>// Copyright 2018 Developers of the Rand project.
// Copyright 2016-2017 The Rust Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The binomial distribution.

use Rng;
use distributions::{Distribution, Cauchy};
use distributions::utils::log_gamma;

/// The binomial distribution `Binomial(n, p)`.
///
/// This distribution has density function:
/// `f(k) = n!/(k! (n-k)!) p^k (1-p)^(n-k)` for `k >= 0`.
///
/// # Example
///
/// ```
/// use rand::distributions::{Binomial, Distribution};
///
/// let bin = Binomial::new(20, 0.3);
/// let v = bin.sample(&mut rand::thread_rng());
/// println!("{} is from a binomial distribution", v);
/// ```
#[derive(Clone, Copy, Debug)]
pub struct Binomial {
    /// Number of trials.
    n: u64,
    /// Probability of success.
    p: f64,
}

impl Binomial {
    /// Construct a new `Binomial` with the given shape parameters `n` (number
    /// of trials) and `p` (probability of success).
    ///
    /// Panics if `p < 0` or `p > 1`.
    pub fn new(n: u64, p: f64) -> Binomial {
        assert!(p >= 0.0, "Binomial::new called with p < 0");
        assert!(p <= 1.0, "Binomial::new called with p > 1");
        Binomial { n, p }
    }
}

impl Distribution<u64> for Binomial {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u64 {
        // Handle these values directly.
        if self.p == 0.0 {
            return 0;
        } else if self.p == 1.0 {
            return self.n;
        }

        // binomial distribution is symmetrical with respect to p -> 1-p, k -> n-k
        // switch p so that it is less than 0.5 - this allows for lower expected values
        // we will just invert the result at the end
        let p = if self.p <= 0.5 {
            self.p
        } else {
            1.0 - self.p
        };

        let result;

        // For small n * min(p, 1 - p), the BINV algorithm based on the inverse
        // transformation of the binomial distribution is more efficient:
        //
        // Voratas Kachitvichyanukul and Bruce W. Schmeiser. 1988. Binomial
        // random variate generation. Commun. ACM 31, 2 (February 1988),
        // 216-222. http://dx.doi.org/10.1145/42372.42381
        if (self.n as f64) * p < 10. {
            let q = 1. - p;
            let s = p / q;
            let a = ((self.n + 1) as f64) * s;
            let mut r = q.powf(self.n as f64);
            // FIXME: Using integer exponentiation should be faster, but it is not available for
            // `u64` exponents, neither in `std` or `num`.
            let mut u: f64 = rng.gen();
            let mut x = 0;
            while u > r as f64 {
                u -= r;
                x += 1;
                r *= a / (x as f64) - s;
            }
            result = x;
        } else {
            // FIXME: Using the BTPE algorithm is probably faster.

            // prepare some cached values
            let float_n = self.n as f64;
            let ln_fact_n = log_gamma(float_n + 1.0);
            let pc = 1.0 - p;
            let log_p = p.ln();
            let log_pc = pc.ln();
            let expected = self.n as f64 * p;
            let sq = (expected * (2.0 * pc)).sqrt();
            let mut lresult;

            // we use the Cauchy distribution as the comparison distribution
            // f(x) ~ 1/(1+x^2)
            let cauchy = Cauchy::new(0.0, 1.0);
            loop {
                let mut comp_dev: f64;
                loop {
                    // draw from the Cauchy distribution
                    comp_dev = rng.sample(cauchy);
                    // shift the peak of the comparison ditribution
                    lresult = expected + sq * comp_dev;
                    // repeat the drawing until we are in the range of possible values
                    if lresult >= 0.0 && lresult < float_n + 1.0 {
                        break;
                    }
                }

                // the result should be discrete
                lresult = lresult.floor();

                let log_binomial_dist = ln_fact_n - log_gamma(lresult+1.0) -
                    log_gamma(float_n - lresult + 1.0) + lresult*log_p + (float_n - lresult)*log_pc;
                // this is the binomial probability divided by the comparison probability
                // we will generate a uniform random value and if it is larger than this,
                // we interpret it as a value falling out of the distribution and repeat
                let comparison_coeff = (log_binomial_dist.exp() * sq) * (1.2 * (1.0 + comp_dev*comp_dev));

                if comparison_coeff >= rng.gen() {
                    break;
                }
            }
            result = lresult as u64;
        }

        // invert the result for p < 0.5
        if p != self.p {
            self.n - result
        } else {
            result
        }
    }
}

#[cfg(test)]
mod test {
    use Rng;
    use distributions::Distribution;
    use super::Binomial;

    fn test_binomial_mean_and_variance<R: Rng>(n: u64, p: f64, rng: &mut R) {
        let binomial = Binomial::new(n, p);

        let expected_mean = n as f64 * p;
        let expected_variance = n as f64 * p * (1.0 - p);

        let mut results = [0.0; 1000];
        for i in results.iter_mut() { *i = binomial.sample(rng) as f64; }

        let mean = results.iter().sum::<f64>() / results.len() as f64;
        assert!((mean as f64 - expected_mean).abs() < expected_mean / 50.0);

        let variance =
            results.iter().map(|x| (x - mean) * (x - mean)).sum::<f64>()
            / results.len() as f64;
        assert!((variance - expected_variance).abs() < expected_variance / 10.0);
    }

    #[test]
    fn test_binomial() {
        let mut rng = ::test::rng(351);
        test_binomial_mean_and_variance(150, 0.1, &mut rng);
        test_binomial_mean_and_variance(70, 0.6, &mut rng);
        test_binomial_mean_and_variance(40, 0.5, &mut rng);
        test_binomial_mean_and_variance(20, 0.7, &mut rng);
        test_binomial_mean_and_variance(20, 0.5, &mut rng);
    }

    #[test]
    fn test_binomial_end_points() {
        let mut rng = ::test::rng(352);
        assert_eq!(rng.sample(Binomial::new(20, 0.0)), 0);
        assert_eq!(rng.sample(Binomial::new(20, 1.0)), 20);
    }

    #[test]
    #[should_panic]
    fn test_binomial_invalid_lambda_neg() {
        Binomial::new(20, -10.0);
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

extern crate genmesh;
extern crate clock_ticks;
extern crate obj;

use std::thread;
use glium::{self, Display};
use glium::vertex::VertexBufferAny;

pub mod camera;

pub enum Action {
    Stop,
    Continue,
}

pub fn start_loop<F>(mut callback: F) where F: FnMut() -> Action {
    let mut accumulator = 0;
    let mut previous_clock = clock_ticks::precise_time_ns();

    loop {
        match callback() {
            Action::Stop => break,
            Action::Continue => ()
        };

        let now = clock_ticks::precise_time_ns();
        accumulator += now - previous_clock;
        previous_clock = now;

        const FIXED_TIME_STAMP: u64 = 16666667;
        while accumulator >= FIXED_TIME_STAMP {
            accumulator -= FIXED_TIME_STAMP;

            // if you have a game, update the state here
        }

        thread::sleep_ms(((FIXED_TIME_STAMP - accumulator) / 1000000) as u32);
    }
}

/// Returns a vertex buffer that should be rendered as `TrianglesList`.
pub fn load_wavefront(display: &Display, data: &[u8]) -> VertexBufferAny {
    #[derive(Copy, Clone)]
    struct Vertex {
        position: [f32; 3],
        normal: [f32; 3],
        texture: [f32; 2],
    }

    implement_vertex!(Vertex, position, normal, texture);

    let mut data = ::std::io::BufReader::new(data);
    let data = obj::Obj::load(&mut data);

    let mut vertex_data = Vec::new();

    for shape in data.object_iter().next().unwrap().group_iter().flat_map(|g| g.indices().iter()) {
        match shape {
            &genmesh::Polygon::PolyTri(genmesh::Triangle { x: v1, y: v2, z: v3 }) => {
                for v in [v1, v2, v3].iter() {
                    let position = data.position()[v.0];
                    let texture = v.1.map(|index| data.texture()[index]);
                    let normal = v.2.map(|index| data.normal()[index]);

                    let texture = texture.unwrap_or([0.0, 0.0]);
                    let normal = normal.unwrap_or([0.0, 0.0, 0.0]);

                    vertex_data.push(Vertex {
                        position: position,
                        normal: normal,
                        texture: texture,
                    })
                }
            },
            _ => unimplemented!()
        }
    }

    glium::vertex::VertexBuffer::new(display, &vertex_data).unwrap().into_vertex_buffer_any()
}
<commit_msg>Fix for multiple objects in wavefront .obj file.<commit_after>#![allow(dead_code)]

extern crate genmesh;
extern crate clock_ticks;
extern crate obj;

use std::thread;
use glium::{self, Display};
use glium::vertex::VertexBufferAny;

pub mod camera;

pub enum Action {
    Stop,
    Continue,
}

pub fn start_loop<F>(mut callback: F) where F: FnMut() -> Action {
    let mut accumulator = 0;
    let mut previous_clock = clock_ticks::precise_time_ns();

    loop {
        match callback() {
            Action::Stop => break,
            Action::Continue => ()
        };

        let now = clock_ticks::precise_time_ns();
        accumulator += now - previous_clock;
        previous_clock = now;

        const FIXED_TIME_STAMP: u64 = 16666667;
        while accumulator >= FIXED_TIME_STAMP {
            accumulator -= FIXED_TIME_STAMP;

            // if you have a game, update the state here
        }

        thread::sleep_ms(((FIXED_TIME_STAMP - accumulator) / 1000000) as u32);
    }
}

/// Returns a vertex buffer that should be rendered as `TrianglesList`.
pub fn load_wavefront(display: &Display, data: &[u8]) -> VertexBufferAny {
    #[derive(Copy, Clone)]
    struct Vertex {
        position: [f32; 3],
        normal: [f32; 3],
        texture: [f32; 2],
    }

    implement_vertex!(Vertex, position, normal, texture);

    let mut data = ::std::io::BufReader::new(data);
    let data = obj::Obj::load(&mut data);

    let mut vertex_data = Vec::new();

    for object in data.object_iter() {
        for shape in object.group_iter().flat_map(|g| g.indices().iter()) {
            match shape {
                &genmesh::Polygon::PolyTri(genmesh::Triangle { x: v1, y: v2, z: v3 }) => {
                    for v in [v1, v2, v3].iter() {
                        let position = data.position()[v.0];
                        let texture = v.1.map(|index| data.texture()[index]);
                        let normal = v.2.map(|index| data.normal()[index]);

                        let texture = texture.unwrap_or([0.0, 0.0]);
                        let normal = normal.unwrap_or([0.0, 0.0, 0.0]);

                        vertex_data.push(Vertex {
                            position: position,
                            normal: normal,
                            texture: texture,
                        })
                    }
                },
                _ => unimplemented!()
            }
        }
    }

    glium::vertex::VertexBuffer::new(display, &vertex_data).unwrap().into_vertex_buffer_any()
}
<|endoftext|>


<commit_before>use std::fs::read_to_string;

fn main() {
    let git_hash = option_env!("TRAVIS_COMMIT")
        .map(|s| s.into())
        .unwrap_or_else(|| read_to_string(".git/refs/heads/next").unwrap_or_default());

    println!("cargo:rustc-env=GIT_HASH={}", git_hash);
}
<commit_msg>Get proper git SHA when TRAVIS_COMMIT is not available.<commit_after>fn main() {
    let git_hash = option_env!("TRAVIS_COMMIT")
        .map(ToOwned::to_owned)
        .unwrap_or_else(|| {
            let stdout = std::process::Command::new("git")
                .arg("rev-parse")
                .arg("HEAD")
                .output()
                .expect("Failed to get git commit SHA")
                .stdout;
            String::from_utf8(stdout).expect("Failed to construct string")
        });

    println!("cargo:rustc-env=GIT_HASH={}", git_hash);
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#![feature(io, env, path, fs)]

extern crate "pkg-config" as pkg_config;

use std::path::Path;
use std::fs::PathExt;
use std::env;

#[cfg(all(unix, not(target_os = "linux")))]
use unix_platform as platform;

fn main() {
    // If pkg-config finds a library on the system, we are done
    if pkg_config::Config::new().atleast_version("19").find("portaudio-2.0").is_ok() {
        return;
    }

    build();
}

fn build() {
    // retrieve cargo deps out dir
    let out_dir_str = env::var("OUT_DIR").unwrap();
    let out_dir = Path::new(&out_dir_str);

    let static_lib = out_dir.join("lib/libportaudio.a");
    if !static_lib.exists() {
        platform::build(out_dir);
    }

    platform::print_libs(out_dir);
}

#[allow(dead_code)]
mod unix_platform {
    use std::old_io::process::Command;
    use std::path::Path;
    use std::old_path::Path as OldPath;

    use std::{env, os};

    pub const PORTAUDIO_URL: &'static str = "http://www.portaudio.com/archives/pa_stable_v19_20140130.tgz";
    pub const PORTAUDIO_TAR: &'static str = "pa_stable_v19_20140130.tgz";
    pub const PORTAUDIO_FOLDER: &'static str = "portaudio";

    pub fn build(out_dir: &Path) {
        // get portaudio library sources
        match Command::new("wget").arg(PORTAUDIO_URL).output() {
            Ok(_) => {},
            Err(e) => panic!("{}", e)
        }

        // untar portaudio sources
        match Command::new("tar").arg("xvf").arg(PORTAUDIO_TAR).output() {
            Ok(_) => {},
            Err(e) => panic!("{}", e)
        }

        // change dir to the portaudio folder
        match env::set_current_dir(&OldPath::new(PORTAUDIO_FOLDER)) {
            Ok(_) => {},
            Err(e) => panic!("{}", e)
        }

        // run portaudio autoconf
        Command::new("./configure")
            .args(&["--disable-shared", "--enable-static"]) // Only build static lib
            .args(&["--prefix", out_dir.to_str().unwrap()]) // Install on the outdir
            .arg("--with-pic") // Build position-independent code (required by Rust)
            .output()
            .unwrap();

        // then make
        match Command::new("make").arg(format!("-j{}", os::num_cpus())).output() {
            Ok(_) => {},
            Err(e) => panic!("{}", e)
        }

        // "install" on the outdir
        match Command::new("make").arg("install").output() {
            Ok(_) => {},
            Err(e) => panic!("{}", e)
        }

        // return to rust-portaudio root
        match env::set_current_dir(&OldPath::new("..")) {
            Ok(_) => {},
            Err(e) => panic!("{}", e)
        }

        // cleaning portaudio sources
        match Command::new("rm").arg("-rf").args(&[PORTAUDIO_TAR, PORTAUDIO_FOLDER]).output() {
            Ok(_) => {},
            Err(e) => panic!("{}", e)
        }
    }

    pub fn print_libs(out_dir: &Path) {
        let out_str = out_dir.to_str().unwrap();
        println!("cargo:rustc-flags=-L native={}/lib -l static=portaudio", out_str);
    }
}

#[cfg(target_os = "linux")]
mod platform {
    use pkg_config;
    use super::unix_platform;
    use std::path::Path;

    pub fn build(out_dir: &Path) {
        unix_platform::build(out_dir);
    }

    pub fn print_libs(out_dir: &Path) {
        let portaudio_pc_file = out_dir.join("lib/pkgconfig/portaudio-2.0.pc");
        let portaudio_pc_file = portaudio_pc_file.to_str().unwrap();

        pkg_config::Config::new().statik(true).find(portaudio_pc_file).unwrap();
    }
}

#[cfg(windows)]
mod platform {
    use std::path::Path;

    pub fn build(_: &Path) {
        panic!("Don't know how to build portaudio on Windows yet!");
    }

    pub fn print_libs(_: &Path) {
        panic!("Don't know how to build portaudio on Windows yet!");
    }
}
<commit_msg>Support forcing building portaudio even if a system library is present<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#![feature(io, env, path, fs)]

extern crate "pkg-config" as pkg_config;

use std::path::Path;
use std::fs::PathExt;
use std::env;

#[cfg(all(unix, not(target_os = "linux")))]
use unix_platform as platform;

fn main() {
    if env::var("PORTAUDIO_ONLY_STATIC").is_none() {
        // If pkg-config finds a library on the system, we are done
        if pkg_config::Config::new().atleast_version("19").find("portaudio-2.0").is_ok() {
            return;
        }
    }

    build();
}

fn build() {
    // retrieve cargo deps out dir
    let out_dir_str = env::var("OUT_DIR").unwrap();
    let out_dir = Path::new(&out_dir_str);

    let static_lib = out_dir.join("lib/libportaudio.a");
    if !static_lib.exists() {
        platform::build(out_dir);
    }

    platform::print_libs(out_dir);
}

#[allow(dead_code)]
mod unix_platform {
    use std::old_io::process::Command;
    use std::path::Path;
    use std::old_path::Path as OldPath;

    use std::{env, os};

    pub const PORTAUDIO_URL: &'static str = "http://www.portaudio.com/archives/pa_stable_v19_20140130.tgz";
    pub const PORTAUDIO_TAR: &'static str = "pa_stable_v19_20140130.tgz";
    pub const PORTAUDIO_FOLDER: &'static str = "portaudio";

    pub fn build(out_dir: &Path) {
        // get portaudio library sources
        match Command::new("wget").arg(PORTAUDIO_URL).output() {
            Ok(_) => {},
            Err(e) => panic!("{}", e)
        }

        // untar portaudio sources
        match Command::new("tar").arg("xvf").arg(PORTAUDIO_TAR).output() {
            Ok(_) => {},
            Err(e) => panic!("{}", e)
        }

        // change dir to the portaudio folder
        match env::set_current_dir(&OldPath::new(PORTAUDIO_FOLDER)) {
            Ok(_) => {},
            Err(e) => panic!("{}", e)
        }

        // run portaudio autoconf
        Command::new("./configure")
            .args(&["--disable-shared", "--enable-static"]) // Only build static lib
            .args(&["--prefix", out_dir.to_str().unwrap()]) // Install on the outdir
            .arg("--with-pic") // Build position-independent code (required by Rust)
            .output()
            .unwrap();

        // then make
        match Command::new("make").arg(format!("-j{}", os::num_cpus())).output() {
            Ok(_) => {},
            Err(e) => panic!("{}", e)
        }

        // "install" on the outdir
        match Command::new("make").arg("install").output() {
            Ok(_) => {},
            Err(e) => panic!("{}", e)
        }

        // return to rust-portaudio root
        match env::set_current_dir(&OldPath::new("..")) {
            Ok(_) => {},
            Err(e) => panic!("{}", e)
        }

        // cleaning portaudio sources
        match Command::new("rm").arg("-rf").args(&[PORTAUDIO_TAR, PORTAUDIO_FOLDER]).output() {
            Ok(_) => {},
            Err(e) => panic!("{}", e)
        }
    }

    pub fn print_libs(out_dir: &Path) {
        let out_str = out_dir.to_str().unwrap();
        println!("cargo:rustc-flags=-L native={}/lib -l static=portaudio", out_str);
    }
}

#[cfg(target_os = "linux")]
mod platform {
    use pkg_config;
    use super::unix_platform;
    use std::path::Path;

    pub fn build(out_dir: &Path) {
        unix_platform::build(out_dir);
    }

    pub fn print_libs(out_dir: &Path) {
        let portaudio_pc_file = out_dir.join("lib/pkgconfig/portaudio-2.0.pc");
        let portaudio_pc_file = portaudio_pc_file.to_str().unwrap();

        pkg_config::Config::new().statik(true).find(portaudio_pc_file).unwrap();
    }
}

#[cfg(windows)]
mod platform {
    use std::path::Path;

    pub fn build(_: &Path) {
        panic!("Don't know how to build portaudio on Windows yet!");
    }

    pub fn print_libs(_: &Path) {
        panic!("Don't know how to build portaudio on Windows yet!");
    }
}
<|endoftext|>


<commit_before>use std::env;

fn main() {
    let mut matched = false;

    for (key, val) in env::vars() {
        match (&key[..], &val[..], matched) {
            ("MATLAB_LIB_PATH", _, true) |
                ("OCTAVE_LIB_PATH", _, true) => {
                    panic!("Please specify only MATLAB_LIB_PATH or OCTAVE_LIB_PATH");
            },
            ("MATLAB_LIB_PATH", path, false) => {
                println!("cargo:rustc-link-search={}", path);
                println!("cargo:rustc-cfg=matlab");
                matched = true;
            },
            ("OCTAVE_LIB_PATH", path, false) => {
                println!("cargo:rustc-link-search={}", path);
                println!("cargo:rustc-cfg=octave");
                matched = true;
            },
            _ => { }
        };
    }

    if !matched {
        panic!("Please set either MATLAB_LIB_PATH or OCTAVE_LIB_PATH");
    }
}

<commit_msg>added automatic octave configuration<commit_after>use std::env;
use std::path::{Path, PathBuf};
use std::fs::metadata;
use std::process::Command;
use std::io::Read;

fn get_path() -> Option<String> {
    for (key, val) in env::vars() {
        if key == "PATH" {
            return Some(val)
        }
    }
    None
}

fn main() {
    let mut matched = false;

    for (key, val) in env::vars() {
        match (&key[..], &val[..], matched) {
            ("MATLAB_LIB_PATH", _, true) |
                ("OCTAVE_LIB_PATH", _, true) => {
                    panic!("Please specify only MATLAB_LIB_PATH or OCTAVE_LIB_PATH");
            },
            ("MATLAB_LIB_PATH", path, false) => {
                println!("cargo:rustc-link-search={}", path);
                println!("cargo:rustc-cfg=matlab");
                matched = true;
            },
            ("OCTAVE_LIB_PATH", path, false) => {
                println!("cargo:rustc-link-search={}", path);
                println!("cargo:rustc-cfg=octave");
                matched = true;
            },
            _ => { }
        };
    }

    if let (Some(path), false) = (get_path(), matched) {
        for path_item in path.split(":") {
            // look for octave-config
            let mut oct_path = PathBuf::from(path_item);
            oct_path.push("octave-config");
            if let Ok(_) = metadata(&oct_path) {
                if let Ok(output) = Command::new(&oct_path).arg("--print").arg("OCTLIBDIR").output() {
                    if let Ok(txt) = String::from_utf8(output.stdout) {
                        println!("cargo:rustc-link-search={}", txt);
                        println!("cargo:rustc-cfg=octave");
                        matched = true;
                    }
                }
            }

            // look for matlab-config
            // TODO
        }
    }

    if !matched {
        panic!("Please set either MATLAB_LIB_PATH or OCTAVE_LIB_PATH");
    }
}

<|endoftext|>


<commit_before>use std::ops::Deref;

use super::super::crypto::{Hash, hash};
use messages::Message;
use ::storage::{Database, Error};
use storage::Map;
use ::blockchain::Blockchain;
use config::txs::{ConfigTx, TxConfigPropose, TxConfigVote };
use config::view::ConfigsView;
use config::height_to_slice;

use super::view::StoredConfiguration;

#[derive(Clone)]
pub struct ConfigsBlockchain<D: Database> {
    pub db: D,
    pub loaded_config: Option<StoredConfiguration>
}

impl<D: Database> Deref for ConfigsBlockchain<D> {
    type Target = D;
    fn deref(&self) -> &D {
        &self.db
    }
}

impl<D> ConfigsBlockchain<D> where D: Database {

    fn handle_config_propose(&self, config_propose: &TxConfigPropose) {

        let view = self.view();
        if let Some(ref config) = self.loaded_config {
            if !config.validators.contains(config_propose.from()){
                error!("ConfigPropose from unknown validator: {:?}", config_propose.from());
                return;
            }
        }

        if view.config_proposes().get(&config_propose.hash()).unwrap().is_some() {
            error!("Received config_propose has already been handled, msg={:?}", config_propose);
            return;
        }

        trace!("Handle ConfigPropose");
        let _ = view.config_proposes().put(&config_propose.hash(), config_propose.clone());

    }

    fn handle_config_vote(&self, config_vote: &TxConfigVote){

        let view = self.view();
        if let Some(ref config) = self.loaded_config {

            let validators = config.validators.clone();
            if !validators.contains(config_vote.from()){
                error!("ConfigVote from unknown validator: {:?}", config_vote.from());
                return;
            }

            if view.config_proposes().get(config_vote.hash_propose()).unwrap().is_some() {
                error!("Received config_vote for unknown transaciton, msg={:?}", config_vote);
                return;
            }

            if let Some(vote) = view.config_votes().get(config_vote.from()).unwrap() {
                if vote.seed() != config_vote.seed() -1 {
                    error!("Received config_vote with wrong seed, msg={:?}", config_vote);
                    return;
                }
            }

            let msg = config_vote.clone();
            let _ = view.config_votes().put(msg.from(), config_vote.clone());

            let validators = config.validators.clone();
            let mut votes_count = 0;
            for pub_key in validators {
                if let Some(vote) = view.config_votes().get(&pub_key).unwrap() {
                    if !vote.revoke() {
                        votes_count += 1;
                    }
                }
            }

            let validators = config.validators.clone();
            if votes_count >= 2/3 * validators.len(){
                if let Some(config_propose) = view.config_proposes().get(config_vote.hash_propose()).unwrap() {
                    view.configs().put(&height_to_slice(config_propose.actual_from_height()), config_propose.config().to_vec()).unwrap();
                    // TODO: clear storages
                }
            }
        }
    }
}

impl<D> Blockchain for ConfigsBlockchain<D> where D: Database
{
    type Database = D;
    type Transaction = ConfigTx;
    type View = ConfigsView<D::Fork>;

    fn verify_tx(tx: &Self::Transaction) -> bool {
        tx.verify(tx.pub_key())
    }

    fn state_hash(view: &Self::View) -> Result<Hash, Error> {
        let mut hashes = Vec::new();
        hashes.extend_from_slice(view.configs().root_hash()?.as_ref());
        Ok(hash(&hashes))
    }

    fn execute(&self, tx: &Self::Transaction) -> Result<(), Error> {
        match *tx {
            ConfigTx::ConfigPropose(ref tx) => {
                self.handle_config_propose(tx);
                return Ok(());
            }
            ConfigTx::ConfigVote(ref tx) => {
                self.handle_config_vote(tx);
                return Ok(());
            }
        }
    }

    fn get_initial_configuration (&mut self) -> Option<StoredConfiguration> {
        let r = self.last_block().unwrap();
        let last_height = if let Some(last_block) = r {
            last_block.height() + 1
        } else {
            0
        };
        let mut h = last_height;

        while h > 0 {
            if let Some(configuration) = self.get_configuration_at_height(h){
                self.loaded_config = Some(configuration);
                return self.loaded_config.clone();
            }
            h -= 1;
        }
        None
    }

    fn get_configuration_at_height (&mut self, height: u64) -> Option<StoredConfiguration> {
        let view = self.view();
        let configs = view.configs();
        if let Ok(config) = configs.get(&height_to_slice(height)) {
            match StoredConfiguration::deserialize(&config.unwrap()) {
                Ok(configuration) => {
                    self.loaded_config = Some(configuration);
                    return self.loaded_config.clone();
                },
                Err(_) => {
                    error!("Can't parse found configuration at height: {}", height);
                }
            }
        }
        None
    }
}<commit_msg>Build fix<commit_after>use std::ops::Deref;

use super::super::crypto::{Hash, hash};
use messages::Message;
use ::storage::{Database, Error};
use storage::Map;
use ::blockchain::Blockchain;
use config::txs::{ConfigTx, TxConfigPropose, TxConfigVote };
use config::view::ConfigsView;
use config::height_to_slice;

use super::view::StoredConfiguration;

#[derive(Clone)]
pub struct ConfigsBlockchain<D: Database> {
    pub db: D,
    pub loaded_config: Option<StoredConfiguration>
}

impl<D: Database> Deref for ConfigsBlockchain<D> {
    type Target = D;
    fn deref(&self) -> &D {
        &self.db
    }
}

impl<D> ConfigsBlockchain<D> where D: Database {

    fn handle_config_propose(&self, config_propose: &TxConfigPropose) {

        let view = self.view();
        if let Some(ref config) = self.loaded_config {
            if !config.validators.contains(config_propose.from()){
                error!("ConfigPropose from unknown validator: {:?}", config_propose.from());
                return;
            }
        }

        if view.config_proposes().get(&config_propose.hash()).unwrap().is_some() {
            error!("Received config_propose has already been handled, msg={:?}", config_propose);
            return;
        }

        trace!("Handle ConfigPropose");
        let _ = view.config_proposes().put(&config_propose.hash(), config_propose.clone());

    }

    fn handle_config_vote(&self, config_vote: &TxConfigVote){

        let view = self.view();
        if let Some(ref config) = self.loaded_config {

            let validators = config.validators.clone();
            if !validators.contains(config_vote.from()){
                error!("ConfigVote from unknown validator: {:?}", config_vote.from());
                return;
            }

            if view.config_proposes().get(config_vote.hash_propose()).unwrap().is_some() {
                error!("Received config_vote for unknown transaciton, msg={:?}", config_vote);
                return;
            }

            if let Some(vote) = view.config_votes().get(config_vote.from()).unwrap() {
                if vote.seed() != config_vote.seed() -1 {
                    error!("Received config_vote with wrong seed, msg={:?}", config_vote);
                    return;
                }
            }

            let msg = config_vote.clone();
            let _ = view.config_votes().put(msg.from(), config_vote.clone());

            let validators = config.validators.clone();
            let mut votes_count = 0;
            for pub_key in validators {
                if let Some(vote) = view.config_votes().get(&pub_key).unwrap() {
                    if !vote.revoke() {
                        votes_count += 1;
                    }
                }
            }

            let validators = config.validators.clone();
            if votes_count >= 2/3 * validators.len(){
                if let Some(config_propose) = view.config_proposes().get(config_vote.hash_propose()).unwrap() {
                    view.configs().put(&height_to_slice(config_propose.actual_from_height()), config_propose.config().to_vec()).unwrap();
                    // TODO: clear storages
                }
            }
        }
    }
}

impl<D> Blockchain for ConfigsBlockchain<D> where D: Database
{
    type Database = D;
    type Transaction = ConfigTx;
    type View = ConfigsView<D::Fork>;

    fn verify_tx(tx: &Self::Transaction) -> bool {
        tx.verify(tx.pub_key())
    }

    fn state_hash(view: &Self::View) -> Result<Hash, Error> {
        let mut hashes = Vec::new();
        hashes.extend_from_slice(view.configs().root_hash()?.as_ref());
        Ok(hash(&hashes))
    }

    fn execute(&self, tx: &Self::Transaction) -> Result<(), Error> {
        match *tx {
            ConfigTx::ConfigPropose(ref tx) => {
                self.handle_config_propose(tx);
            }
            ConfigTx::ConfigVote(ref tx) => {
                self.handle_config_vote(tx);

            }
        }
        Ok(())
    }

    fn get_initial_configuration (&mut self) -> Option<StoredConfiguration> {
        let r = self.last_block().unwrap();
        let last_height = if let Some(last_block) = r {
            last_block.height() + 1
        } else {
            0
        };
        let mut h = last_height;

        while h > 0 {
            if let Some(configuration) = self.get_configuration_at_height(h){
                self.loaded_config = Some(configuration);
                return self.loaded_config.clone();
            }
            h -= 1;
        }
        None
    }

    fn get_configuration_at_height (&mut self, height: u64) -> Option<StoredConfiguration> {
        let view = self.view();
        let configs = view.configs();
        if let Ok(config) = configs.get(&height_to_slice(height)) {
            match StoredConfiguration::deserialize(&config.unwrap()) {
                Ok(configuration) => {
                    self.loaded_config = Some(configuration);
                    return self.loaded_config.clone();
                },
                Err(_) => {
                    error!("Can't parse found configuration at height: {}", height);
                }
            }
        }
        None
    }
}<|endoftext|>


<commit_before>use dbus::arg::{Array};
use dbus::tree::MethodErr;
use dbus::MessageItem;

use ::rustwlc::WlcOutput;
use ::layout::Handle;
use ::ipc::utils::{parse_uuid, lock_tree_dbus};
use ::ipc::{DBusFactory, DBusObjPath};
use ::render::screen_scrape::{write_screen_scrape_lock, read_screen_scrape_lock,
                              scraped_pixels_lock, sync_scrape};

pub fn setup(f: &mut DBusFactory) -> DBusObjPath {
    f.object_path("/org/way_cooler/Screen", ()).introspectable().add(
        f.interface("org.way_cooler.Screen", ())
            .add_m(
                f.method("List", (), |m| {
                    let tree = lock_tree_dbus()?;
                    let outputs = tree.outputs().iter()
                        .map(|id|
                             MessageItem::Str(format!("{}", id.simple())))
                        .collect();
                    Ok(vec![m.msg.method_return()
                            .append((MessageItem::Array(outputs, "s".into())))
                    ])
                }).outarg::<Array<String, Vec<String>>, _>("success")
            )
            .add_m(
                f.method("ActiveScreen", (), |m| {
                    let tree = lock_tree_dbus()?;
                    let id = tree.lookup_handle(Handle::Output(WlcOutput::focused()))
                        .map_err(|err| MethodErr::failed(&format!("{:?}", err)))?.to_string();
                    Ok(vec![m.msg.method_return().append((MessageItem::Str(id)))])
                }).outarg::<String, _>("success")
            )
            .add_m(
                f.method("Scrape", (), |m| {
                    *write_screen_scrape_lock() = true;
                    // ensure that no other threads can try to grab the pixels.
                    let _lock = read_screen_scrape_lock();
                    let mut args_iter = m.msg.iter_init();
                    let output = args_iter.read::<u32>()?;
                    let output = unsafe { WlcOutput::dummy(output)};
                    {
                        let mut scraped_pixels = scraped_pixels_lock().unwrap();
                        scraped_pixels.1 = Some(output);
                    }
                    output.schedule_render();
                    sync_scrape();
                    drop(_lock);
                    *write_screen_scrape_lock() = false;
                    let mut scraped_pixels = scraped_pixels_lock()
                        .expect("scraped_pixels lock was poisoned!");
                    let result = scraped_pixels.0.iter()
                        .map(|pixel| MessageItem::Byte(*pixel)).collect();
                    scraped_pixels.1 = None;
                    Ok(vec![m.msg.method_return()
                            .append((MessageItem::Array(result, "y".into())))])
                })
                    .outarg::<Array<u8, Vec<u8>>, _>("success")
                    .inarg::<u32, _>("output_number")
            )
            .add_m(
                f.method("Resolution", (), |m| {
                    let mut args_iter = m.msg.iter_init();
                    let output_id = args_iter.read::<String>()?;
                    let tree = lock_tree_dbus()?;
                    let uuid = parse_uuid("container_id", &output_id)?
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container"))?;
                    let size = tree.output_resolution(uuid)
                        .map_err(|err| {
                            MethodErr::failed(&format!("{:?}", err))
                        })?;
                    Ok(vec![m.msg.method_return()
                            .append1((size.w, size.h))
                    ])
                })
                    .outarg::<(u32, u32), _>("success")
                    .inarg::<String, _>("output_id")
            )
    )
}
<commit_msg>If output is 0 for Scrape, use the focused output<commit_after>use dbus::arg::{Array};
use dbus::tree::MethodErr;
use dbus::MessageItem;

use ::rustwlc::WlcOutput;
use ::layout::Handle;
use ::ipc::utils::{parse_uuid, lock_tree_dbus};
use ::ipc::{DBusFactory, DBusObjPath};
use ::render::screen_scrape::{write_screen_scrape_lock, read_screen_scrape_lock,
                              scraped_pixels_lock, sync_scrape};

pub fn setup(f: &mut DBusFactory) -> DBusObjPath {
    f.object_path("/org/way_cooler/Screen", ()).introspectable().add(
        f.interface("org.way_cooler.Screen", ())
            .add_m(
                f.method("List", (), |m| {
                    let tree = lock_tree_dbus()?;
                    let outputs = tree.outputs().iter()
                        .map(|id|
                             MessageItem::Str(format!("{}", id.simple())))
                        .collect();
                    Ok(vec![m.msg.method_return()
                            .append((MessageItem::Array(outputs, "s".into())))
                    ])
                }).outarg::<Array<String, Vec<String>>, _>("success")
            )
            .add_m(
                f.method("ActiveScreen", (), |m| {
                    let tree = lock_tree_dbus()?;
                    let id = tree.lookup_handle(Handle::Output(WlcOutput::focused()))
                        .map_err(|err| MethodErr::failed(&format!("{:?}", err)))?.to_string();
                    Ok(vec![m.msg.method_return().append((MessageItem::Str(id)))])
                }).outarg::<String, _>("success")
            )
            .add_m(
                f.method("Scrape", (), |m| {
                    *write_screen_scrape_lock() = true;
                    // ensure that no other threads can try to grab the pixels.
                    let _lock = read_screen_scrape_lock();
                    let mut args_iter = m.msg.iter_init();
                    let output_num = args_iter.read::<u32>()?;
                    let output = if output_num == 0 {
                        WlcOutput::focused()
                    } else {
                        unsafe { WlcOutput::dummy(output_num) }
                    };
                    {
                        let mut scraped_pixels = scraped_pixels_lock().unwrap();
                        scraped_pixels.1 = Some(output);
                    }
                    output.schedule_render();
                    sync_scrape();
                    drop(_lock);
                    *write_screen_scrape_lock() = false;
                    let mut scraped_pixels = scraped_pixels_lock()
                        .expect("scraped_pixels lock was poisoned!");
                    let result = scraped_pixels.0.iter()
                        .map(|pixel| MessageItem::Byte(*pixel)).collect();
                    scraped_pixels.1 = None;
                    Ok(vec![m.msg.method_return()
                            .append((MessageItem::Array(result, "y".into())))])
                })
                    .outarg::<Array<u8, Vec<u8>>, _>("success")
                    .inarg::<u32, _>("output_number")
            )
            .add_m(
                f.method("Resolution", (), |m| {
                    let mut args_iter = m.msg.iter_init();
                    let output_id = args_iter.read::<String>()?;
                    let tree = lock_tree_dbus()?;
                    let uuid = parse_uuid("container_id", &output_id)?
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container"))?;
                    let size = tree.output_resolution(uuid)
                        .map_err(|err| {
                            MethodErr::failed(&format!("{:?}", err))
                        })?;
                    Ok(vec![m.msg.method_return()
                            .append1((size.w, size.h))
                    ])
                })
                    .outarg::<(u32, u32), _>("success")
                    .inarg::<String, _>("output_id")
            )
    )
}
<|endoftext|>


<commit_before>use crate::ty::query::Providers;
use crate::hir::def_id::DefId;
use crate::hir;
use crate::ty::TyCtxt;
use syntax_pos::symbol::{sym, Symbol};
use rustc_target::spec::abi::Abi;
use crate::hir::map::blocks::FnLikeNode;
use syntax::attr;

impl<'tcx> TyCtxt<'tcx> {
    /// Whether the `def_id` counts as const fn in your current crate, considering all active
    /// feature gates
    pub fn is_const_fn(self, def_id: DefId) -> bool {
        self.is_const_fn_raw(def_id) && match self.is_unstable_const_fn(def_id) {
            Some(feature_name) => {
                // has a `rustc_const_unstable` attribute, check whether the user enabled the
                // corresponding feature gate.
                self.features()
                    .declared_lib_features
                    .iter()
                    .any(|&(sym, _)| sym == feature_name)
            },
            // functions without const stability are either stable user written
            // const fn or the user is using feature gates and we thus don't
            // care what they do
            None => true,
        }
    }

    /// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it
    pub fn is_unstable_const_fn(self, def_id: DefId) -> Option<Symbol> {
        if self.is_const_fn_raw(def_id) {
            let const_stab = self.lookup_const_stability(def_id)?;
            if const_stab.level.is_unstable() {
                Some(const_stab.feature)
            } else {
                None
            }
        } else {
            None
        }
    }

    /// Returns `true` if the `def_id` refers to an intrisic which we've whitelisted
    /// for being called from stable `const fn`s (`min_const_fn`).
    ///
    /// Adding more intrinsics requires sign-off from @rust-lang/lang.
    ///
    /// This list differs from the list in `is_const_intrinsic` in the sense that any item on this
    /// list must be on the `is_const_intrinsic` list, too, because if an intrinsic is callable from
    /// stable, it must be callable at all.
    fn is_intrinsic_min_const_fn(self, def_id: DefId) -> bool {
        match self.item_name(def_id) {
            | sym::size_of
            | sym::min_align_of
            | sym::needs_drop
            // Arithmetic:
            | sym::add_with_overflow // ~> .overflowing_add
            | sym::sub_with_overflow // ~> .overflowing_sub
            | sym::mul_with_overflow // ~> .overflowing_mul
            | sym::wrapping_add // ~> .wrapping_add
            | sym::wrapping_sub // ~> .wrapping_sub
            | sym::wrapping_mul // ~> .wrapping_mul
            | sym::saturating_add // ~> .saturating_add
            | sym::saturating_sub // ~> .saturating_sub
            | sym::unchecked_shl // ~> .wrapping_shl
            | sym::unchecked_shr // ~> .wrapping_shr
            | sym::rotate_left // ~> .rotate_left
            | sym::rotate_right // ~> .rotate_right
            | sym::ctpop // ~> .count_ones
            | sym::ctlz // ~> .leading_zeros
            | sym::cttz // ~> .trailing_zeros
            | sym::bswap // ~> .swap_bytes
            | sym::bitreverse // ~> .reverse_bits
            => true,
            _ => false,
        }
    }

    /// Returns `true` if this function must conform to `min_const_fn`
    pub fn is_min_const_fn(self, def_id: DefId) -> bool {
        // Bail out if the signature doesn't contain `const`
        if !self.is_const_fn_raw(def_id) {
            return false;
        }
        if let Abi::RustIntrinsic = self.fn_sig(def_id).abi() {
            return self.is_intrinsic_min_const_fn(def_id);
        }

        if self.features().staged_api {
            // In order for a libstd function to be considered min_const_fn
            // it needs to be stable and have no `rustc_const_unstable` attribute.
            match self.lookup_const_stability(def_id) {
                // `rustc_const_unstable` functions don't need to conform.
                Some(&attr::ConstStability { ref level, .. }) if level.is_unstable() => false,
                None => if let Some(stab) = self.lookup_stability(def_id) {
                    if stab.level.is_stable() {
                        self.sess.span_err(
                            self.def_span(def_id),
                            "stable const functions must have either `rustc_const_stable` or \
                            `rustc_const_unstable` attribute",
                        );
                        // While we errored above, because we don't know if we need to conform, we
                        // err on the "safe" side and require min_const_fn.
                        true
                    } else {
                        // Unstable functions need not conform to min const fn.
                        false
                    }
                } else {
                    // Internal functions are forced to conform to min const fn.
                    // Annotate the internal function with a const stability attribute if
                    // you need to use unstable features.
                    // Note: this is an arbitrary choice that does not affect stability or const
                    // safety or anything, it just changes whether we need to annotate some
                    // internal functions with `rustc_const_stable` or with `rustc_const_unstable`
                    true
                },
                // Everything else needs to conform, because it would be callable from
                // other `min_const_fn` functions.
                _ => true,
            }
        } else {
            // users enabling the `const_fn` feature gate can do what they want
            !self.features().const_fn
        }
    }
}

pub fn provide(providers: &mut Providers<'_>) {
    /// Const evaluability whitelist is here to check evaluability at the
    /// top level beforehand.
    fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option<bool> {
        match tcx.fn_sig(def_id).abi() {
            Abi::RustIntrinsic |
            Abi::PlatformIntrinsic => {
                // FIXME: deduplicate these two lists as much as possible
                match tcx.item_name(def_id) {
                    // Keep this list in the same order as the match patterns in
                    // `librustc_mir/interpret/intrinsics.rs`

                    // This whitelist is a list of intrinsics that have a miri-engine implementation
                    // and can thus be called when enabling enough feature gates. The similar
                    // whitelist in `is_intrinsic_min_const_fn` (in this file), exists for allowing
                    // the intrinsics to be called by stable const fns.
                    | sym::caller_location

                    | sym::min_align_of
                    | sym::pref_align_of
                    | sym::needs_drop
                    | sym::size_of
                    | sym::type_id
                    | sym::type_name

                    | sym::ctpop
                    | sym::cttz
                    | sym::cttz_nonzero
                    | sym::ctlz
                    | sym::ctlz_nonzero
                    | sym::bswap
                    | sym::bitreverse

                    | sym::wrapping_add
                    | sym::wrapping_sub
                    | sym::wrapping_mul
                    | sym::add_with_overflow
                    | sym::sub_with_overflow
                    | sym::mul_with_overflow

                    | sym::saturating_add
                    | sym::saturating_sub

                    | sym::unchecked_shl
                    | sym::unchecked_shr

                    | sym::rotate_left
                    | sym::rotate_right

                    | sym::ptr_offset_from

                    | sym::transmute

                    | sym::simd_insert

                    | sym::simd_extract

                    => Some(true),

                    _ => Some(false)
                }
            }
            _ => None
        }
    }

    /// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether
    /// said intrinsic is on the whitelist for being const callable.
    fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
        let hir_id = tcx.hir().as_local_hir_id(def_id)
                              .expect("Non-local call to local provider is_const_fn");

        let node = tcx.hir().get(hir_id);

        if let Some(whitelisted) = is_const_intrinsic(tcx, def_id) {
            whitelisted
        } else if let Some(fn_like) = FnLikeNode::from_node(node) {
            fn_like.constness() == hir::Constness::Const
        } else if let hir::Node::Ctor(_) = node {
            true
        } else {
            false
        }
    }

    fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
        tcx.is_const_fn(def_id) && match tcx.lookup_const_stability(def_id) {
            Some(stab) => {
                if cfg!(debug_assertions) && stab.promotable {
                    let sig = tcx.fn_sig(def_id);
                    assert_eq!(
                        sig.unsafety(),
                        hir::Unsafety::Normal,
                        "don't mark const unsafe fns as promotable",
                        // https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682
                    );
                }
                stab.promotable
            },
            None => false,
        }
    }

    fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
        tcx.is_const_fn(def_id) &&
            tcx.lookup_const_stability(def_id)
                .map(|stab| stab.allow_const_fn_ptr).unwrap_or(false)
    }

    *providers = Providers {
        is_const_fn_raw,
        is_promotable_const_fn,
        const_fn_is_allowed_fn_ptr,
        ..*providers
    };
}
<commit_msg>Consistently name `min_const_fn`<commit_after>use crate::ty::query::Providers;
use crate::hir::def_id::DefId;
use crate::hir;
use crate::ty::TyCtxt;
use syntax_pos::symbol::{sym, Symbol};
use rustc_target::spec::abi::Abi;
use crate::hir::map::blocks::FnLikeNode;
use syntax::attr;

impl<'tcx> TyCtxt<'tcx> {
    /// Whether the `def_id` counts as const fn in your current crate, considering all active
    /// feature gates
    pub fn is_const_fn(self, def_id: DefId) -> bool {
        self.is_const_fn_raw(def_id) && match self.is_unstable_const_fn(def_id) {
            Some(feature_name) => {
                // has a `rustc_const_unstable` attribute, check whether the user enabled the
                // corresponding feature gate.
                self.features()
                    .declared_lib_features
                    .iter()
                    .any(|&(sym, _)| sym == feature_name)
            },
            // functions without const stability are either stable user written
            // const fn or the user is using feature gates and we thus don't
            // care what they do
            None => true,
        }
    }

    /// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it
    pub fn is_unstable_const_fn(self, def_id: DefId) -> Option<Symbol> {
        if self.is_const_fn_raw(def_id) {
            let const_stab = self.lookup_const_stability(def_id)?;
            if const_stab.level.is_unstable() {
                Some(const_stab.feature)
            } else {
                None
            }
        } else {
            None
        }
    }

    /// Returns `true` if the `def_id` refers to an intrisic which we've whitelisted
    /// for being called from stable `const fn`s (`min_const_fn`).
    ///
    /// Adding more intrinsics requires sign-off from @rust-lang/lang.
    ///
    /// This list differs from the list in `is_const_intrinsic` in the sense that any item on this
    /// list must be on the `is_const_intrinsic` list, too, because if an intrinsic is callable from
    /// stable, it must be callable at all.
    fn is_intrinsic_min_const_fn(self, def_id: DefId) -> bool {
        match self.item_name(def_id) {
            | sym::size_of
            | sym::min_align_of
            | sym::needs_drop
            // Arithmetic:
            | sym::add_with_overflow // ~> .overflowing_add
            | sym::sub_with_overflow // ~> .overflowing_sub
            | sym::mul_with_overflow // ~> .overflowing_mul
            | sym::wrapping_add // ~> .wrapping_add
            | sym::wrapping_sub // ~> .wrapping_sub
            | sym::wrapping_mul // ~> .wrapping_mul
            | sym::saturating_add // ~> .saturating_add
            | sym::saturating_sub // ~> .saturating_sub
            | sym::unchecked_shl // ~> .wrapping_shl
            | sym::unchecked_shr // ~> .wrapping_shr
            | sym::rotate_left // ~> .rotate_left
            | sym::rotate_right // ~> .rotate_right
            | sym::ctpop // ~> .count_ones
            | sym::ctlz // ~> .leading_zeros
            | sym::cttz // ~> .trailing_zeros
            | sym::bswap // ~> .swap_bytes
            | sym::bitreverse // ~> .reverse_bits
            => true,
            _ => false,
        }
    }

    /// Returns `true` if this function must conform to `min_const_fn`
    pub fn is_min_const_fn(self, def_id: DefId) -> bool {
        // Bail out if the signature doesn't contain `const`
        if !self.is_const_fn_raw(def_id) {
            return false;
        }
        if let Abi::RustIntrinsic = self.fn_sig(def_id).abi() {
            return self.is_intrinsic_min_const_fn(def_id);
        }

        if self.features().staged_api {
            // In order for a libstd function to be considered min_const_fn
            // it needs to be stable and have no `rustc_const_unstable` attribute.
            match self.lookup_const_stability(def_id) {
                // `rustc_const_unstable` functions don't need to conform.
                Some(&attr::ConstStability { ref level, .. }) if level.is_unstable() => false,
                None => if let Some(stab) = self.lookup_stability(def_id) {
                    if stab.level.is_stable() {
                        self.sess.span_err(
                            self.def_span(def_id),
                            "stable const functions must have either `rustc_const_stable` or \
                            `rustc_const_unstable` attribute",
                        );
                        // While we errored above, because we don't know if we need to conform, we
                        // err on the "safe" side and require min_const_fn.
                        true
                    } else {
                        // Unstable functions need not conform to min_const_fn.
                        false
                    }
                } else {
                    // Internal functions are forced to conform to min_const_fn.
                    // Annotate the internal function with a const stability attribute if
                    // you need to use unstable features.
                    // Note: this is an arbitrary choice that does not affect stability or const
                    // safety or anything, it just changes whether we need to annotate some
                    // internal functions with `rustc_const_stable` or with `rustc_const_unstable`
                    true
                },
                // Everything else needs to conform, because it would be callable from
                // other `min_const_fn` functions.
                _ => true,
            }
        } else {
            // users enabling the `const_fn` feature gate can do what they want
            !self.features().const_fn
        }
    }
}

pub fn provide(providers: &mut Providers<'_>) {
    /// Const evaluability whitelist is here to check evaluability at the
    /// top level beforehand.
    fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option<bool> {
        match tcx.fn_sig(def_id).abi() {
            Abi::RustIntrinsic |
            Abi::PlatformIntrinsic => {
                // FIXME: deduplicate these two lists as much as possible
                match tcx.item_name(def_id) {
                    // Keep this list in the same order as the match patterns in
                    // `librustc_mir/interpret/intrinsics.rs`

                    // This whitelist is a list of intrinsics that have a miri-engine implementation
                    // and can thus be called when enabling enough feature gates. The similar
                    // whitelist in `is_intrinsic_min_const_fn` (in this file), exists for allowing
                    // the intrinsics to be called by stable const fns.
                    | sym::caller_location

                    | sym::min_align_of
                    | sym::pref_align_of
                    | sym::needs_drop
                    | sym::size_of
                    | sym::type_id
                    | sym::type_name

                    | sym::ctpop
                    | sym::cttz
                    | sym::cttz_nonzero
                    | sym::ctlz
                    | sym::ctlz_nonzero
                    | sym::bswap
                    | sym::bitreverse

                    | sym::wrapping_add
                    | sym::wrapping_sub
                    | sym::wrapping_mul
                    | sym::add_with_overflow
                    | sym::sub_with_overflow
                    | sym::mul_with_overflow

                    | sym::saturating_add
                    | sym::saturating_sub

                    | sym::unchecked_shl
                    | sym::unchecked_shr

                    | sym::rotate_left
                    | sym::rotate_right

                    | sym::ptr_offset_from

                    | sym::transmute

                    | sym::simd_insert

                    | sym::simd_extract

                    => Some(true),

                    _ => Some(false)
                }
            }
            _ => None
        }
    }

    /// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether
    /// said intrinsic is on the whitelist for being const callable.
    fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
        let hir_id = tcx.hir().as_local_hir_id(def_id)
                              .expect("Non-local call to local provider is_const_fn");

        let node = tcx.hir().get(hir_id);

        if let Some(whitelisted) = is_const_intrinsic(tcx, def_id) {
            whitelisted
        } else if let Some(fn_like) = FnLikeNode::from_node(node) {
            fn_like.constness() == hir::Constness::Const
        } else if let hir::Node::Ctor(_) = node {
            true
        } else {
            false
        }
    }

    fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
        tcx.is_const_fn(def_id) && match tcx.lookup_const_stability(def_id) {
            Some(stab) => {
                if cfg!(debug_assertions) && stab.promotable {
                    let sig = tcx.fn_sig(def_id);
                    assert_eq!(
                        sig.unsafety(),
                        hir::Unsafety::Normal,
                        "don't mark const unsafe fns as promotable",
                        // https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682
                    );
                }
                stab.promotable
            },
            None => false,
        }
    }

    fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
        tcx.is_const_fn(def_id) &&
            tcx.lookup_const_stability(def_id)
                .map(|stab| stab.allow_const_fn_ptr).unwrap_or(false)
    }

    *providers = Providers {
        is_const_fn_raw,
        is_promotable_const_fn,
        const_fn_is_allowed_fn_ptr,
        ..*providers
    };
}
<|endoftext|>


<commit_before>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use core::sync::atomic::{spin_loop_hint, AtomicBool, Ordering};
use std::{
    os::fortanix_sgx::{
        thread::current as current_tcs,
        usercalls::{
            self,
            raw::{Tcs, EV_UNPARK, WAIT_INDEFINITE},
        },
    },
    thread,
    time::Instant,
};

// Helper type for putting a thread to sleep until some other thread wakes it up
pub struct ThreadParker {
    parked: AtomicBool,
    tcs: Tcs,
}

impl ThreadParker {
    pub const IS_CHEAP_TO_CONSTRUCT: bool = true;

    #[inline]
    pub fn new() -> ThreadParker {
        ThreadParker {
            parked: AtomicBool::new(false),
            tcs: current_tcs(),
        }
    }

    // Prepares the parker. This should be called before adding it to the queue.
    #[inline]
    pub fn prepare_park(&self) {
        self.parked.store(true, Ordering::Relaxed);
    }

    // Checks if the park timed out. This should be called while holding the
    // queue lock after park_until has returned false.
    #[inline]
    pub fn timed_out(&self) -> bool {
        self.parked.load(Ordering::Relaxed)
    }

    // Parks the thread until it is unparked. This should be called after it has
    // been added to the queue, after unlocking the queue.
    #[inline]
    pub fn park(&self) {
        while self.parked.load(Ordering::Acquire) {
            let res = usercalls::wait(EV_UNPARK, WAIT_INDEFINITE).expect("wait returned error");
            assert_eq!(res & EV_UNPARK, EV_UNPARK);
        }
    }

    // Parks the thread until it is unparked or the timeout is reached. This
    // should be called after it has been added to the queue, after unlocking
    // the queue. Returns true if we were unparked and false if we timed out.
    #[inline]
    pub fn park_until(&self, timeout: Instant) -> bool {
        while self.parked.load(Ordering::Acquire) {
            if Instant::now() >= timeout {
                return false;
            }
            // SGX currently does not support waiting for an event with a
            // timeout. So we just implement this as a spin loop.
            spin_loop_hint();
        }
        true
    }

    // Locks the parker to prevent the target thread from exiting. This is
    // necessary to ensure that thread-local ThreadData objects remain valid.
    // This should be called while holding the queue lock.
    #[inline]
    pub fn unpark_lock(&self) -> UnparkHandle {
        // We don't need to lock anything, just clear the state
        self.parked.store(false, Ordering::Release);
        UnparkHandle(self.tcs)
    }
}

// Handle for a thread that is about to be unparked. We need to mark the thread
// as unparked while holding the queue lock, but we delay the actual unparking
// until after the queue lock is released.
pub struct UnparkHandle(Tcs);

impl UnparkHandle {
    // Wakes up the parked thread. This should be called after the queue lock is
    // released to avoid blocking the queue for too long.
    #[inline]
    pub fn unpark(self) {
        usercalls::send(EV_UNPARK, Some(self.0)).expect("send returned error");
    }
}

#[inline]
pub fn thread_yield() {
    thread::yield_now();
}
<commit_msg>Panic in park_until instead of using timestamps<commit_after>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use core::sync::atomic::{AtomicBool, Ordering};
use std::{
    os::fortanix_sgx::{
        thread::current as current_tcs,
        usercalls::{
            self,
            raw::{Tcs, EV_UNPARK, WAIT_INDEFINITE},
        },
    },
    thread,
    time::Instant,
};

// Helper type for putting a thread to sleep until some other thread wakes it up
pub struct ThreadParker {
    parked: AtomicBool,
    tcs: Tcs,
}

impl ThreadParker {
    pub const IS_CHEAP_TO_CONSTRUCT: bool = true;

    #[inline]
    pub fn new() -> ThreadParker {
        ThreadParker {
            parked: AtomicBool::new(false),
            tcs: current_tcs(),
        }
    }

    // Prepares the parker. This should be called before adding it to the queue.
    #[inline]
    pub fn prepare_park(&self) {
        self.parked.store(true, Ordering::Relaxed);
    }

    // Checks if the park timed out. This should be called while holding the
    // queue lock after park_until has returned false.
    #[inline]
    pub fn timed_out(&self) -> bool {
        self.parked.load(Ordering::Relaxed)
    }

    // Parks the thread until it is unparked. This should be called after it has
    // been added to the queue, after unlocking the queue.
    #[inline]
    pub fn park(&self) {
        while self.parked.load(Ordering::Acquire) {
            let res = usercalls::wait(EV_UNPARK, WAIT_INDEFINITE).expect("wait returned error");
            assert_eq!(res & EV_UNPARK, EV_UNPARK);
        }
    }

    // Parks the thread until it is unparked or the timeout is reached. This
    // should be called after it has been added to the queue, after unlocking
    // the queue. Returns true if we were unparked and false if we timed out.
    #[inline]
    pub fn park_until(&self, _timeout: Instant) -> bool {
        // FIXME: https://github.com/fortanix/rust-sgx/issues/31
        panic!("timeout not supported in SGX");
    }

    // Locks the parker to prevent the target thread from exiting. This is
    // necessary to ensure that thread-local ThreadData objects remain valid.
    // This should be called while holding the queue lock.
    #[inline]
    pub fn unpark_lock(&self) -> UnparkHandle {
        // We don't need to lock anything, just clear the state
        self.parked.store(false, Ordering::Release);
        UnparkHandle(self.tcs)
    }
}

// Handle for a thread that is about to be unparked. We need to mark the thread
// as unparked while holding the queue lock, but we delay the actual unparking
// until after the queue lock is released.
pub struct UnparkHandle(Tcs);

impl UnparkHandle {
    // Wakes up the parked thread. This should be called after the queue lock is
    // released to avoid blocking the queue for too long.
    #[inline]
    pub fn unpark(self) {
        usercalls::send(EV_UNPARK, Some(self.0)).expect("send returned error");
    }
}

#[inline]
pub fn thread_yield() {
    thread::yield_now();
}
<|endoftext|>


<commit_before>use actix::prelude::*;
use godcoin::prelude::{net::ErrorKind, *};
use std::io::Cursor;

mod common;
pub use common::*;

#[test]
fn error_with_bytes_remaining() {
    System::run(|| {
        let minter = TestMinter::new();

        let body = {
            let req = net::RequestType::Batch(vec![MsgRequest::GetBlock(0)]);
            let mut buf = Vec::with_capacity(4096);
            req.serialize(&mut buf);

            // Set the batch len to 0
            buf[1..=4].iter_mut().for_each(|x| *x = 0);

            buf
        };

        // Confirm the length is actually 0 in case the binary format changes
        match net::RequestType::deserialize(&mut Cursor::new(&body)).unwrap() {
            net::RequestType::Batch(reqs) => assert_eq!(reqs.len(), 0),
            _ => panic!("Expected batch request type"),
        }

        let fut = minter.raw_request(body);
        Arbiter::spawn(fut.and_then(move |res| {
            let res = res.unwrap_single();
            assert!(res.is_err());
            assert_eq!(res, MsgResponse::Error(ErrorKind::BytesRemaining));

            System::current().stop();
            Ok(())
        }));
    })
    .unwrap();
}

#[test]
fn get_block() {
    System::run(|| {
        let minter = TestMinter::new();
        let fut = minter.request(MsgRequest::GetBlock(0));
        Arbiter::spawn(
            fut.and_then(move |res| {
                assert!(!res.is_err());

                let other = minter.chain().get_block(0).unwrap();
                assert_eq!(res, MsgResponse::GetBlock((*other).clone()));

                minter.request(MsgRequest::GetBlock(2))
            })
            .then(|res| {
                let res = res.unwrap();
                assert!(res.is_err());
                assert_eq!(res, MsgResponse::Error(ErrorKind::InvalidHeight));

                System::current().stop();
                Ok(())
            }),
        );
    })
    .unwrap();
}

#[test]
fn successful_broadcast() {
    System::run(|| {
        let minter = TestMinter::new();

        let mut tx = MintTx {
            base: create_tx_header(TxType::MINT, "0.0000 GRAEL"),
            to: (&minter.genesis_info().script).into(),
            amount: get_asset("10.0000 GRAEL"),
            attachment: vec![],
            attachment_name: "".to_owned(),
            script: minter.genesis_info().script.clone(),
        };

        tx.append_sign(&minter.genesis_info().wallet_keys[1]);
        tx.append_sign(&minter.genesis_info().wallet_keys[0]);

        let tx = TxVariant::MintTx(tx);
        let fut = minter.request(MsgRequest::Broadcast(tx));
        Arbiter::spawn(fut.and_then(move |res| {
            assert_eq!(res, MsgResponse::Broadcast());

            System::current().stop();
            Ok(())
        }));
    })
    .unwrap();
}

#[test]
fn batch_preserves_order() {
    System::run(|| {
        let minter = TestMinter::new();
        let fut = minter.batch_request(vec![
            MsgRequest::GetBlock(0),
            MsgRequest::GetBlock(2),
            MsgRequest::GetBlock(1),
        ]);
        Arbiter::spawn(fut.and_then(move |responses| {
            assert_eq!(responses.len(), 3);

            let block_0 = minter.chain().get_block(0).unwrap();
            let block_1 = minter.chain().get_block(1).unwrap();

            assert_eq!(responses[0], MsgResponse::GetBlock((*block_0).clone()));
            assert_eq!(
                responses[1],
                MsgResponse::Error(net::ErrorKind::InvalidHeight)
            );
            assert_eq!(responses[2], MsgResponse::GetBlock((*block_1).clone()));

            System::current().stop();
            Ok(())
        }));
    })
    .unwrap();
}
<commit_msg>Add GetProperties test<commit_after>use actix::prelude::*;
use godcoin::prelude::{net::ErrorKind, *};
use std::io::Cursor;

mod common;
pub use common::*;

#[test]
fn get_properties() {
    System::run(|| {
        let minter = TestMinter::new();
        let fut = minter.request(MsgRequest::GetProperties);
        Arbiter::spawn(fut.and_then(move |res| {
            let chain_props = minter.chain().get_properties();
            assert!(!res.is_err());
            assert_eq!(res, MsgResponse::GetProperties(chain_props));

            System::current().stop();
            Ok(())
        }));
    })
    .unwrap();
}

#[test]
fn get_block() {
    System::run(|| {
        let minter = TestMinter::new();
        let fut = minter.request(MsgRequest::GetBlock(0));
        Arbiter::spawn(
            fut.and_then(move |res| {
                assert!(!res.is_err());

                let other = minter.chain().get_block(0).unwrap();
                assert_eq!(res, MsgResponse::GetBlock((*other).clone()));

                minter.request(MsgRequest::GetBlock(2))
            })
            .then(|res| {
                let res = res.unwrap();
                assert!(res.is_err());
                assert_eq!(res, MsgResponse::Error(ErrorKind::InvalidHeight));

                System::current().stop();
                Ok(())
            }),
        );
    })
    .unwrap();
}

#[test]
fn successful_broadcast() {
    System::run(|| {
        let minter = TestMinter::new();

        let mut tx = MintTx {
            base: create_tx_header(TxType::MINT, "0.0000 GRAEL"),
            to: (&minter.genesis_info().script).into(),
            amount: get_asset("10.0000 GRAEL"),
            attachment: vec![],
            attachment_name: "".to_owned(),
            script: minter.genesis_info().script.clone(),
        };

        tx.append_sign(&minter.genesis_info().wallet_keys[1]);
        tx.append_sign(&minter.genesis_info().wallet_keys[0]);

        let tx = TxVariant::MintTx(tx);
        let fut = minter.request(MsgRequest::Broadcast(tx));
        Arbiter::spawn(fut.and_then(move |res| {
            assert_eq!(res, MsgResponse::Broadcast());

            System::current().stop();
            Ok(())
        }));
    })
    .unwrap();
}

#[test]
fn error_with_bytes_remaining() {
    System::run(|| {
        let minter = TestMinter::new();

        let body = {
            let req = net::RequestType::Batch(vec![MsgRequest::GetBlock(0)]);
            let mut buf = Vec::with_capacity(4096);
            req.serialize(&mut buf);

            // Set the batch len to 0
            buf[1..=4].iter_mut().for_each(|x| *x = 0);

            buf
        };

        // Confirm the length is actually 0 in case the binary format changes
        match net::RequestType::deserialize(&mut Cursor::new(&body)).unwrap() {
            net::RequestType::Batch(reqs) => assert_eq!(reqs.len(), 0),
            _ => panic!("Expected batch request type"),
        }

        let fut = minter.raw_request(body);
        Arbiter::spawn(fut.and_then(move |res| {
            let res = res.unwrap_single();
            assert!(res.is_err());
            assert_eq!(res, MsgResponse::Error(ErrorKind::BytesRemaining));

            System::current().stop();
            Ok(())
        }));
    })
    .unwrap();
}

#[test]
fn batch_preserves_order() {
    System::run(|| {
        let minter = TestMinter::new();
        let fut = minter.batch_request(vec![
            MsgRequest::GetBlock(0),
            MsgRequest::GetBlock(2),
            MsgRequest::GetBlock(1),
        ]);
        Arbiter::spawn(fut.and_then(move |responses| {
            assert_eq!(responses.len(), 3);

            let block_0 = minter.chain().get_block(0).unwrap();
            let block_1 = minter.chain().get_block(1).unwrap();

            assert_eq!(responses[0], MsgResponse::GetBlock((*block_0).clone()));
            assert_eq!(
                responses[1],
                MsgResponse::Error(net::ErrorKind::InvalidHeight)
            );
            assert_eq!(responses[2], MsgResponse::GetBlock((*block_1).clone()));

            System::current().stop();
            Ok(())
        }));
    })
    .unwrap();
}
<|endoftext|>


<commit_before>use logger::prelude::*;
use std::{thread, time, vec::IntoIter};

/// Items are returned in the world of microseconds.
const MICROSECONDS_IN_ONE_SECOND: u64 = 1_000_000;

/// Utilize IntoIter to implement an iterator that returns constant number of items per second.
/// That is, an item is returned to user after waiting some time duration.
/// Return immediately (e.g. flood all available items) when rate is set to u64::MAX.
#[derive(Debug, Clone)]
pub struct ConstantRate<T> {
    /// Number of items to return per second.
    rate: u64,
    /// Time duration to return 1 item.
    interval_us: u64,
    /// Between two calls to next(), user may perform operations on the item, consuming some time.
    /// We calculate it as the duration between two last_call values and then exclude.
    last_call: time::Instant,
    /// Pointer to the items to be consumed.
    into_iter: IntoIter<T>,
}

impl<T> ConstantRate<T> {
    /// Init with rate, and the IntoIter of the vector to be consumed.
    /// For simplicity we assume user calls next() right after new().
    pub fn new(rate: u64, into_iter: IntoIter<T>) -> Self {
        assert!(rate > 0);
        let interval_us = MICROSECONDS_IN_ONE_SECOND / rate;
        debug!("Return 1 item after {} us", interval_us);
        ConstantRate {
            rate,
            interval_us,
            last_call: time::Instant::now(),
            into_iter,
        }
    }
}

impl<T> Iterator for ConstantRate<T> {
    type Item = T;
    fn next(&mut self) -> Option<T> {
        let exclude_duration_us = self.last_call.elapsed().as_micros() as u64;
        if self.interval_us > exclude_duration_us {
            let rest = self.interval_us - exclude_duration_us;
            debug!("Sleep {} us before return next item", rest);
            thread::sleep(time::Duration::from_micros(rest as u64));
        }
        self.last_call = time::Instant::now();
        self.into_iter.next()
    }
}

#[cfg(test)]
mod tests {
    use crate::submit_rate::ConstantRate;
    use std::{thread, time};

    #[test]
    fn test_submit_rate_empty_vec() {
        let empty_vec: Vec<u32> = vec![];
        let mut rate = ConstantRate::new(1, empty_vec.into_iter());
        let item = rate.next();
        assert_eq!(item.is_none(), true);
    }

    #[test]
    fn test_submit_rate_flood_all() {
        let vec = vec![1, 2, 3, 4, 5, 6, 7];
        let flood = ConstantRate::new(std::u64::MAX, vec.into_iter());

        let now = time::Instant::now();
        // consume all elements
        flood.into_iter().for_each(drop);
        let elapsed = now.elapsed().as_micros();
        // Loop should finish instantly
        assert!(elapsed < 1000);
    }

    #[test]
    fn test_submit_rate_contant_rate() {
        let vec = vec![1, 2, 3, 4, 5, 6, 7, 8];
        let const_rate = ConstantRate::new(2, vec.into_iter());

        let mut now = time::Instant::now();
        for _item in const_rate {
            let new_now = time::Instant::now();
            let delta = new_now.duration_since(now).as_micros();
            // Interval between each call to next() should be roughly 0.5 second.
            assert!(delta < 510_000);
            assert!(delta > 490_000);
            now = new_now;
        }
    }

    #[test]
    fn test_submit_rate_exclude_duration() {
        let vec = vec![1, 2, 3, 4, 5, 6, 7, 8];
        let const_rate = ConstantRate::new(2, vec.into_iter());

        let mut now = time::Instant::now();
        for _item in const_rate {
            let new_now = time::Instant::now();
            let delta = new_now.duration_since(now).as_micros();
            // Interval between each call to next() should be roughly 0.5 second.
            assert!(delta < 510_000);
            assert!(delta > 490_000);
            now = time::Instant::now();
            // Use this sleep to emulate that user performed something on item.
            thread::sleep(time::Duration::from_micros(10_000));
        }
    }
}
<commit_msg>[benchmark] make clippy happy<commit_after>use logger::prelude::*;
use std::{thread, time, vec::IntoIter};

/// Items are returned in the world of microseconds.
const MICROSECONDS_IN_ONE_SECOND: u64 = 1_000_000;

/// Utilize IntoIter to implement an iterator that returns constant number of items per second.
/// That is, an item is returned to user after waiting some time duration.
/// Return immediately (e.g. flood all available items) when rate is set to u64::MAX.
#[derive(Debug, Clone)]
pub struct ConstantRate<T> {
    /// Number of items to return per second.
    rate: u64,
    /// Time duration to return 1 item.
    interval_us: u64,
    /// Between two calls to next(), user may perform operations on the item, consuming some time.
    /// We calculate it as the duration between two last_call values and then exclude.
    last_call: time::Instant,
    /// Pointer to the items to be consumed.
    into_iter: IntoIter<T>,
}

impl<T> ConstantRate<T> {
    /// Init with rate, and the IntoIter of the vector to be consumed.
    /// For simplicity we assume user calls next() right after new().
    pub fn new(rate: u64, into_iter: IntoIter<T>) -> Self {
        assert!(rate > 0);
        let interval_us = MICROSECONDS_IN_ONE_SECOND / rate;
        debug!("Return 1 item after {} us", interval_us);
        ConstantRate {
            rate,
            interval_us,
            last_call: time::Instant::now(),
            into_iter,
        }
    }
}

impl<T> Iterator for ConstantRate<T> {
    type Item = T;
    fn next(&mut self) -> Option<T> {
        let exclude_duration_us = self.last_call.elapsed().as_micros() as u64;
        if self.interval_us > exclude_duration_us {
            let rest = self.interval_us - exclude_duration_us;
            debug!("Sleep {} us before return next item", rest);
            thread::sleep(time::Duration::from_micros(rest as u64));
        }
        self.last_call = time::Instant::now();
        self.into_iter.next()
    }
}

#[cfg(test)]
mod tests {
    use crate::submit_rate::ConstantRate;
    use std::{thread, time};

    #[test]
    fn test_submit_rate_empty_vec() {
        let empty_vec: Vec<u32> = vec![];
        let mut rate = ConstantRate::new(1, empty_vec.into_iter());
        let item = rate.next();
        assert_eq!(item.is_none(), true);
    }

    #[test]
    fn test_submit_rate_flood_all() {
        let vec = vec![1, 2, 3, 4, 5, 6, 7];
        let flood = ConstantRate::new(std::u64::MAX, vec.into_iter());

        let now = time::Instant::now();
        // consume all elements
        flood.for_each(drop);
        let elapsed = now.elapsed().as_micros();
        // Loop should finish instantly
        assert!(elapsed < 1000);
    }

    #[test]
    fn test_submit_rate_contant_rate() {
        let vec = vec![1, 2, 3, 4, 5, 6, 7, 8];
        let const_rate = ConstantRate::new(2, vec.into_iter());

        let mut now = time::Instant::now();
        for _item in const_rate {
            let new_now = time::Instant::now();
            let delta = new_now.duration_since(now).as_micros();
            // Interval between each call to next() should be roughly 0.5 second.
            assert!(delta < 510_000);
            assert!(delta > 490_000);
            now = new_now;
        }
    }

    #[test]
    fn test_submit_rate_exclude_duration() {
        let vec = vec![1, 2, 3, 4, 5, 6, 7, 8];
        let const_rate = ConstantRate::new(2, vec.into_iter());

        let mut now = time::Instant::now();
        for _item in const_rate {
            let new_now = time::Instant::now();
            let delta = new_now.duration_since(now).as_micros();
            // Interval between each call to next() should be roughly 0.5 second.
            assert!(delta < 510_000);
            assert!(delta > 490_000);
            now = time::Instant::now();
            // Use this sleep to emulate that user performed something on item.
            thread::sleep(time::Duration::from_micros(10_000));
        }
    }
}
<|endoftext|>