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

extern crate gcc;
extern crate build_helper;

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

use build_helper::output;

fn detect_llvm_link(llvm_config: &Path) -> (&'static str, Option<&'static str>) {
    let mut version_cmd = Command::new(llvm_config);
    version_cmd.arg("--version");
    let version_output = output(&mut version_cmd);
    let mut parts = version_output.split('.').take(2)
        .filter_map(|s| s.parse::<u32>().ok());
    if let (Some(major), Some(minor)) = (parts.next(), parts.next()) {
        if major > 3 || (major == 3 && minor >= 9) {
            // Force the link mode we want, preferring static by default, but
            // possibly overridden by `configure --enable-llvm-link-shared`.
            if env::var_os("LLVM_LINK_SHARED").is_some() {
                return ("dylib", Some("--link-shared"));
            } else {
                return ("static", Some("--link-static"));
            }
        } else if major == 3 && minor == 8 {
            // Find out LLVM's default linking mode.
            let mut mode_cmd = Command::new(llvm_config);
            mode_cmd.arg("--shared-mode");
            if output(&mut mode_cmd).trim() == "shared" {
                return ("dylib", None);
            } else {
                return ("static", None);
            }
        }
    }
    ("static", None)
}

fn main() {
    println!("cargo:rustc-cfg=cargobuild");

    let target = env::var("TARGET").expect("TARGET was not set");
    let llvm_config = env::var_os("LLVM_CONFIG")
        .map(PathBuf::from)
        .unwrap_or_else(|| {
            if let Some(dir) = env::var_os("CARGO_TARGET_DIR").map(PathBuf::from) {
                let to_test = dir.parent()
                    .unwrap()
                    .parent()
                    .unwrap()
                    .join(&target)
                    .join("llvm/bin/llvm-config");
                if Command::new(&to_test).output().is_ok() {
                    return to_test;
                }
            }
            PathBuf::from("llvm-config")
        });

    println!("cargo:rerun-if-changed={}", llvm_config.display());

    // Test whether we're cross-compiling LLVM. This is a pretty rare case
    // currently where we're producing an LLVM for a different platform than
    // what this build script is currently running on.
    //
    // In that case, there's no guarantee that we can actually run the target,
    // so the build system works around this by giving us the LLVM_CONFIG for
    // the host platform. This only really works if the host LLVM and target
    // LLVM are compiled the same way, but for us that's typically the case.
    //
    // We *want* detect this cross compiling situation by asking llvm-config
    // what it's host-target is. If that's not the TARGET, then we're cross
    // compiling. Unfortunately `llvm-config` seems either be buggy, or we're
    // misconfiguring it, because the `i686-pc-windows-gnu` build of LLVM will
    // report itself with a `--host-target` of `x86_64-pc-windows-gnu`. This
    // tricks us into thinking we're doing a cross build when we aren't, so
    // havoc ensues.
    //
    // In any case, if we're cross compiling, this generally just means that we
    // can't trust all the output of llvm-config becaues it might be targeted
    // for the host rather than the target. As a result a bunch of blocks below
    // are gated on `if !is_crossed`
    let target = env::var("TARGET").expect("TARGET was not set");
    let host = env::var("HOST").expect("HOST was not set");
    let is_crossed = target != host;

    let optional_components =
        ["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", "systemz", "jsbackend", "msp430", "sparc"];

    // FIXME: surely we don't need all these components, right? Stuff like mcjit
    //        or interpreter the compiler itself never uses.
    let required_components = &["ipo",
                                "bitreader",
                                "bitwriter",
                                "linker",
                                "asmparser",
                                "mcjit",
                                "interpreter",
                                "instrumentation"];

    let components = output(Command::new(&llvm_config).arg("--components"));
    let mut components = components.split_whitespace().collect::<Vec<_>>();
    components.retain(|c| optional_components.contains(c) || required_components.contains(c));

    for component in required_components {
        if !components.contains(component) {
            panic!("require llvm component {} but wasn't found", component);
        }
    }

    for component in components.iter() {
        println!("cargo:rustc-cfg=llvm_component=\"{}\"", component);
    }

    // Link in our own LLVM shims, compiled with the same flags as LLVM
    let mut cmd = Command::new(&llvm_config);
    cmd.arg("--cxxflags");
    let cxxflags = output(&mut cmd);
    let mut cfg = gcc::Config::new();
    for flag in cxxflags.split_whitespace() {
        // Ignore flags like `-m64` when we're doing a cross build
        if is_crossed && flag.starts_with("-m") {
            continue;
        }
        cfg.flag(flag);
    }

    for component in &components[..] {
        let mut flag = String::from("-DLLVM_COMPONENT_");
        flag.push_str(&component.to_uppercase());
        cfg.flag(&flag);
    }

    if env::var_os("LLVM_RUSTLLVM").is_some() {
        cfg.flag("-DLLVM_RUSTLLVM");
    }

    println!("cargo:rerun-if-changed=../rustllvm/PassWrapper.cpp");
    println!("cargo:rerun-if-changed=../rustllvm/RustWrapper.cpp");
    println!("cargo:rerun-if-changed=../rustllvm/ArchiveWrapper.cpp");
    cfg.file("../rustllvm/PassWrapper.cpp")
       .file("../rustllvm/RustWrapper.cpp")
       .file("../rustllvm/ArchiveWrapper.cpp")
       .cpp(true)
       .cpp_link_stdlib(None) // we handle this below
       .compile("librustllvm.a");

    let (llvm_kind, llvm_link_arg) = detect_llvm_link(&llvm_config);

    // Link in all LLVM libraries, if we're uwring the "wrong" llvm-config then
    // we don't pick up system libs because unfortunately they're for the host
    // of llvm-config, not the target that we're attempting to link.
    let mut cmd = Command::new(&llvm_config);
    cmd.arg("--libs");

    if let Some(link_arg) = llvm_link_arg {
        cmd.arg(link_arg);
    }

    if !is_crossed {
        cmd.arg("--system-libs");
    }
    cmd.args(&components[..]);

    for lib in output(&mut cmd).split_whitespace() {
        let name = if lib.starts_with("-l") {
            &lib[2..]
        } else if lib.starts_with("-") {
            &lib[1..]
        } else if Path::new(lib).exists() {
            // On MSVC llvm-config will print the full name to libraries, but
            // we're only interested in the name part
            let name = Path::new(lib).file_name().unwrap().to_str().unwrap();
            name.trim_right_matches(".lib")
        } else if lib.ends_with(".lib") {
            // Some MSVC libraries just come up with `.lib` tacked on, so chop
            // that off
            lib.trim_right_matches(".lib")
        } else {
            continue;
        };

        // Don't need or want this library, but LLVM's CMake build system
        // doesn't provide a way to disable it, so filter it here even though we
        // may or may not have built it. We don't reference anything from this
        // library and it otherwise may just pull in extra dependencies on
        // libedit which we don't want
        if name == "LLVMLineEditor" {
            continue;
        }

        let kind = if name.starts_with("LLVM") {
            llvm_kind
        } else {
            "dylib"
        };
        println!("cargo:rustc-link-lib={}={}", kind, name);
    }

    // LLVM ldflags
    //
    // If we're a cross-compile of LLVM then unfortunately we can't trust these
    // ldflags (largely where all the LLVM libs are located). Currently just
    // hack around this by replacing the host triple with the target and pray
    // that those -L directories are the same!
    let mut cmd = Command::new(&llvm_config);
    cmd.arg("--ldflags");
    for lib in output(&mut cmd).split_whitespace() {
        if lib.starts_with("-LIBPATH:") {
            println!("cargo:rustc-link-search=native={}", &lib[9..]);
        } else if is_crossed {
            if lib.starts_with("-L") {
                println!("cargo:rustc-link-search=native={}",
                         lib[2..].replace(&host, &target));
            }
        } else if lib.starts_with("-l") {
            println!("cargo:rustc-link-lib={}", &lib[2..]);
        } else if lib.starts_with("-L") {
            println!("cargo:rustc-link-search=native={}", &lib[2..]);
        }
    }

    // C++ runtime library
    if !target.contains("msvc") {
        if let Some(s) = env::var_os("LLVM_STATIC_STDCPP") {
            assert!(!cxxflags.contains("stdlib=libc++"));
            let path = PathBuf::from(s);
            println!("cargo:rustc-link-search=native={}",
                     path.parent().unwrap().display());
            println!("cargo:rustc-link-lib=static=stdc++");
        } else if cxxflags.contains("stdlib=libc++") {
            println!("cargo:rustc-link-lib=c++");
        } else {
            println!("cargo:rustc-link-lib=stdc++");
        }
    }
}
<commit_msg>fix tidy<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate gcc;
extern crate build_helper;

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

use build_helper::output;

fn detect_llvm_link(llvm_config: &Path) -> (&'static str, Option<&'static str>) {
    let mut version_cmd = Command::new(llvm_config);
    version_cmd.arg("--version");
    let version_output = output(&mut version_cmd);
    let mut parts = version_output.split('.').take(2)
        .filter_map(|s| s.parse::<u32>().ok());
    if let (Some(major), Some(minor)) = (parts.next(), parts.next()) {
        if major > 3 || (major == 3 && minor >= 9) {
            // Force the link mode we want, preferring static by default, but
            // possibly overridden by `configure --enable-llvm-link-shared`.
            if env::var_os("LLVM_LINK_SHARED").is_some() {
                return ("dylib", Some("--link-shared"));
            } else {
                return ("static", Some("--link-static"));
            }
        } else if major == 3 && minor == 8 {
            // Find out LLVM's default linking mode.
            let mut mode_cmd = Command::new(llvm_config);
            mode_cmd.arg("--shared-mode");
            if output(&mut mode_cmd).trim() == "shared" {
                return ("dylib", None);
            } else {
                return ("static", None);
            }
        }
    }
    ("static", None)
}

fn main() {
    println!("cargo:rustc-cfg=cargobuild");

    let target = env::var("TARGET").expect("TARGET was not set");
    let llvm_config = env::var_os("LLVM_CONFIG")
        .map(PathBuf::from)
        .unwrap_or_else(|| {
            if let Some(dir) = env::var_os("CARGO_TARGET_DIR").map(PathBuf::from) {
                let to_test = dir.parent()
                    .unwrap()
                    .parent()
                    .unwrap()
                    .join(&target)
                    .join("llvm/bin/llvm-config");
                if Command::new(&to_test).output().is_ok() {
                    return to_test;
                }
            }
            PathBuf::from("llvm-config")
        });

    println!("cargo:rerun-if-changed={}", llvm_config.display());

    // Test whether we're cross-compiling LLVM. This is a pretty rare case
    // currently where we're producing an LLVM for a different platform than
    // what this build script is currently running on.
    //
    // In that case, there's no guarantee that we can actually run the target,
    // so the build system works around this by giving us the LLVM_CONFIG for
    // the host platform. This only really works if the host LLVM and target
    // LLVM are compiled the same way, but for us that's typically the case.
    //
    // We *want* detect this cross compiling situation by asking llvm-config
    // what it's host-target is. If that's not the TARGET, then we're cross
    // compiling. Unfortunately `llvm-config` seems either be buggy, or we're
    // misconfiguring it, because the `i686-pc-windows-gnu` build of LLVM will
    // report itself with a `--host-target` of `x86_64-pc-windows-gnu`. This
    // tricks us into thinking we're doing a cross build when we aren't, so
    // havoc ensues.
    //
    // In any case, if we're cross compiling, this generally just means that we
    // can't trust all the output of llvm-config becaues it might be targeted
    // for the host rather than the target. As a result a bunch of blocks below
    // are gated on `if !is_crossed`
    let target = env::var("TARGET").expect("TARGET was not set");
    let host = env::var("HOST").expect("HOST was not set");
    let is_crossed = target != host;

    let optional_components =
        ["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", "systemz", "jsbackend", "msp430",
         "sparc"];

    // FIXME: surely we don't need all these components, right? Stuff like mcjit
    //        or interpreter the compiler itself never uses.
    let required_components = &["ipo",
                                "bitreader",
                                "bitwriter",
                                "linker",
                                "asmparser",
                                "mcjit",
                                "interpreter",
                                "instrumentation"];

    let components = output(Command::new(&llvm_config).arg("--components"));
    let mut components = components.split_whitespace().collect::<Vec<_>>();
    components.retain(|c| optional_components.contains(c) || required_components.contains(c));

    for component in required_components {
        if !components.contains(component) {
            panic!("require llvm component {} but wasn't found", component);
        }
    }

    for component in components.iter() {
        println!("cargo:rustc-cfg=llvm_component=\"{}\"", component);
    }

    // Link in our own LLVM shims, compiled with the same flags as LLVM
    let mut cmd = Command::new(&llvm_config);
    cmd.arg("--cxxflags");
    let cxxflags = output(&mut cmd);
    let mut cfg = gcc::Config::new();
    for flag in cxxflags.split_whitespace() {
        // Ignore flags like `-m64` when we're doing a cross build
        if is_crossed && flag.starts_with("-m") {
            continue;
        }
        cfg.flag(flag);
    }

    for component in &components[..] {
        let mut flag = String::from("-DLLVM_COMPONENT_");
        flag.push_str(&component.to_uppercase());
        cfg.flag(&flag);
    }

    if env::var_os("LLVM_RUSTLLVM").is_some() {
        cfg.flag("-DLLVM_RUSTLLVM");
    }

    println!("cargo:rerun-if-changed=../rustllvm/PassWrapper.cpp");
    println!("cargo:rerun-if-changed=../rustllvm/RustWrapper.cpp");
    println!("cargo:rerun-if-changed=../rustllvm/ArchiveWrapper.cpp");
    cfg.file("../rustllvm/PassWrapper.cpp")
       .file("../rustllvm/RustWrapper.cpp")
       .file("../rustllvm/ArchiveWrapper.cpp")
       .cpp(true)
       .cpp_link_stdlib(None) // we handle this below
       .compile("librustllvm.a");

    let (llvm_kind, llvm_link_arg) = detect_llvm_link(&llvm_config);

    // Link in all LLVM libraries, if we're uwring the "wrong" llvm-config then
    // we don't pick up system libs because unfortunately they're for the host
    // of llvm-config, not the target that we're attempting to link.
    let mut cmd = Command::new(&llvm_config);
    cmd.arg("--libs");

    if let Some(link_arg) = llvm_link_arg {
        cmd.arg(link_arg);
    }

    if !is_crossed {
        cmd.arg("--system-libs");
    }
    cmd.args(&components[..]);

    for lib in output(&mut cmd).split_whitespace() {
        let name = if lib.starts_with("-l") {
            &lib[2..]
        } else if lib.starts_with("-") {
            &lib[1..]
        } else if Path::new(lib).exists() {
            // On MSVC llvm-config will print the full name to libraries, but
            // we're only interested in the name part
            let name = Path::new(lib).file_name().unwrap().to_str().unwrap();
            name.trim_right_matches(".lib")
        } else if lib.ends_with(".lib") {
            // Some MSVC libraries just come up with `.lib` tacked on, so chop
            // that off
            lib.trim_right_matches(".lib")
        } else {
            continue;
        };

        // Don't need or want this library, but LLVM's CMake build system
        // doesn't provide a way to disable it, so filter it here even though we
        // may or may not have built it. We don't reference anything from this
        // library and it otherwise may just pull in extra dependencies on
        // libedit which we don't want
        if name == "LLVMLineEditor" {
            continue;
        }

        let kind = if name.starts_with("LLVM") {
            llvm_kind
        } else {
            "dylib"
        };
        println!("cargo:rustc-link-lib={}={}", kind, name);
    }

    // LLVM ldflags
    //
    // If we're a cross-compile of LLVM then unfortunately we can't trust these
    // ldflags (largely where all the LLVM libs are located). Currently just
    // hack around this by replacing the host triple with the target and pray
    // that those -L directories are the same!
    let mut cmd = Command::new(&llvm_config);
    cmd.arg("--ldflags");
    for lib in output(&mut cmd).split_whitespace() {
        if lib.starts_with("-LIBPATH:") {
            println!("cargo:rustc-link-search=native={}", &lib[9..]);
        } else if is_crossed {
            if lib.starts_with("-L") {
                println!("cargo:rustc-link-search=native={}",
                         lib[2..].replace(&host, &target));
            }
        } else if lib.starts_with("-l") {
            println!("cargo:rustc-link-lib={}", &lib[2..]);
        } else if lib.starts_with("-L") {
            println!("cargo:rustc-link-search=native={}", &lib[2..]);
        }
    }

    // C++ runtime library
    if !target.contains("msvc") {
        if let Some(s) = env::var_os("LLVM_STATIC_STDCPP") {
            assert!(!cxxflags.contains("stdlib=libc++"));
            let path = PathBuf::from(s);
            println!("cargo:rustc-link-search=native={}",
                     path.parent().unwrap().display());
            println!("cargo:rustc-link-lib=static=stdc++");
        } else if cxxflags.contains("stdlib=libc++") {
            println!("cargo:rustc-link-lib=c++");
        } else {
            println!("cargo:rustc-link-lib=stdc++");
        }
    }
}
<|endoftext|>


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

use fmt;
use sync::{Mutex, Condvar};

/// A barrier enables multiple threads to synchronize the beginning
/// of some computation.
///
/// # Examples
///
/// ```
/// use std::sync::{Arc, Barrier};
/// use std::thread;
///
/// let mut handles = Vec::with_capacity(10);
/// let barrier = Arc::new(Barrier::new(10));
/// for _ in 0..10 {
///     let c = barrier.clone();
///     // The same messages will be printed together.
///     // You will NOT see any interleaving.
///     handles.push(thread::spawn(move|| {
///         println!("before wait");
///         c.wait();
///         println!("after wait");
///     }));
/// }
/// // Wait for other threads to finish.
/// for handle in handles {
///     handle.join().unwrap();
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Barrier {
    lock: Mutex<BarrierState>,
    cvar: Condvar,
    num_threads: usize,
}

// The inner state of a double barrier
struct BarrierState {
    count: usize,
    generation_id: usize,
}

/// A `BarrierWaitResult` is returned by [`wait`] when all threads in the [`Barrier`]
/// have rendezvoused.
///
/// [`wait`]: struct.Barrier.html#method.wait
/// [`Barrier`]: struct.Barrier.html
///
/// # Examples
///
/// ```
/// use std::sync::Barrier;
///
/// let barrier = Barrier::new(1);
/// let barrier_wait_result = barrier.wait();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct BarrierWaitResult(bool);

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Barrier {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Barrier { .. }")
    }
}

impl Barrier {
    /// Creates a new barrier that can block a given number of threads.
    ///
    /// A barrier will block `n`-1 threads which call [`wait`] and then wake up
    /// all threads at once when the `n`th thread calls [`wait`].
    ///
    /// [`wait`]: #method.wait
    ///
    /// # Examples
    ///
    /// ```
    /// use std::sync::Barrier;
    ///
    /// let barrier = Barrier::new(10);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new(n: usize) -> Barrier {
        Barrier {
            lock: Mutex::new(BarrierState {
                count: 0,
                generation_id: 0,
            }),
            cvar: Condvar::new(),
            num_threads: n,
        }
    }

    /// Blocks the current thread until all threads have rendezvoused here.
    ///
    /// Barriers are re-usable after all threads have rendezvoused once, and can
    /// be used continuously.
    ///
    /// A single (arbitrary) thread will receive a [`BarrierWaitResult`] that
    /// returns `true` from [`is_leader`] when returning from this function, and
    /// all other threads will receive a result that will return `false` from
    /// [`is_leader`].
    ///
    /// [`BarrierWaitResult`]: struct.BarrierWaitResult.html
    /// [`is_leader`]: struct.BarrierWaitResult.html#method.is_leader
    ///
    /// # Examples
    ///
    /// ```
    /// use std::sync::{Arc, Barrier};
    /// use std::thread;
    ///
    /// let mut handles = Vec::with_capacity(10);
    /// let barrier = Arc::new(Barrier::new(10));
    /// for _ in 0..10 {
    ///     let c = barrier.clone();
    ///     // The same messages will be printed together.
    ///     // You will NOT see any interleaving.
    ///     handles.push(thread::spawn(move|| {
    ///         println!("before wait");
    ///         c.wait();
    ///         println!("after wait");
    ///     }));
    /// }
    /// // Wait for other threads to finish.
    /// for handle in handles {
    ///     handle.join().unwrap();
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn wait(&self) -> BarrierWaitResult {
        let mut lock = self.lock.lock().unwrap();
        let local_gen = lock.generation_id;
        lock.count += 1;
        if lock.count < self.num_threads {
            // We need a while loop to guard against spurious wakeups.
            // http://en.wikipedia.org/wiki/Spurious_wakeup
            while local_gen == lock.generation_id &&
                  lock.count < self.num_threads {
                lock = self.cvar.wait(lock).unwrap();
            }
            BarrierWaitResult(false)
        } else {
            lock.count = 0;
            lock.generation_id += 1;
            self.cvar.notify_all();
            BarrierWaitResult(true)
        }
    }
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for BarrierWaitResult {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("BarrierWaitResult")
            .field("is_leader", &self.is_leader())
            .finish()
    }
}

impl BarrierWaitResult {
    /// Returns whether this thread from [`wait`] is the "leader thread".
    ///
    /// Only one thread will have `true` returned from their result, all other
    /// threads will have `false` returned.
    ///
    /// [`wait`]: struct.Barrier.html#method.wait
    ///
    /// # Examples
    ///
    /// ```
    /// use std::sync::Barrier;
    ///
    /// let barrier = Barrier::new(1);
    /// let barrier_wait_result = barrier.wait();
    /// println!("{:?}", barrier_wait_result.is_leader());
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn is_leader(&self) -> bool { self.0 }
}

#[cfg(test)]
mod tests {
    use sync::{Arc, Barrier};
    use sync::mpsc::{channel, TryRecvError};
    use thread;

    #[test]
    #[cfg_attr(target_os = "emscripten", ignore)]
    fn test_barrier() {
        const N: usize = 10;

        let barrier = Arc::new(Barrier::new(N));
        let (tx, rx) = channel();

        for _ in 0..N - 1 {
            let c = barrier.clone();
            let tx = tx.clone();
            thread::spawn(move|| {
                tx.send(c.wait().is_leader()).unwrap();
            });
        }

        // At this point, all spawned threads should be blocked,
        // so we shouldn't get anything from the port
        assert!(match rx.try_recv() {
            Err(TryRecvError::Empty) => true,
            _ => false,
        });

        let mut leader_found = barrier.wait().is_leader();

        // Now, the barrier is cleared and we should get data.
        for _ in 0..N - 1 {
            if rx.recv().unwrap() {
                assert!(!leader_found);
                leader_found = true;
            }
        }
        assert!(leader_found);
    }
}
<commit_msg>Auto merge of #43588 - dns2utf8:wrapping_add, r=sfackler<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use fmt;
use sync::{Mutex, Condvar};

/// A barrier enables multiple threads to synchronize the beginning
/// of some computation.
///
/// # Examples
///
/// ```
/// use std::sync::{Arc, Barrier};
/// use std::thread;
///
/// let mut handles = Vec::with_capacity(10);
/// let barrier = Arc::new(Barrier::new(10));
/// for _ in 0..10 {
///     let c = barrier.clone();
///     // The same messages will be printed together.
///     // You will NOT see any interleaving.
///     handles.push(thread::spawn(move|| {
///         println!("before wait");
///         c.wait();
///         println!("after wait");
///     }));
/// }
/// // Wait for other threads to finish.
/// for handle in handles {
///     handle.join().unwrap();
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Barrier {
    lock: Mutex<BarrierState>,
    cvar: Condvar,
    num_threads: usize,
}

// The inner state of a double barrier
struct BarrierState {
    count: usize,
    generation_id: usize,
}

/// A `BarrierWaitResult` is returned by [`wait`] when all threads in the [`Barrier`]
/// have rendezvoused.
///
/// [`wait`]: struct.Barrier.html#method.wait
/// [`Barrier`]: struct.Barrier.html
///
/// # Examples
///
/// ```
/// use std::sync::Barrier;
///
/// let barrier = Barrier::new(1);
/// let barrier_wait_result = barrier.wait();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct BarrierWaitResult(bool);

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Barrier {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Barrier { .. }")
    }
}

impl Barrier {
    /// Creates a new barrier that can block a given number of threads.
    ///
    /// A barrier will block `n`-1 threads which call [`wait`] and then wake up
    /// all threads at once when the `n`th thread calls [`wait`].
    ///
    /// [`wait`]: #method.wait
    ///
    /// # Examples
    ///
    /// ```
    /// use std::sync::Barrier;
    ///
    /// let barrier = Barrier::new(10);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new(n: usize) -> Barrier {
        Barrier {
            lock: Mutex::new(BarrierState {
                count: 0,
                generation_id: 0,
            }),
            cvar: Condvar::new(),
            num_threads: n,
        }
    }

    /// Blocks the current thread until all threads have rendezvoused here.
    ///
    /// Barriers are re-usable after all threads have rendezvoused once, and can
    /// be used continuously.
    ///
    /// A single (arbitrary) thread will receive a [`BarrierWaitResult`] that
    /// returns `true` from [`is_leader`] when returning from this function, and
    /// all other threads will receive a result that will return `false` from
    /// [`is_leader`].
    ///
    /// [`BarrierWaitResult`]: struct.BarrierWaitResult.html
    /// [`is_leader`]: struct.BarrierWaitResult.html#method.is_leader
    ///
    /// # Examples
    ///
    /// ```
    /// use std::sync::{Arc, Barrier};
    /// use std::thread;
    ///
    /// let mut handles = Vec::with_capacity(10);
    /// let barrier = Arc::new(Barrier::new(10));
    /// for _ in 0..10 {
    ///     let c = barrier.clone();
    ///     // The same messages will be printed together.
    ///     // You will NOT see any interleaving.
    ///     handles.push(thread::spawn(move|| {
    ///         println!("before wait");
    ///         c.wait();
    ///         println!("after wait");
    ///     }));
    /// }
    /// // Wait for other threads to finish.
    /// for handle in handles {
    ///     handle.join().unwrap();
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn wait(&self) -> BarrierWaitResult {
        let mut lock = self.lock.lock().unwrap();
        let local_gen = lock.generation_id;
        lock.count += 1;
        if lock.count < self.num_threads {
            // We need a while loop to guard against spurious wakeups.
            // http://en.wikipedia.org/wiki/Spurious_wakeup
            while local_gen == lock.generation_id &&
                  lock.count < self.num_threads {
                lock = self.cvar.wait(lock).unwrap();
            }
            BarrierWaitResult(false)
        } else {
            lock.count = 0;
            lock.generation_id = lock.generation_id.wrapping_add(1);
            self.cvar.notify_all();
            BarrierWaitResult(true)
        }
    }
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for BarrierWaitResult {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("BarrierWaitResult")
            .field("is_leader", &self.is_leader())
            .finish()
    }
}

impl BarrierWaitResult {
    /// Returns whether this thread from [`wait`] is the "leader thread".
    ///
    /// Only one thread will have `true` returned from their result, all other
    /// threads will have `false` returned.
    ///
    /// [`wait`]: struct.Barrier.html#method.wait
    ///
    /// # Examples
    ///
    /// ```
    /// use std::sync::Barrier;
    ///
    /// let barrier = Barrier::new(1);
    /// let barrier_wait_result = barrier.wait();
    /// println!("{:?}", barrier_wait_result.is_leader());
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn is_leader(&self) -> bool { self.0 }
}

#[cfg(test)]
mod tests {
    use sync::{Arc, Barrier};
    use sync::mpsc::{channel, TryRecvError};
    use thread;

    #[test]
    #[cfg_attr(target_os = "emscripten", ignore)]
    fn test_barrier() {
        const N: usize = 10;

        let barrier = Arc::new(Barrier::new(N));
        let (tx, rx) = channel();

        for _ in 0..N - 1 {
            let c = barrier.clone();
            let tx = tx.clone();
            thread::spawn(move|| {
                tx.send(c.wait().is_leader()).unwrap();
            });
        }

        // At this point, all spawned threads should be blocked,
        // so we shouldn't get anything from the port
        assert!(match rx.try_recv() {
            Err(TryRecvError::Empty) => true,
            _ => false,
        });

        let mut leader_found = barrier.wait().is_leader();

        // Now, the barrier is cleared and we should get data.
        for _ in 0..N - 1 {
            if rx.recv().unwrap() {
                assert!(!leader_found);
                leader_found = true;
            }
        }
        assert!(leader_found);
    }
}
<|endoftext|>


<commit_before><commit_msg>Day7_2 construct<commit_after><|endoftext|>


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

#![deny(warnings)]

extern crate build_helper;
extern crate gcc;

use std::env;
use std::path::PathBuf;
use std::process::Command;
use build_helper::run;

fn main() {
    println!("cargo:rustc-cfg=cargobuild");
    println!("cargo:rerun-if-changed=build.rs");

    let target = env::var("TARGET").expect("TARGET was not set");
    let host = env::var("HOST").expect("HOST was not set");
    let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let src_dir = env::current_dir().unwrap();

    // FIXME: This is a hack to support building targets that don't
    // support jemalloc alongside hosts that do. The jemalloc build is
    // controlled by a feature of the std crate, and if that feature
    // changes between targets, it invalidates the fingerprint of
    // std's build script (this is a cargo bug); so we must ensure
    // that the feature set used by std is the same across all
    // targets, which means we have to build the alloc_jemalloc crate
    // for targets like emscripten, even if we don't use it.
    if target.contains("rumprun") || target.contains("bitrig") || target.contains("openbsd") ||
       target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") {
        println!("cargo:rustc-cfg=dummy_jemalloc");
        return;
    }

    if let Some(jemalloc) = env::var_os("JEMALLOC_OVERRIDE") {
        let jemalloc = PathBuf::from(jemalloc);
        println!("cargo:rustc-link-search=native={}",
                 jemalloc.parent().unwrap().display());
        let stem = jemalloc.file_stem().unwrap().to_str().unwrap();
        let name = jemalloc.file_name().unwrap().to_str().unwrap();
        let kind = if name.ends_with(".a") {
            "static"
        } else {
            "dylib"
        };
        println!("cargo:rustc-link-lib={}={}", kind, &stem[3..]);
        return;
    }

    let compiler = gcc::Config::new().get_compiler();
    // only msvc returns None for ar so unwrap is okay
    let ar = build_helper::cc2ar(compiler.path(), &target).unwrap();
    let cflags = compiler.args()
        .iter()
        .map(|s| s.to_str().unwrap())
        .collect::<Vec<_>>()
        .join(" ");

    let mut stack = src_dir.join("../jemalloc")
        .read_dir()
        .unwrap()
        .map(|e| e.unwrap())
        .collect::<Vec<_>>();
    while let Some(entry) = stack.pop() {
        let path = entry.path();
        if entry.file_type().unwrap().is_dir() {
            stack.extend(path.read_dir().unwrap().map(|e| e.unwrap()));
        } else {
            println!("cargo:rerun-if-changed={}", path.display());
        }
    }

    let mut cmd = Command::new("sh");
    cmd.arg(src_dir.join("../jemalloc/configure")
                   .to_str()
                   .unwrap()
                   .replace("C:\\", "/c/")
                   .replace("\\", "/"))
       .current_dir(&build_dir)
       .env("CC", compiler.path())
       .env("EXTRA_CFLAGS", cflags.clone())
       // jemalloc generates Makefile deps using GCC's "-MM" flag. This means
       // that GCC will run the preprocessor, and only the preprocessor, over
       // jemalloc's source files. If we don't specify CPPFLAGS, then at least
       // on ARM that step fails with a "Missing implementation for 32-bit
       // atomic operations" error. This is because no "-march" flag will be
       // passed to GCC, and then GCC won't define the
       // "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" macro that jemalloc needs to
       // select an atomic operation implementation.
       .env("CPPFLAGS", cflags.clone())
       .env("AR", &ar)
       .env("RANLIB", format!("{} s", ar.display()));

    if target.contains("windows") {
        // A bit of history here, this used to be --enable-lazy-lock added in
        // #14006 which was filed with jemalloc in jemalloc/jemalloc#83 which
        // was also reported to MinGW:
        //
        //  http://sourceforge.net/p/mingw-w64/bugs/395/
        //
        // When updating jemalloc to 4.0, however, it was found that binaries
        // would exit with the status code STATUS_RESOURCE_NOT_OWNED indicating
        // that a thread was unlocking a mutex it never locked. Disabling this
        // "lazy lock" option seems to fix the issue, but it was enabled by
        // default for MinGW targets in 13473c7 for jemalloc.
        //
        // As a result of all that, force disabling lazy lock on Windows, and
        // after reading some code it at least *appears* that the initialization
        // of mutexes is otherwise ok in jemalloc, so shouldn't cause problems
        // hopefully...
        //
        // tl;dr: make windows behave like other platforms by disabling lazy
        //        locking, but requires passing an option due to a historical
        //        default with jemalloc.
        cmd.arg("--disable-lazy-lock");
    } else if target.contains("ios") {
        cmd.arg("--disable-tls");
    } else if target.contains("android") {
        // We force android to have prefixed symbols because apparently
        // replacement of the libc allocator doesn't quite work. When this was
        // tested (unprefixed symbols), it was found that the `realpath`
        // function in libc would allocate with libc malloc (not jemalloc
        // malloc), and then the standard library would free with jemalloc free,
        // causing a segfault.
        //
        // If the test suite passes, however, without symbol prefixes then we
        // should be good to go!
        cmd.arg("--with-jemalloc-prefix=je_");
        cmd.arg("--disable-tls");
    } else if target.contains("dragonfly") {
        cmd.arg("--with-jemalloc-prefix=je_");
    }

    if cfg!(feature = "debug-jemalloc") {
        cmd.arg("--enable-debug");
    }

    // Turn off broken quarantine (see jemalloc/jemalloc#161)
    cmd.arg("--disable-fill");
    cmd.arg(format!("--host={}", build_helper::gnu_target(&target)));
    cmd.arg(format!("--build={}", build_helper::gnu_target(&host)));

    run(&mut cmd);
    run(Command::new("make")
        .current_dir(&build_dir)
        .arg("build_lib_static")
        .arg("-j")
        .arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")));

    if target.contains("windows") {
        println!("cargo:rustc-link-lib=static=jemalloc");
    } else {
        println!("cargo:rustc-link-lib=static=jemalloc_pic");
    }
    println!("cargo:rustc-link-search=native={}/lib", build_dir.display());
    if target.contains("android") {
        println!("cargo:rustc-link-lib=gcc");
    } else if !target.contains("windows") && !target.contains("musl") {
        println!("cargo:rustc-link-lib=pthread");
    }
}
<commit_msg>Auto merge of #38111 - japaric:jemalloc, r=alexcrichton<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(warnings)]

extern crate build_helper;
extern crate gcc;

use std::env;
use std::path::PathBuf;
use std::process::Command;
use build_helper::run;

fn main() {
    println!("cargo:rustc-cfg=cargobuild");
    println!("cargo:rerun-if-changed=build.rs");

    let target = env::var("TARGET").expect("TARGET was not set");
    let host = env::var("HOST").expect("HOST was not set");
    let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let src_dir = env::current_dir().unwrap();

    // FIXME: This is a hack to support building targets that don't
    // support jemalloc alongside hosts that do. The jemalloc build is
    // controlled by a feature of the std crate, and if that feature
    // changes between targets, it invalidates the fingerprint of
    // std's build script (this is a cargo bug); so we must ensure
    // that the feature set used by std is the same across all
    // targets, which means we have to build the alloc_jemalloc crate
    // for targets like emscripten, even if we don't use it.
    if target.contains("rumprun") || target.contains("bitrig") || target.contains("openbsd") ||
       target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") {
        println!("cargo:rustc-cfg=dummy_jemalloc");
        return;
    }

    if let Some(jemalloc) = env::var_os("JEMALLOC_OVERRIDE") {
        let jemalloc = PathBuf::from(jemalloc);
        println!("cargo:rustc-link-search=native={}",
                 jemalloc.parent().unwrap().display());
        let stem = jemalloc.file_stem().unwrap().to_str().unwrap();
        let name = jemalloc.file_name().unwrap().to_str().unwrap();
        let kind = if name.ends_with(".a") {
            "static"
        } else {
            "dylib"
        };
        println!("cargo:rustc-link-lib={}={}", kind, &stem[3..]);
        return;
    }

    let compiler = gcc::Config::new().get_compiler();
    // only msvc returns None for ar so unwrap is okay
    let ar = build_helper::cc2ar(compiler.path(), &target).unwrap();
    let cflags = compiler.args()
        .iter()
        .map(|s| s.to_str().unwrap())
        .collect::<Vec<_>>()
        .join(" ");

    let mut stack = src_dir.join("../jemalloc")
        .read_dir()
        .unwrap()
        .map(|e| e.unwrap())
        .filter(|e| &*e.file_name() != ".git")
        .collect::<Vec<_>>();
    while let Some(entry) = stack.pop() {
        let path = entry.path();
        if entry.file_type().unwrap().is_dir() {
            stack.extend(path.read_dir().unwrap().map(|e| e.unwrap()));
        } else {
            println!("cargo:rerun-if-changed={}", path.display());
        }
    }

    let mut cmd = Command::new("sh");
    cmd.arg(src_dir.join("../jemalloc/configure")
                   .to_str()
                   .unwrap()
                   .replace("C:\\", "/c/")
                   .replace("\\", "/"))
       .current_dir(&build_dir)
       .env("CC", compiler.path())
       .env("EXTRA_CFLAGS", cflags.clone())
       // jemalloc generates Makefile deps using GCC's "-MM" flag. This means
       // that GCC will run the preprocessor, and only the preprocessor, over
       // jemalloc's source files. If we don't specify CPPFLAGS, then at least
       // on ARM that step fails with a "Missing implementation for 32-bit
       // atomic operations" error. This is because no "-march" flag will be
       // passed to GCC, and then GCC won't define the
       // "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" macro that jemalloc needs to
       // select an atomic operation implementation.
       .env("CPPFLAGS", cflags.clone())
       .env("AR", &ar)
       .env("RANLIB", format!("{} s", ar.display()));

    if target.contains("windows") {
        // A bit of history here, this used to be --enable-lazy-lock added in
        // #14006 which was filed with jemalloc in jemalloc/jemalloc#83 which
        // was also reported to MinGW:
        //
        //  http://sourceforge.net/p/mingw-w64/bugs/395/
        //
        // When updating jemalloc to 4.0, however, it was found that binaries
        // would exit with the status code STATUS_RESOURCE_NOT_OWNED indicating
        // that a thread was unlocking a mutex it never locked. Disabling this
        // "lazy lock" option seems to fix the issue, but it was enabled by
        // default for MinGW targets in 13473c7 for jemalloc.
        //
        // As a result of all that, force disabling lazy lock on Windows, and
        // after reading some code it at least *appears* that the initialization
        // of mutexes is otherwise ok in jemalloc, so shouldn't cause problems
        // hopefully...
        //
        // tl;dr: make windows behave like other platforms by disabling lazy
        //        locking, but requires passing an option due to a historical
        //        default with jemalloc.
        cmd.arg("--disable-lazy-lock");
    } else if target.contains("ios") {
        cmd.arg("--disable-tls");
    } else if target.contains("android") {
        // We force android to have prefixed symbols because apparently
        // replacement of the libc allocator doesn't quite work. When this was
        // tested (unprefixed symbols), it was found that the `realpath`
        // function in libc would allocate with libc malloc (not jemalloc
        // malloc), and then the standard library would free with jemalloc free,
        // causing a segfault.
        //
        // If the test suite passes, however, without symbol prefixes then we
        // should be good to go!
        cmd.arg("--with-jemalloc-prefix=je_");
        cmd.arg("--disable-tls");
    } else if target.contains("dragonfly") {
        cmd.arg("--with-jemalloc-prefix=je_");
    }

    if cfg!(feature = "debug-jemalloc") {
        cmd.arg("--enable-debug");
    }

    // Turn off broken quarantine (see jemalloc/jemalloc#161)
    cmd.arg("--disable-fill");
    cmd.arg(format!("--host={}", build_helper::gnu_target(&target)));
    cmd.arg(format!("--build={}", build_helper::gnu_target(&host)));

    run(&mut cmd);
    run(Command::new("make")
        .current_dir(&build_dir)
        .arg("build_lib_static")
        .arg("-j")
        .arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")));

    if target.contains("windows") {
        println!("cargo:rustc-link-lib=static=jemalloc");
    } else {
        println!("cargo:rustc-link-lib=static=jemalloc_pic");
    }
    println!("cargo:rustc-link-search=native={}/lib", build_dir.display());
    if target.contains("android") {
        println!("cargo:rustc-link-lib=gcc");
    } else if !target.contains("windows") && !target.contains("musl") {
        println!("cargo:rustc-link-lib=pthread");
    }
}
<|endoftext|>


<commit_before><commit_msg>Review remarks from dulanov. Changed usage format! to to_string()<commit_after><|endoftext|>


<commit_before><commit_msg>Formatting<commit_after><|endoftext|>


<commit_before><commit_msg>Fire start of drawing/end of drawing interrupts regardless of whether or not drawing is enabled<commit_after><|endoftext|>


<commit_before><commit_msg>Rollup merge of #90115 - samlich:test-issue-78561, r=oli-obk<commit_after>// check-pass
#![feature(type_alias_impl_trait)]

pub trait Trait {
    type A;

    fn f() -> Self::A;
}

pub trait Tr2<'a, 'b> {}

pub struct A<T>(T);
pub trait Tr {
    type B;
}

impl<'a, 'b, T: Tr<B = dyn Tr2<'a, 'b>>> Trait for A<T> {
    type A = impl core::fmt::Debug;

    fn f() -> Self::A {}
}

fn main() {}
<|endoftext|>


<commit_before><commit_msg>added simple struct example<commit_after>struct Rectangle {
    width: i32,
    height: i32,
}

impl Rectangle {
    fn new(w: i32, h: i32) -> Rectangle {
        Rectangle { width: w, height: h }
    }

    fn area(&self) -> f32 {
        return (self.width * self.height) as f32;
    }
}

fn main() {
    let r = Rectangle::new(3, 2);

    println!("{}", r.area());
}<|endoftext|>


<commit_before><commit_msg>example of implementing traits for family of types<commit_after>use std::io::{self, Write};

/// Trait for values to which you can send HTML.
trait WriteHtml {
    fn write_html(&mut self, &HtmlDocument) -> io::Result<()>;
}

/// You can write HTML to any std::io writer.
impl<W: Write> WriteHtml for W {
    fn write_html(&mut self, html: &HtmlDocument) -> io::Result<()> {
        // code goes here...
        Ok(())
    }
}
<|endoftext|>


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

//! Provider for the `implied_outlives_bounds` query.
//! Do not call this query directory. See [`rustc::traits::query::implied_outlives_bounds`].

use rustc::infer::InferCtxt;
use rustc::infer::canonical::{self, Canonical};
use rustc::traits::{TraitEngine, TraitEngineExt};
use rustc::traits::query::outlives_bounds::OutlivesBound;
use rustc::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::outlives::Component;
use rustc::ty::query::Providers;
use rustc::ty::wf;
use syntax::ast::DUMMY_NODE_ID;
use syntax::source_map::DUMMY_SP;
use rustc::traits::FulfillmentContext;

use rustc_data_structures::sync::Lrc;

crate fn provide(p: &mut Providers) {
    *p = Providers {
        implied_outlives_bounds,
        ..*p
    };
}

fn implied_outlives_bounds<'tcx>(
    tcx: TyCtxt<'_, 'tcx, 'tcx>,
    goal: CanonicalTyGoal<'tcx>,
) -> Result<
        Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>>,
        NoSolution,
> {
    tcx.infer_ctxt()
       .enter_canonical_trait_query(&goal, |infcx, _fulfill_cx, key| {
           let (param_env, ty) = key.into_parts();
           compute_implied_outlives_bounds(&infcx, param_env, ty)
       })
}

fn compute_implied_outlives_bounds<'tcx>(
    infcx: &InferCtxt<'_, '_, 'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    ty: Ty<'tcx>
) -> Fallible<Vec<OutlivesBound<'tcx>>> {
    let tcx = infcx.tcx;

    // Sometimes when we ask what it takes for T: WF, we get back that
    // U: WF is required; in that case, we push U onto this stack and
    // process it next. Currently (at least) these resulting
    // predicates are always guaranteed to be a subset of the original
    // type, so we need not fear non-termination.
    let mut wf_types = vec![ty];

    let mut implied_bounds = vec![];

    let mut fulfill_cx = FulfillmentContext::new();

    while let Some(ty) = wf_types.pop() {
        // Compute the obligations for `ty` to be well-formed. If `ty` is
        // an unresolved inference variable, just substituted an empty set
        // -- because the return type here is going to be things we *add*
        // to the environment, it's always ok for this set to be smaller
        // than the ultimate set. (Note: normally there won't be
        // unresolved inference variables here anyway, but there might be
        // during typeck under some circumstances.)
        let obligations =
            wf::obligations(infcx, param_env, DUMMY_NODE_ID, ty, DUMMY_SP).unwrap_or(vec![]);

        // NB: All of these predicates *ought* to be easily proven
        // true. In fact, their correctness is (mostly) implied by
        // other parts of the program. However, in #42552, we had
        // an annoying scenario where:
        //
        // - Some `T::Foo` gets normalized, resulting in a
        //   variable `_1` and a `T: Trait<Foo=_1>` constraint
        //   (not sure why it couldn't immediately get
        //   solved). This result of `_1` got cached.
        // - These obligations were dropped on the floor here,
        //   rather than being registered.
        // - Then later we would get a request to normalize
        //   `T::Foo` which would result in `_1` being used from
        //   the cache, but hence without the `T: Trait<Foo=_1>`
        //   constraint. As a result, `_1` never gets resolved,
        //   and we get an ICE (in dropck).
        //
        // Therefore, we register any predicates involving
        // inference variables. We restrict ourselves to those
        // involving inference variables both for efficiency and
        // to avoids duplicate errors that otherwise show up.
        fulfill_cx.register_predicate_obligations(
            infcx,
            obligations
                .iter()
                .filter(|o| o.predicate.has_infer_types())
                .cloned(),
        );

        // From the full set of obligations, just filter down to the
        // region relationships.
        implied_bounds.extend(obligations.into_iter().flat_map(|obligation| {
            assert!(!obligation.has_escaping_regions());
            match obligation.predicate {
                ty::Predicate::Trait(..) |
                ty::Predicate::Subtype(..) |
                ty::Predicate::Projection(..) |
                ty::Predicate::ClosureKind(..) |
                ty::Predicate::ObjectSafe(..) |
                ty::Predicate::ConstEvaluatable(..) => vec![],

                ty::Predicate::WellFormed(subty) => {
                    wf_types.push(subty);
                    vec![]
                }

                ty::Predicate::RegionOutlives(ref data) => match data.no_late_bound_regions() {
                    None => vec![],
                    Some(ty::OutlivesPredicate(r_a, r_b)) => {
                        vec![OutlivesBound::RegionSubRegion(r_b, r_a)]
                    }
                },

                ty::Predicate::TypeOutlives(ref data) => match data.no_late_bound_regions() {
                    None => vec![],
                    Some(ty::OutlivesPredicate(ty_a, r_b)) => {
                        let ty_a = infcx.resolve_type_vars_if_possible(&ty_a);
                        let components = tcx.outlives_components(ty_a);
                        implied_bounds_from_components(r_b, components)
                    }
                },
            }
        }));
    }

    // Ensure that those obligations that we had to solve
    // get solved *here*.
    match fulfill_cx.select_all_or_error(infcx) {
        Ok(()) => Ok(implied_bounds),
        Err(_) => Err(NoSolution),
    }
}

/// When we have an implied bound that `T: 'a`, we can further break
/// this down to determine what relationships would have to hold for
/// `T: 'a` to hold. We get to assume that the caller has validated
/// those relationships.
fn implied_bounds_from_components(
    sub_region: ty::Region<'tcx>,
    sup_components: Vec<Component<'tcx>>,
) -> Vec<OutlivesBound<'tcx>> {
    sup_components
        .into_iter()
        .flat_map(|component| {
            match component {
                Component::Region(r) =>
                    vec![OutlivesBound::RegionSubRegion(sub_region, r)],
                Component::Param(p) =>
                    vec![OutlivesBound::RegionSubParam(sub_region, p)],
                Component::Projection(p) =>
                    vec![OutlivesBound::RegionSubProjection(sub_region, p)],
                Component::EscapingProjection(_) =>
                // If the projection has escaping regions, don't
                // try to infer any implied bounds even for its
                // free components. This is conservative, because
                // the caller will still have to prove that those
                // free components outlive `sub_region`. But the
                // idea is that the WAY that the caller proves
                // that may change in the future and we want to
                // give ourselves room to get smarter here.
                    vec![],
                Component::UnresolvedInferenceVariable(..) =>
                    vec![],
            }
        })
        .collect()
}
<commit_msg>Change a flat_map with 0/1-element vecs to a filter_map<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Provider for the `implied_outlives_bounds` query.
//! Do not call this query directory. See [`rustc::traits::query::implied_outlives_bounds`].

use rustc::infer::InferCtxt;
use rustc::infer::canonical::{self, Canonical};
use rustc::traits::{TraitEngine, TraitEngineExt};
use rustc::traits::query::outlives_bounds::OutlivesBound;
use rustc::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::outlives::Component;
use rustc::ty::query::Providers;
use rustc::ty::wf;
use syntax::ast::DUMMY_NODE_ID;
use syntax::source_map::DUMMY_SP;
use rustc::traits::FulfillmentContext;

use rustc_data_structures::sync::Lrc;

crate fn provide(p: &mut Providers) {
    *p = Providers {
        implied_outlives_bounds,
        ..*p
    };
}

fn implied_outlives_bounds<'tcx>(
    tcx: TyCtxt<'_, 'tcx, 'tcx>,
    goal: CanonicalTyGoal<'tcx>,
) -> Result<
        Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>>,
        NoSolution,
> {
    tcx.infer_ctxt()
       .enter_canonical_trait_query(&goal, |infcx, _fulfill_cx, key| {
           let (param_env, ty) = key.into_parts();
           compute_implied_outlives_bounds(&infcx, param_env, ty)
       })
}

fn compute_implied_outlives_bounds<'tcx>(
    infcx: &InferCtxt<'_, '_, 'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    ty: Ty<'tcx>
) -> Fallible<Vec<OutlivesBound<'tcx>>> {
    let tcx = infcx.tcx;

    // Sometimes when we ask what it takes for T: WF, we get back that
    // U: WF is required; in that case, we push U onto this stack and
    // process it next. Currently (at least) these resulting
    // predicates are always guaranteed to be a subset of the original
    // type, so we need not fear non-termination.
    let mut wf_types = vec![ty];

    let mut implied_bounds = vec![];

    let mut fulfill_cx = FulfillmentContext::new();

    while let Some(ty) = wf_types.pop() {
        // Compute the obligations for `ty` to be well-formed. If `ty` is
        // an unresolved inference variable, just substituted an empty set
        // -- because the return type here is going to be things we *add*
        // to the environment, it's always ok for this set to be smaller
        // than the ultimate set. (Note: normally there won't be
        // unresolved inference variables here anyway, but there might be
        // during typeck under some circumstances.)
        let obligations =
            wf::obligations(infcx, param_env, DUMMY_NODE_ID, ty, DUMMY_SP).unwrap_or(vec![]);

        // NB: All of these predicates *ought* to be easily proven
        // true. In fact, their correctness is (mostly) implied by
        // other parts of the program. However, in #42552, we had
        // an annoying scenario where:
        //
        // - Some `T::Foo` gets normalized, resulting in a
        //   variable `_1` and a `T: Trait<Foo=_1>` constraint
        //   (not sure why it couldn't immediately get
        //   solved). This result of `_1` got cached.
        // - These obligations were dropped on the floor here,
        //   rather than being registered.
        // - Then later we would get a request to normalize
        //   `T::Foo` which would result in `_1` being used from
        //   the cache, but hence without the `T: Trait<Foo=_1>`
        //   constraint. As a result, `_1` never gets resolved,
        //   and we get an ICE (in dropck).
        //
        // Therefore, we register any predicates involving
        // inference variables. We restrict ourselves to those
        // involving inference variables both for efficiency and
        // to avoids duplicate errors that otherwise show up.
        fulfill_cx.register_predicate_obligations(
            infcx,
            obligations
                .iter()
                .filter(|o| o.predicate.has_infer_types())
                .cloned(),
        );

        // From the full set of obligations, just filter down to the
        // region relationships.
        implied_bounds.extend(obligations.into_iter().flat_map(|obligation| {
            assert!(!obligation.has_escaping_regions());
            match obligation.predicate {
                ty::Predicate::Trait(..) |
                ty::Predicate::Subtype(..) |
                ty::Predicate::Projection(..) |
                ty::Predicate::ClosureKind(..) |
                ty::Predicate::ObjectSafe(..) |
                ty::Predicate::ConstEvaluatable(..) => vec![],

                ty::Predicate::WellFormed(subty) => {
                    wf_types.push(subty);
                    vec![]
                }

                ty::Predicate::RegionOutlives(ref data) => match data.no_late_bound_regions() {
                    None => vec![],
                    Some(ty::OutlivesPredicate(r_a, r_b)) => {
                        vec![OutlivesBound::RegionSubRegion(r_b, r_a)]
                    }
                },

                ty::Predicate::TypeOutlives(ref data) => match data.no_late_bound_regions() {
                    None => vec![],
                    Some(ty::OutlivesPredicate(ty_a, r_b)) => {
                        let ty_a = infcx.resolve_type_vars_if_possible(&ty_a);
                        let components = tcx.outlives_components(ty_a);
                        implied_bounds_from_components(r_b, components)
                    }
                },
            }
        }));
    }

    // Ensure that those obligations that we had to solve
    // get solved *here*.
    match fulfill_cx.select_all_or_error(infcx) {
        Ok(()) => Ok(implied_bounds),
        Err(_) => Err(NoSolution),
    }
}

/// When we have an implied bound that `T: 'a`, we can further break
/// this down to determine what relationships would have to hold for
/// `T: 'a` to hold. We get to assume that the caller has validated
/// those relationships.
fn implied_bounds_from_components(
    sub_region: ty::Region<'tcx>,
    sup_components: Vec<Component<'tcx>>,
) -> Vec<OutlivesBound<'tcx>> {
    sup_components
        .into_iter()
        .filter_map(|component| {
            match component {
                Component::Region(r) =>
                    Some(OutlivesBound::RegionSubRegion(sub_region, r)),
                Component::Param(p) =>
                    Some(OutlivesBound::RegionSubParam(sub_region, p)),
                Component::Projection(p) =>
                    Some(OutlivesBound::RegionSubProjection(sub_region, p)),
                Component::EscapingProjection(_) =>
                // If the projection has escaping regions, don't
                // try to infer any implied bounds even for its
                // free components. This is conservative, because
                // the caller will still have to prove that those
                // free components outlive `sub_region`. But the
                // idea is that the WAY that the caller proves
                // that may change in the future and we want to
                // give ourselves room to get smarter here.
                    None,
                Component::UnresolvedInferenceVariable(..) =>
                    None,
            }
        })
        .collect()
}
<|endoftext|>


<commit_before><commit_msg>Rollup merge of #72008 - lcnr:patch-3, r=varkor<commit_after>// check-pass
#![allow(incomplete_features)]
#![feature(const_generics)]

struct Const<const N: usize>;
trait Foo<const N: usize> {}

impl<const N: usize> Foo<N> for Const<N> {}

fn foo_impl(_: impl Foo<3>) {}

fn foo_explicit<T: Foo<3>>(_: T) {}

fn foo_where<T>(_: T)
where
    T: Foo<3>,
{
}

fn main() {
    foo_impl(Const);
    foo_impl(Const::<3>);

    foo_explicit(Const);
    foo_explicit(Const::<3>);

    foo_where(Const);
    foo_where(Const::<3>);
}
<|endoftext|>


<commit_before><commit_msg>Replaced extern crate with use (thanks, @steveklabnik)<commit_after><|endoftext|>


<commit_before><commit_msg>added clone benchmark<commit_after>#![feature(test)]

extern crate abomonation;
extern crate test;

use abomonation::*;
use test::Bencher;

#[bench] fn empty_e_d(bencher: &mut Bencher) { _bench_e_d(bencher, vec![(); 1024]); }
#[bench] fn empty_cln(bencher: &mut Bencher) { _bench_cln(bencher, vec![(); 1024]); }

#[bench] fn u64_e_d(bencher: &mut Bencher) { _bench_e_d(bencher, vec![0u64; 1024]); }
#[bench] fn u64_cln(bencher: &mut Bencher) { _bench_cln(bencher, vec![0u64; 1024]); }

#[bench] fn u8_u64_e_d(bencher: &mut Bencher) { _bench_e_d(bencher, vec![(0u8, 0u64); 512]); }
#[bench] fn u8_u64_cln(bencher: &mut Bencher) { _bench_cln(bencher, vec![(0u8, 0u64); 512]); }

#[bench] fn string10_e_d(bencher: &mut Bencher) { _bench_e_d(bencher, vec![format!("grawwwwrr!"); 1024]); }
#[bench] fn string10_cln(bencher: &mut Bencher) { _bench_cln(bencher, vec![format!("grawwwwrr!"); 1024]); }

#[bench] fn string20_e_d(bencher: &mut Bencher) { _bench_e_d(bencher, vec![format!("grawwwwrr!!!!!!!!!!!"); 512]); }
#[bench] fn string20_cln(bencher: &mut Bencher) { _bench_cln(bencher, vec![format!("grawwwwrr!!!!!!!!!!!"); 512]); }

#[bench] fn vec_u_s_e_d(bencher: &mut Bencher) { _bench_e_d(bencher, vec![vec![(0u64, format!("grawwwwrr!")); 32]; 32]); }
#[bench] fn vec_u_s_cln(bencher: &mut Bencher) { _bench_cln(bencher, vec![vec![(0u64, format!("grawwwwrr!")); 32]; 32]); }

#[bench] fn vec_u_vn_s_e_d(bencher: &mut Bencher) { _bench_e_d(bencher, vec![vec![(0u64, vec![(); 1 << 40], format!("grawwwwrr!")); 32]; 32]); }
#[bench] fn vec_u_vn_s_cln(bencher: &mut Bencher) { _bench_cln(bencher, vec![vec![(0u64, vec![(); 1 << 40], format!("grawwwwrr!")); 32]; 32]); }

fn _bench_e_d<T: Abomonation>(bencher: &mut Bencher, record: T) {

    // prepare encoded data for bencher.bytes
    let mut bytes = Vec::new();
    unsafe { encode(&record, &mut bytes); }

    // repeatedly encode this many bytes
    bencher.bytes = bytes.len() as u64;
    bencher.iter(|| {
        bytes = vec![];
        unsafe { encode(&record, &mut bytes) }
        unsafe { decode::<T>(&mut bytes) }.is_some()
    });
}

fn _bench_cln<T: Abomonation+Clone>(bencher: &mut Bencher, record: T) {

    // prepare encoded data
    let mut bytes = Vec::new();
    unsafe { encode(&record, &mut bytes); }

    // repeatedly decode (and validate)
    bencher.bytes = bytes.len() as u64;
    bencher.iter(|| {
        record.clone()
    });
}
<|endoftext|>


<commit_before><commit_msg>stdin<commit_after><|endoftext|>


<commit_before><commit_msg>Use ActiveMQ whacky spellings.<commit_after><|endoftext|>


<commit_before><commit_msg>Extract function for metrics.<commit_after><|endoftext|>


<commit_before><commit_msg>Proactively change to range notation<commit_after><|endoftext|>


<commit_before><commit_msg>Add Ipv4Packet<commit_after>use std::net::Ipv4Addr;
use types::*;

/// Bitmasks for the three bit flags field in IPv4
pub mod flags {
    use types::*;

    /// A bitmask with a one in the "Reserved" position.
    pub static RESERVED: u3 = 0b100;
    /// A bitmask with a one in the "Don't fragment" position.
    pub static DF: u3 = 0b010;
    /// A bitmask with a one in the "More fragments" position.
    pub static MF: u3 = 0b001;
}

packet!(Ipv4Packet, MutIpv4Packet, 20);

impl<'a> Ipv4Packet<'a> {
    pub fn version(&self) -> u4 {
        read_offset!(self.0, 0, u8) >> 4
    }

    pub fn header_length(&self) -> u4 {
        read_offset!(self.0, 0, u8) & 0x0f
    }

    pub fn dscp(&self) -> u6 {
        read_offset!(self.0, 1, u8) >> 2
    }

    pub fn ecn(&self) -> u2 {
        read_offset!(self.0, 1, u8) & 0x03
    }

    pub fn total_length(&self) -> u16 {
        read_offset!(self.0, 2, u16, from_be)
    }

    pub fn identification(&self) -> u16 {
        read_offset!(self.0, 4, u16, from_be)
    }

    pub fn flags(&self) -> u3 {
        read_offset!(self.0, 6, u8) >> 5
    }

    pub fn dont_fragment(&self) -> bool {
        (self.flags() & flags::DF) != 0
    }

    pub fn more_fragments(&self) -> bool {
        (self.flags() & flags::MF) != 0
    }

    pub fn fragment_offset(&self) -> u13 {
        read_offset!(self.0, 6, u16, from_be) & 0x1fff
    }

    pub fn ttl(&self) -> u8 {
        read_offset!(self.0, 8, u8)
    }

    pub fn protocol(&self) -> u8 {
        read_offset!(self.0, 9, u8)
    }

    pub fn header_checksum(&self) -> u16 {
        read_offset!(self.0, 10, u16, from_be)
    }

    pub fn source(&self) -> Ipv4Addr {
        Ipv4Addr::from(read_offset!(self.0, 12, [u8; 4]))
    }

    pub fn destination(&self) -> Ipv4Addr {
        Ipv4Addr::from(read_offset!(self.0, 16, [u8; 4]))
    }
}

impl<'a> MutIpv4Packet<'a> {
    pub fn set_version(&mut self, version: u4) {
        let new_byte = (version << 4) | (read_offset!(self.0, 0, u8) & 0x0f);
        write_offset!(self.0, 0, new_byte, u8);
    }

    pub fn set_header_length(&mut self, header_length: u4) {
        let new_byte = (read_offset!(self.0, 0, u8) & 0xf0) | (header_length & 0x0f);
        write_offset!(self.0, 0, new_byte, u8);
    }

    pub fn set_dscp(&mut self, dscp: u6) {
        let new_byte = (dscp << 2) | (read_offset!(self.0, 1, u8) & 0x03);
        write_offset!(self.0, 1, new_byte, u8);
    }

    pub fn set_ecn(&mut self, ecn: u2) {
        let new_byte = (read_offset!(self.0, 1, u8) & 0xfc) | (ecn & 0x03);
        write_offset!(self.0, 1, new_byte, u8);
    }

    pub fn set_total_length(&mut self, total_length: u16) {
        write_offset!(self.0, 2, total_length, u16, to_be);
    }

    pub fn set_identification(&mut self, identification: u16) {
        write_offset!(self.0, 4, identification, u16, to_be);
    }

    pub fn set_flags(&mut self, flags: u3) {
        let new_byte = (flags << 5) | (read_offset!(self.0, 6, u8) & 0x1f);
        write_offset!(self.0, 6, new_byte, u8);
    }

    pub fn set_fragment_offset(&mut self, fragment_offset: u13) {
        let new_byte = (read_offset!(self.0, 6, u16, from_be) & 0xe000) |
            (fragment_offset & 0x1fff);
        write_offset!(self.0, 6, new_byte, u16, to_be);
    }

    pub fn set_ttl(&mut self, ttl: u8) {
        write_offset!(self.0, 8, ttl, u8);
    }

    pub fn set_protocol(&mut self, protocol: u8) {
        write_offset!(self.0, 9, protocol, u8);
    }

    pub fn set_header_checksum(&mut self, checksum: u16) {
        write_offset!(self.0, 10, checksum, u16, to_be);
    }

    pub fn set_source(&mut self, source: Ipv4Addr) {
        write_offset!(self.0, 12, source.octets(), [u8; 4]);
    }

    pub fn set_destination(&mut self, destination: Ipv4Addr) {
        write_offset!(self.0, 16, destination.octets(), [u8; 4]);
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    macro_rules! ipv4_setget_test {
        ($name:ident, $set_name:ident, $value:expr, $offset:expr, $expected:expr) => {
            setget_test!(MutIpv4Packet, $name, $set_name, $value, $offset, $expected);
        }
    }

    ipv4_setget_test!(version, set_version, 0xf, 0, [0xf0]);
    ipv4_setget_test!(header_length, set_header_length, 0xf, 0, [0x0f]);
    ipv4_setget_test!(dscp, set_dscp, 0x3f, 1, [0xfc]);
    ipv4_setget_test!(ecn, set_ecn, 0x3, 1, [0x3]);
    ipv4_setget_test!(total_length, set_total_length, 0xffbf, 2, [0xff, 0xbf]);
    ipv4_setget_test!(identification, set_identification, 0xffaf, 4, [0xff, 0xaf]);
    ipv4_setget_test!(flags, set_flags, 0b111, 6, [0xe0]);
    ipv4_setget_test!(
        fragment_offset,
        set_fragment_offset,
        0x1faf,
        6,
        [0x1f, 0xaf]
    );
    ipv4_setget_test!(ttl, set_ttl, 0xff, 8, [0xff]);
    ipv4_setget_test!(protocol, set_protocol, 0xff, 9, [0xff]);
    ipv4_setget_test!(
        header_checksum,
        set_header_checksum,
        0xfeff,
        10,
        [0xfe, 0xff]
    );
    ipv4_setget_test!(
        source,
        set_source,
        Ipv4Addr::new(192, 168, 15, 1),
        12,
        [192, 168, 15, 1]
    );
    ipv4_setget_test!(
        destination,
        set_destination,
        Ipv4Addr::new(168, 254, 99, 88),
        16,
        [168, 254, 99, 88]
    );

    #[test]
    fn getters_alternating_bits() {
        let backing_data = [0b1010_1010; 20];
        let testee = Ipv4Packet::new(&backing_data).unwrap();
        assert_eq!(0b1010, testee.version());
        assert_eq!(0b1010, testee.header_length());
        assert_eq!(0b101010, testee.dscp());
        assert_eq!(0b10, testee.ecn());
        assert_eq!(0b1010_1010_1010_1010, testee.total_length());
        assert_eq!(0b1010_1010_1010_1010, testee.identification());
        assert_eq!(0b101, testee.flags());
        assert!(!testee.dont_fragment());
        assert!(testee.more_fragments());
        assert_eq!(0b0_1010_1010_1010, testee.fragment_offset());
    }
}
<|endoftext|>


<commit_before><commit_msg>added autobahn test server<commit_after><|endoftext|>


<commit_before><commit_msg>Updates<commit_after><|endoftext|>


<commit_before><commit_msg>Add a simple Game Of Life example<commit_after>extern crate sdl2;

use sdl2::rect::{Point, Rect};
use sdl2::pixels::Color;
use sdl2::event::Event;
use sdl2::mouse::MouseButton;
use sdl2::keyboard::Keycode;
use sdl2::video::{Window, WindowContext};
use sdl2::render::{Canvas, Texture, TextureCreator};
use game_of_life::{SQUARE_SIZE, PLAYGROUND_WIDTH, PLAYGROUND_HEIGHT};

mod game_of_life {
    pub const SQUARE_SIZE: u32 = 16;
    pub const PLAYGROUND_WIDTH: u32 = 49;
    pub const PLAYGROUND_HEIGHT: u32 = 40;

    #[derive(Copy, Clone)]
    pub enum State {
        Paused,
        Playing,
    }

    pub struct GameOfLife {
        playground: [bool; (PLAYGROUND_WIDTH*PLAYGROUND_HEIGHT) as usize],
        state: State,
    }

    impl GameOfLife {
        pub fn new() -> GameOfLife {
            let mut playground = [false; (PLAYGROUND_WIDTH * PLAYGROUND_HEIGHT) as usize];

            // let's make a nice default pattern !
            for i in 1..(PLAYGROUND_HEIGHT-1) {
                playground[(1 + i* PLAYGROUND_WIDTH) as usize] = true;
                playground[((PLAYGROUND_WIDTH-2) + i* PLAYGROUND_WIDTH) as usize] = true;
            }
            for j in 2..(PLAYGROUND_WIDTH-2) {
                playground[(1*PLAYGROUND_WIDTH + j) as usize] = true;
                playground[((PLAYGROUND_HEIGHT-2)*PLAYGROUND_WIDTH + j) as usize] = true;
            }

            GameOfLife {
                playground: playground,
                state: State::Paused,
            }
        }

        pub fn get(&self, x: i32, y: i32) -> Option<bool> {
            if x >= 0 && y >= 0 &&
               (x as u32) < PLAYGROUND_WIDTH && (y as u32) < PLAYGROUND_HEIGHT {
                Some(self.playground[(x as u32 + (y as u32)* PLAYGROUND_WIDTH) as usize])
            } else {
                None
            }
        }

        pub fn get_mut<'a>(&'a mut self, x: i32, y: i32) -> Option<&'a mut bool> {
            if x >= 0 && y >= 0 &&
               (x as u32) < PLAYGROUND_WIDTH && (y as u32) < PLAYGROUND_HEIGHT {
                Some(&mut self.playground[(x as u32 + (y as u32)* PLAYGROUND_WIDTH) as usize])
            } else {
                None
            }
        }

        pub fn toggle_state(&mut self) {
            self.state = match self.state {
                State::Paused => State::Playing,
                State::Playing => State::Paused,
            }
        }

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

        pub fn update(&mut self) {
            let mut new_playground = self.playground;
            for (u, mut square) in new_playground.iter_mut().enumerate() {
                let u = u as u32;
                let x = u % PLAYGROUND_WIDTH;
                let y = u / PLAYGROUND_WIDTH;
                let mut count : u32 = 0;
                for i in -1..2 {
                    for j in -1..2 {
                        if !(i == 0 && j == 0) {
                            let peek_x : i32 = (x as i32) + i;
                            let peek_y : i32 = (y as i32) + j;
                            match self.get(peek_x, peek_y) {
                                Some(true) => {
                                    count += 1;
                                },
                                _ => {},
                            }
                        }
                    }
                }
                if count > 3 || count < 2 {
                    *square = false;
                } else if count == 3 {
                    *square = true;
                } else if count == 2 {
                    *square = *square;
                }
            }
            self.playground = new_playground;
        }
    }

    impl<'a> IntoIterator for &'a GameOfLife {
        type Item = &'a bool;
        type IntoIter = ::std::slice::Iter<'a, bool>;
        fn into_iter(self) -> ::std::slice::Iter<'a, bool> {
            self.playground.iter()
        }
    }
}

fn dummy_texture<'a>(canvas: &mut Canvas<Window>, texture_creator: &'a TextureCreator<WindowContext>) -> Texture<'a>{
    let mut square_texture : Texture =
        texture_creator.create_texture_target(None, SQUARE_SIZE, SQUARE_SIZE).unwrap();
    {
        // let's change the texture we just created
        let mut texture_canvas = canvas.with_target(&mut square_texture).unwrap();
        texture_canvas.set_draw_color(Color::RGB(0, 0, 0));
        texture_canvas.clear();
        for i in 0..SQUARE_SIZE {
            for j in 0..SQUARE_SIZE {
                // drawing pixel by pixel isn't very effective, but we only do it once and store
                // the texture afterwards so it's still alright!
                if (i+j) % 7 == 0 {
                    // this doesn't mean anything, there was some trial and serror to find
                    // something that wasn't too ugly
                    texture_canvas.set_draw_color(Color::RGB(192, 192, 192));
                    texture_canvas.draw_point(Point::new(i as i32, j as i32)).unwrap();
                }
                if (i+j*2) % 5 == 0 {
                    texture_canvas.set_draw_color(Color::RGB(64, 64, 64));
                    texture_canvas.draw_point(Point::new(i as i32, j as i32)).unwrap();
                }
            }
        }
    }
    square_texture
}

pub fn main() {
    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    // the window is the representation of a window in your operating system,
    // however you can only manipulate properties of that window, like its size, whether it's
    // fullscreen, ... but you cannot change its content without using a Canvas or using the
    // `surface()` method.
    let window = video_subsystem
        .window("rust-sdl2 demo: Game of Life",
                SQUARE_SIZE*PLAYGROUND_WIDTH,
                SQUARE_SIZE*PLAYGROUND_HEIGHT)
        .position_centered()
        .build()
        .unwrap();

    // the canvas allows us to both manipulate the property of the window and to change its content
    // via hardware or software rendering. See CanvasBuilder for more info.
    let mut canvas = window.into_canvas()
        .target_texture()
        .present_vsync()
        .build().unwrap();

    println!("Using SDL_Renderer \"{}\"", canvas.info().name);
    canvas.set_draw_color(Color::RGB(0, 0, 0));
    // clears the canvas with the color we set in `set_draw_color`.
    canvas.clear();
    // However the canvas has not been updated to the window yet, everything has been processed to
    // an internal buffer, but if we want our buffer to be displayed on the window, we need to call
    // `present`. We need to call this everytime we want to render a new frame on the window.
    canvas.present();

    // this struct manages textures. For lifetime reasons, the canvas cannot directly create
    // textures, you have to create a `TextureCreator` instead.
    let texture_creator : TextureCreator<_> = canvas.texture_creator();

    // Create a "target" texture so that we can use our Renderer with it later
    let square_texture = dummy_texture(&mut canvas, &texture_creator);
    let mut game = game_of_life::GameOfLife::new();

    let mut event_pump = sdl_context.event_pump().unwrap();
    let mut frame : u32 = 0;
    'running: loop {
        // get the inputs here
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                    break 'running
                },
                Event::KeyDown { keycode: Some(Keycode::Space), repeat: false, .. } => {
                    game.toggle_state();
                },
                Event::MouseButtonDown { x, y, mouse_btn: MouseButton::Left, .. } => {
                    let x = (x as u32) / SQUARE_SIZE;
                    let y = (y as u32) / SQUARE_SIZE;
                    match game.get_mut(x as i32, y as i32) {
                        Some(mut square) => {*square = !(*square);},
                        None => {panic!()}
                    };
                },
                _ => {}
            }
        }

        // update the game loop here
        if frame >= 29 {
            game.update();
            frame = 0;
        }

        canvas.set_draw_color(Color::RGB(0, 0, 0));
        canvas.clear();
        for (i, unit) in (&game).into_iter().enumerate() {
            let i = i as u32;
            match *unit {
                true => {
                    canvas.copy(&square_texture,
                                None,
                                Rect::new(((i % PLAYGROUND_WIDTH) * SQUARE_SIZE) as i32,
                                          ((i / PLAYGROUND_WIDTH) * SQUARE_SIZE) as i32,
                                          SQUARE_SIZE,
                                          SQUARE_SIZE)).unwrap();
                },
                false => {},
            }
        }
        canvas.present();
        match game.state() {
            game_of_life::State::Playing => { frame += 1; },
            _ => {}
        };
    }
}
<|endoftext|>


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

use std::{mem, ptr};
use d3dcompiler;
use dxguid;
use winapi;
use gfx_core as core;
use gfx_core::shade as s;

pub fn reflect_shader(code: &[u8]) -> *mut winapi::ID3D11ShaderReflection {
    let mut reflection = ptr::null_mut();
    let hr = unsafe {
        d3dcompiler::D3DReflect(code.as_ptr() as *const winapi::VOID,
            code.len() as winapi::SIZE_T, &dxguid::IID_ID3D11ShaderReflection, &mut reflection)
    };
    if !winapi::SUCCEEDED(hr) {
        error!("Shader reflection failed with code {:x}", hr);
    }
    reflection as *mut winapi::ID3D11ShaderReflection
}

fn convert_str(pchar: *const i8) -> String {
    use std::ffi::CStr;
    unsafe {
        CStr::from_ptr(pchar).to_string_lossy().into_owned()
    }
}

fn map_base_type(ct: winapi::D3D_REGISTER_COMPONENT_TYPE) -> s::BaseType {
    match ct {
        winapi::D3D_REGISTER_COMPONENT_UINT32 => s::BaseType::U32,
        winapi::D3D_REGISTER_COMPONENT_SINT32 => s::BaseType::I32,
        winapi::D3D_REGISTER_COMPONENT_FLOAT32 => s::BaseType::F32,
        winapi::D3D_REGISTER_COMPONENT_TYPE(t) => {
            error!("Unknown register component type {} detected!", t);
            s::BaseType::F32
        },
    }
}

pub fn populate_info(info: &mut s::ProgramInfo, stage: s::Stage,
                     reflection: *mut winapi::ID3D11ShaderReflection) {
    use winapi::{UINT, SUCCEEDED};
    let usage = stage.into();
    let shader_desc = unsafe {
        let mut desc = mem::zeroed();
        (*reflection).GetDesc(&mut desc);
        desc
    };
    if stage == s::Stage::Vertex {
        // record vertex attributes
        for i in 0 .. shader_desc.InputParameters {
            let (hr, desc) = unsafe {
                let mut desc = mem::zeroed();
                let hr = (*reflection).GetInputParameterDesc(i as UINT, &mut desc);
                (hr, desc)
            };
            assert!(SUCCEEDED(hr));
            debug!("Attribute {}, system type {:?}, mask {}, read-write mask {}",
                convert_str(desc.SemanticName), desc.SystemValueType, desc.Mask, desc.ReadWriteMask);
            if desc.SystemValueType != winapi::D3D_NAME_UNDEFINED {
                // system value semantic detected, skipping
                continue
            }
            if desc.Mask == 0 {
                // not used, skipping
                continue
            }
            info.vertex_attributes.push(s::AttributeVar {
                name: convert_str(desc.SemanticName),
                slot: desc.Register as core::AttributeSlot,
                base_type: map_base_type(desc.ComponentType),
                container: s::ContainerType::Vector(4), // how to get it?
            });
        }
    }
    if stage == s::Stage::Pixel {
        // record pixel outputs
        for i in 0 .. shader_desc.OutputParameters {
            let (hr, desc) = unsafe {
                let mut desc = mem::zeroed();
                let hr = (*reflection).GetOutputParameterDesc(i as UINT, &mut desc);
                (hr, desc)
            };
            assert!(SUCCEEDED(hr));
            debug!("Output {}, system type {:?}, mask {}, read-write mask {}",
                convert_str(desc.SemanticName), desc.SystemValueType, desc.Mask, desc.ReadWriteMask);
            if desc.SystemValueType != winapi::D3D_NAME_UNDEFINED {
                // system value semantic detected, skipping
                continue
            }
            info.outputs.push(s::OutputVar {
                name: convert_str(desc.SemanticName),
                slot: desc.Register as core::ColorSlot,
                base_type: map_base_type(desc.ComponentType),
                container: s::ContainerType::Vector(4), // how to get it?
            });
        }
    }
    // record resources
    for i in 0 .. shader_desc.BoundResources {
        let (hr, res_desc) = unsafe {
            let mut desc = mem::zeroed();
            let hr = (*reflection).GetResourceBindingDesc(i as UINT, &mut desc);
            (hr, desc)
        };
        assert!(SUCCEEDED(hr));
        let name = convert_str(res_desc.Name);
        debug!("Resource {}, type {:?}", name, res_desc.Type);
        if res_desc.Type == winapi::D3D_SIT_CBUFFER {
            if let Some(cb) = info.constant_buffers.iter_mut().find(|cb| cb.name == name) {
                cb.usage = cb.usage | usage;
                continue;
            }
            let desc = unsafe {
                let cbuf = (*reflection).GetConstantBufferByName(res_desc.Name);
                let mut desc = mem::zeroed();
                let hr = (*cbuf).GetDesc(&mut desc);
                assert!(SUCCEEDED(hr));
                desc
            };
            info.constant_buffers.push(s::ConstantBufferVar {
                name: name,
                slot: res_desc.BindPoint as core::ConstantBufferSlot,
                size: desc.Size as usize,
                usage: usage,
            });
        }else if res_desc.Type == winapi::D3D_SIT_TEXTURE {
            //TODO
        }else if res_desc.Type == winapi::D3D_SIT_SAMPLER {
            //TODO
        }else {
            error!("Unsupported resource type {:?} for {}", res_desc.Type, name);
        }
    }
    /*
    for i in 0 .. desc.ConstantBuffers {
        let cb = reflection->GetConstantBufferByIndex(i);
        let desc = unsafe {
            let mut desc = mem::zeroed();
            cb->GetDesc(&mut desc);
            desc
        };
        let var = s::ConstantBufferVar {
            name: desc.Name,
            slot: i,
            size: desc.Size,
            usage: usage,
        };
        //TODO: search for the existing one
        info.constant_buffers.push(var);
    }*/
}
<commit_msg>DX - shader feature level and sampler queries<commit_after>// Copyright 2016 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{mem, ptr};
use d3dcompiler;
use dxguid;
use winapi;
use gfx_core as core;
use gfx_core::shade as s;

pub fn reflect_shader(code: &[u8]) -> *mut winapi::ID3D11ShaderReflection {
    let mut reflection = ptr::null_mut();
    let hr = unsafe {
        d3dcompiler::D3DReflect(code.as_ptr() as *const winapi::VOID,
            code.len() as winapi::SIZE_T, &dxguid::IID_ID3D11ShaderReflection, &mut reflection)
    };
    if !winapi::SUCCEEDED(hr) {
        error!("Shader reflection failed with code {:x}", hr);
    }
    reflection as *mut winapi::ID3D11ShaderReflection
}

fn convert_str(pchar: *const i8) -> String {
    use std::ffi::CStr;
    unsafe {
        CStr::from_ptr(pchar).to_string_lossy().into_owned()
    }
}

fn map_base_type(ct: winapi::D3D_REGISTER_COMPONENT_TYPE) -> s::BaseType {
    match ct {
        winapi::D3D_REGISTER_COMPONENT_UINT32 => s::BaseType::U32,
        winapi::D3D_REGISTER_COMPONENT_SINT32 => s::BaseType::I32,
        winapi::D3D_REGISTER_COMPONENT_FLOAT32 => s::BaseType::F32,
        winapi::D3D_REGISTER_COMPONENT_TYPE(t) => {
            error!("Unknown register component type {} detected!", t);
            s::BaseType::F32
        },
    }
}

pub fn populate_info(info: &mut s::ProgramInfo, stage: s::Stage,
                     reflection: *mut winapi::ID3D11ShaderReflection) {
    use winapi::{UINT, SUCCEEDED};
    let usage = stage.into();
    let (shader_desc, _feature_level) = unsafe {
        let mut desc = mem::zeroed();
        let mut level = winapi::D3D_FEATURE_LEVEL_9_1;
        (*reflection).GetDesc(&mut desc);
        (*reflection).GetMinFeatureLevel(&mut level);
        (desc, level)
    };
    if stage == s::Stage::Vertex {
        // record vertex attributes
        for i in 0 .. shader_desc.InputParameters {
            let (hr, desc) = unsafe {
                let mut desc = mem::zeroed();
                let hr = (*reflection).GetInputParameterDesc(i as UINT, &mut desc);
                (hr, desc)
            };
            assert!(SUCCEEDED(hr));
            debug!("Attribute {}, system type {:?}, mask {}, read-write mask {}",
                convert_str(desc.SemanticName), desc.SystemValueType, desc.Mask, desc.ReadWriteMask);
            if desc.SystemValueType != winapi::D3D_NAME_UNDEFINED {
                // system value semantic detected, skipping
                continue
            }
            if desc.Mask == 0 {
                // not used, skipping
                continue
            }
            info.vertex_attributes.push(s::AttributeVar {
                name: convert_str(desc.SemanticName),
                slot: desc.Register as core::AttributeSlot,
                base_type: map_base_type(desc.ComponentType),
                container: s::ContainerType::Vector(4), // how to get it?
            });
        }
    }
    if stage == s::Stage::Pixel {
        // record pixel outputs
        for i in 0 .. shader_desc.OutputParameters {
            let (hr, desc) = unsafe {
                let mut desc = mem::zeroed();
                let hr = (*reflection).GetOutputParameterDesc(i as UINT, &mut desc);
                (hr, desc)
            };
            assert!(SUCCEEDED(hr));
            debug!("Output {}, system type {:?}, mask {}, read-write mask {}",
                convert_str(desc.SemanticName), desc.SystemValueType, desc.Mask, desc.ReadWriteMask);
            if desc.SystemValueType != winapi::D3D_NAME_UNDEFINED {
                // system value semantic detected, skipping
                continue
            }
            info.outputs.push(s::OutputVar {
                name: convert_str(desc.SemanticName),
                slot: desc.Register as core::ColorSlot,
                base_type: map_base_type(desc.ComponentType),
                container: s::ContainerType::Vector(4), // how to get it?
            });
        }
    }
    // record resources
    for i in 0 .. shader_desc.BoundResources {
        let (hr, res_desc) = unsafe {
            let mut desc = mem::zeroed();
            let hr = (*reflection).GetResourceBindingDesc(i as UINT, &mut desc);
            (hr, desc)
        };
        assert!(SUCCEEDED(hr));
        let name = convert_str(res_desc.Name);
        debug!("Resource {}, type {:?}", name, res_desc.Type);
        if res_desc.Type == winapi::D3D_SIT_CBUFFER {
            if let Some(cb) = info.constant_buffers.iter_mut().find(|cb| cb.name == name) {
                cb.usage = cb.usage | usage;
                continue;
            }
            let desc = unsafe {
                let cbuf = (*reflection).GetConstantBufferByName(res_desc.Name);
                let mut desc = mem::zeroed();
                let hr = (*cbuf).GetDesc(&mut desc);
                assert!(SUCCEEDED(hr));
                desc
            };
            info.constant_buffers.push(s::ConstantBufferVar {
                name: name,
                slot: res_desc.BindPoint as core::ConstantBufferSlot,
                size: desc.Size as usize,
                usage: usage,
            });
        }else if res_desc.Type == winapi::D3D_SIT_TEXTURE {
            //TODO
        }else if res_desc.Type == winapi::D3D_SIT_SAMPLER {
            if let Some(s) = info.samplers.iter_mut().find(|s| s.name == name) {
                s.usage = s.usage | usage;
                continue;
            }
            let cmp = if res_desc.uFlags & winapi::D3D_SIF_COMPARISON_SAMPLER.0 != 0 {
                s::IsComparison::Compare
            }else {
                s::IsComparison::NoCompare
            };
            info.samplers.push(s::SamplerVar {
                name: name,
                slot: res_desc.BindPoint as core::SamplerSlot,
                ty: s::SamplerType(cmp, s::IsRect::NoRect),
                usage: usage,
            });
        }else {
            error!("Unsupported resource type {:?} for {}", res_desc.Type, name);
        }
    }
}
<|endoftext|>