<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.

#![no_std]
#![allow(unused_attributes)]
#![unstable(feature = "alloc_jemalloc",
            reason = "this library is unlikely to be stabilized in its current \
                      form or name",
            issue = "27783")]
#![deny(warnings)]
#![feature(alloc)]
#![feature(alloc_system)]
#![feature(libc)]
#![feature(linkage)]
#![feature(staged_api)]
#![feature(rustc_attrs)]
#![cfg_attr(dummy_jemalloc, allow(dead_code, unused_extern_crates))]
#![cfg_attr(not(dummy_jemalloc), feature(allocator_api))]
#![rustc_alloc_kind = "exe"]

extern crate alloc;
extern crate alloc_system;
extern crate libc;

#[cfg(not(dummy_jemalloc))]
pub use contents::*;
#[cfg(not(dummy_jemalloc))]
mod contents {
    use core::ptr;

    use alloc::heap::{Alloc, AllocErr, Layout};
    use alloc_system::System;
    use libc::{c_int, c_void, size_t};

    // Note that the symbols here are prefixed by default on macOS and Windows (we
    // don't explicitly request it), and on Android and DragonFly we explicitly
    // request it as unprefixing cause segfaults (mismatches in allocators).
    extern "C" {
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_mallocx")]
        fn mallocx(size: size_t, flags: c_int) -> *mut c_void;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_calloc")]
        fn calloc(size: size_t, flags: c_int) -> *mut c_void;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_rallocx")]
        fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_xallocx")]
        fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_sdallocx")]
        fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_nallocx")]
        fn nallocx(size: size_t, flags: c_int) -> size_t;
    }

    const MALLOCX_ZERO: c_int = 0x40;

    // The minimum alignment guaranteed by the architecture. This value is used to
    // add fast paths for low alignment values. In practice, the alignment is a
    // constant at the call site and the branch will be optimized out.
    #[cfg(all(any(target_arch = "arm",
                  target_arch = "mips",
                  target_arch = "powerpc")))]
    const MIN_ALIGN: usize = 8;
    #[cfg(all(any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "aarch64",
                  target_arch = "powerpc64",
                  target_arch = "mips64",
                  target_arch = "s390x",
                  target_arch = "sparc64")))]
    const MIN_ALIGN: usize = 16;

    // MALLOCX_ALIGN(a) macro
    fn mallocx_align(a: usize) -> c_int {
        a.trailing_zeros() as c_int
    }

    fn align_to_flags(align: usize) -> c_int {
        if align <= MIN_ALIGN {
            0
        } else {
            mallocx_align(align)
        }
    }

    // for symbol names src/librustc/middle/allocator.rs
    // for signatures src/librustc_allocator/lib.rs

    // linkage directives are provided as part of the current compiler allocator
    // ABI

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_alloc(size: usize,
                                     align: usize,
                                     err: *mut u8) -> *mut u8 {
        let flags = align_to_flags(align);
        let ptr = mallocx(size as size_t, flags) as *mut u8;
        if ptr.is_null() {
            let layout = Layout::from_size_align_unchecked(size, align);
            ptr::write(err as *mut AllocErr,
                       AllocErr::Exhausted { request: layout });
        }
        ptr
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_oom(err: *const u8) -> ! {
        System.oom((*(err as *const AllocErr)).clone())
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_dealloc(ptr: *mut u8,
                                       size: usize,
                                       align: usize) {
        let flags = align_to_flags(align);
        sdallocx(ptr as *mut c_void, size, flags);
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_usable_size(layout: *const u8,
                                           min: *mut usize,
                                           max: *mut usize) {
        let layout = &*(layout as *const Layout);
        let flags = align_to_flags(layout.align());
        let size = nallocx(layout.size(), flags) as usize;
        *min = layout.size();
        if size > 0 {
            *max = size;
        } else {
            *max = layout.size();
        }
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_realloc(ptr: *mut u8,
                                       _old_size: usize,
                                       old_align: usize,
                                       new_size: usize,
                                       new_align: usize,
                                       err: *mut u8) -> *mut u8 {
        if new_align != old_align {
            ptr::write(err as *mut AllocErr,
                       AllocErr::Unsupported { details: "can't change alignments" });
            return 0 as *mut u8
        }

        let flags = align_to_flags(new_align);
        let ptr = rallocx(ptr as *mut c_void, new_size, flags) as *mut u8;
        if ptr.is_null() {
            let layout = Layout::from_size_align_unchecked(new_size, new_align);
            ptr::write(err as *mut AllocErr,
                       AllocErr::Exhausted { request: layout });
        }
        ptr
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_alloc_zeroed(size: usize,
                                            align: usize,
                                            err: *mut u8) -> *mut u8 {
        let ptr = if align <= MIN_ALIGN {
            calloc(size as size_t, 1) as *mut u8
        } else {
            let flags = align_to_flags(align) | MALLOCX_ZERO;
            mallocx(size as size_t, flags) as *mut u8
        };
        if ptr.is_null() {
            let layout = Layout::from_size_align_unchecked(size, align);
            ptr::write(err as *mut AllocErr,
                       AllocErr::Exhausted { request: layout });
        }
        ptr
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_alloc_excess(size: usize,
                                            align: usize,
                                            excess: *mut usize,
                                            err: *mut u8) -> *mut u8 {
        let p = __rde_alloc(size, align, err);
        if !p.is_null() {
            *excess = size;
        }
        return p
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_realloc_excess(ptr: *mut u8,
                                              old_size: usize,
                                              old_align: usize,
                                              new_size: usize,
                                              new_align: usize,
                                              excess: *mut usize,
                                              err: *mut u8) -> *mut u8 {
        let p = __rde_realloc(ptr, old_size, old_align, new_size, new_align, err);
        if !p.is_null() {
            *excess = new_size;
        }
        return p
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_grow_in_place(ptr: *mut u8,
                                             old_size: usize,
                                             old_align: usize,
                                             new_size: usize,
                                             new_align: usize) -> u8 {
        __rde_shrink_in_place(ptr, old_size, old_align, new_size, new_align)
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_shrink_in_place(ptr: *mut u8,
                                               _old_size: usize,
                                               old_align: usize,
                                               new_size: usize,
                                               new_align: usize) -> u8 {
        if old_align == new_align {
            let flags = align_to_flags(new_align);
            (xallocx(ptr as *mut c_void, new_size, 0, flags) == new_size) as u8
        } else {
            0
        }
    }
}
<commit_msg>[jemalloc] set correct excess in realloc_excess<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.

#![no_std]
#![allow(unused_attributes)]
#![unstable(feature = "alloc_jemalloc",
            reason = "this library is unlikely to be stabilized in its current \
                      form or name",
            issue = "27783")]
#![deny(warnings)]
#![feature(alloc)]
#![feature(alloc_system)]
#![feature(libc)]
#![feature(linkage)]
#![feature(staged_api)]
#![feature(rustc_attrs)]
#![cfg_attr(dummy_jemalloc, allow(dead_code, unused_extern_crates))]
#![cfg_attr(not(dummy_jemalloc), feature(allocator_api))]
#![rustc_alloc_kind = "exe"]

extern crate alloc;
extern crate alloc_system;
extern crate libc;

#[cfg(not(dummy_jemalloc))]
pub use contents::*;
#[cfg(not(dummy_jemalloc))]
mod contents {
    use core::ptr;

    use alloc::heap::{Alloc, AllocErr, Layout};
    use alloc_system::System;
    use libc::{c_int, c_void, size_t};

    // Note that the symbols here are prefixed by default on macOS and Windows (we
    // don't explicitly request it), and on Android and DragonFly we explicitly
    // request it as unprefixing cause segfaults (mismatches in allocators).
    extern "C" {
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_mallocx")]
        fn mallocx(size: size_t, flags: c_int) -> *mut c_void;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_calloc")]
        fn calloc(size: size_t, flags: c_int) -> *mut c_void;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_rallocx")]
        fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_xallocx")]
        fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_sdallocx")]
        fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_nallocx")]
        fn nallocx(size: size_t, flags: c_int) -> size_t;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_sallocx")]
        fn sallocx(ptr: *mut c_void, flags: c_int) -> size_t;
    }

    const MALLOCX_ZERO: c_int = 0x40;

    // The minimum alignment guaranteed by the architecture. This value is used to
    // add fast paths for low alignment values. In practice, the alignment is a
    // constant at the call site and the branch will be optimized out.
    #[cfg(all(any(target_arch = "arm",
                  target_arch = "mips",
                  target_arch = "powerpc")))]
    const MIN_ALIGN: usize = 8;
    #[cfg(all(any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "aarch64",
                  target_arch = "powerpc64",
                  target_arch = "mips64",
                  target_arch = "s390x",
                  target_arch = "sparc64")))]
    const MIN_ALIGN: usize = 16;

    // MALLOCX_ALIGN(a) macro
    fn mallocx_align(a: usize) -> c_int {
        a.trailing_zeros() as c_int
    }

    fn align_to_flags(align: usize) -> c_int {
        if align <= MIN_ALIGN {
            0
        } else {
            mallocx_align(align)
        }
    }

    // for symbol names src/librustc/middle/allocator.rs
    // for signatures src/librustc_allocator/lib.rs

    // linkage directives are provided as part of the current compiler allocator
    // ABI

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_alloc(size: usize,
                                     align: usize,
                                     err: *mut u8) -> *mut u8 {
        let flags = align_to_flags(align);
        let ptr = mallocx(size as size_t, flags) as *mut u8;
        if ptr.is_null() {
            let layout = Layout::from_size_align_unchecked(size, align);
            ptr::write(err as *mut AllocErr,
                       AllocErr::Exhausted { request: layout });
        }
        ptr
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_oom(err: *const u8) -> ! {
        System.oom((*(err as *const AllocErr)).clone())
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_dealloc(ptr: *mut u8,
                                       size: usize,
                                       align: usize) {
        let flags = align_to_flags(align);
        sdallocx(ptr as *mut c_void, size, flags);
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_usable_size(layout: *const u8,
                                           min: *mut usize,
                                           max: *mut usize) {
        let layout = &*(layout as *const Layout);
        let flags = align_to_flags(layout.align());
        let size = nallocx(layout.size(), flags) as usize;
        *min = layout.size();
        if size > 0 {
            *max = size;
        } else {
            *max = layout.size();
        }
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_realloc(ptr: *mut u8,
                                       _old_size: usize,
                                       old_align: usize,
                                       new_size: usize,
                                       new_align: usize,
                                       err: *mut u8) -> *mut u8 {
        if new_align != old_align {
            ptr::write(err as *mut AllocErr,
                       AllocErr::Unsupported { details: "can't change alignments" });
            return 0 as *mut u8
        }

        let flags = align_to_flags(new_align);
        let ptr = rallocx(ptr as *mut c_void, new_size, flags) as *mut u8;
        if ptr.is_null() {
            let layout = Layout::from_size_align_unchecked(new_size, new_align);
            ptr::write(err as *mut AllocErr,
                       AllocErr::Exhausted { request: layout });
        }
        ptr
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_alloc_zeroed(size: usize,
                                            align: usize,
                                            err: *mut u8) -> *mut u8 {
        let ptr = if align <= MIN_ALIGN {
            calloc(size as size_t, 1) as *mut u8
        } else {
            let flags = align_to_flags(align) | MALLOCX_ZERO;
            mallocx(size as size_t, flags) as *mut u8
        };
        if ptr.is_null() {
            let layout = Layout::from_size_align_unchecked(size, align);
            ptr::write(err as *mut AllocErr,
                       AllocErr::Exhausted { request: layout });
        }
        ptr
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_alloc_excess(size: usize,
                                            align: usize,
                                            excess: *mut usize,
                                            err: *mut u8) -> *mut u8 {
        let p = __rde_alloc(size, align, err);
        if !p.is_null() {
            *excess = size;
        }
        return p
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_realloc_excess(ptr: *mut u8,
                                              _old_size: usize,
                                              old_align: usize,
                                              new_size: usize,
                                              new_align: usize,
                                              excess: *mut usize,
                                              err: *mut u8) -> *mut u8 {
        if new_align != old_align {
            ptr::write(err as *mut AllocErr,
                       AllocErr::Unsupported { details: "can't change alignments" });
            return 0 as *mut u8
        }

        let flags = align_to_flags(new_align);
        let ptr = rallocx(ptr as *mut c_void, new_size, flags) as usize;
        let alloc_size = sallocx(ptr as *mut c_void, flags);
        if ptr.is_null() {
            let layout = Layout::from_size_align_unchecked(new_size, new_align);
            ptr::write(err as *mut AllocErr,
                       AllocErr::Exhausted { request: layout });
        }
        *excess = alloc_size;
        ptr
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_grow_in_place(ptr: *mut u8,
                                             old_size: usize,
                                             old_align: usize,
                                             new_size: usize,
                                             new_align: usize) -> u8 {
        __rde_shrink_in_place(ptr, old_size, old_align, new_size, new_align)
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_shrink_in_place(ptr: *mut u8,
                                               _old_size: usize,
                                               old_align: usize,
                                               new_size: usize,
                                               new_align: usize) -> u8 {
        if old_align == new_align {
            let flags = align_to_flags(new_align);
            (xallocx(ptr as *mut c_void, new_size, 0, flags) == new_size) as u8
        } else {
            0
        }
    }
}
<|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.

#![unstable(feature = "semaphore",
            reason = "the interaction between semaphores and the acquisition/release \
                      of resources is currently unclear",
            issue = "27798")]
#![rustc_deprecated(since = "1.7.0",
                    reason = "easily confused with system sempahores and not \
                              used enough to pull its weight")]
#![allow(deprecated)]

use ops::Drop;
use sync::{Mutex, Condvar};

/// A counting, blocking, semaphore.
///
/// Semaphores are a form of atomic counter where access is only granted if the
/// counter is a positive value. Each acquisition will block the calling thread
/// until the counter is positive, and each release will increment the counter
/// and unblock any threads if necessary.
///
/// # Examples
///
/// ```
/// #![feature(semaphore)]
///
/// use std::sync::Semaphore;
///
/// // Create a semaphore that represents 5 resources
/// let sem = Semaphore::new(5);
///
/// // Acquire one of the resources
/// sem.acquire();
///
/// // Acquire one of the resources for a limited period of time
/// {
///     let _guard = sem.access();
///     // ...
/// } // resources is released here
///
/// // Release our initially acquired resource
/// sem.release();
/// ```
pub struct Semaphore {
    lock: Mutex<isize>,
    cvar: Condvar,
}

/// An RAII guard which will release a resource acquired from a semaphore when
/// dropped.
pub struct SemaphoreGuard<'a> {
    sem: &'a Semaphore,
}

impl Semaphore {
    /// Creates a new semaphore with the initial count specified.
    ///
    /// The count specified can be thought of as a number of resources, and a
    /// call to `acquire` or `access` will block until at least one resource is
    /// available. It is valid to initialize a semaphore with a negative count.
    pub fn new(count: isize) -> Semaphore {
        Semaphore {
            lock: Mutex::new(count),
            cvar: Condvar::new(),
        }
    }

    /// Acquires a resource of this semaphore, blocking the current thread until
    /// it can do so.
    ///
    /// This method will block until the internal count of the semaphore is at
    /// least 1.
    pub fn acquire(&self) {
        let mut count = self.lock.lock().unwrap();
        while *count <= 0 {
            count = self.cvar.wait(count).unwrap();
        }
        *count -= 1;
    }

    /// Release a resource from this semaphore.
    ///
    /// This will increment the number of resources in this semaphore by 1 and
    /// will notify any pending waiters in `acquire` or `access` if necessary.
    pub fn release(&self) {
        *self.lock.lock().unwrap() += 1;
        self.cvar.notify_one();
    }

    /// Acquires a resource of this semaphore, returning an RAII guard to
    /// release the semaphore when dropped.
    ///
    /// This function is semantically equivalent to an `acquire` followed by a
    /// `release` when the guard returned is dropped.
    pub fn access(&self) -> SemaphoreGuard {
        self.acquire();
        SemaphoreGuard { sem: self }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Drop for SemaphoreGuard<'a> {
    fn drop(&mut self) {
        self.sem.release();
    }
}

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

    use sync::Arc;
    use super::Semaphore;
    use sync::mpsc::channel;
    use thread;

    #[test]
    fn test_sem_acquire_release() {
        let s = Semaphore::new(1);
        s.acquire();
        s.release();
        s.acquire();
    }

    #[test]
    fn test_sem_basic() {
        let s = Semaphore::new(1);
        let _g = s.access();
    }

    #[test]
    fn test_sem_as_mutex() {
        let s = Arc::new(Semaphore::new(1));
        let s2 = s.clone();
        let _t = thread::spawn(move|| {
            let _g = s2.access();
        });
        let _g = s.access();
    }

    #[test]
    fn test_sem_as_cvar() {
        /* Child waits and parent signals */
        let (tx, rx) = channel();
        let s = Arc::new(Semaphore::new(0));
        let s2 = s.clone();
        let _t = thread::spawn(move|| {
            s2.acquire();
            tx.send(()).unwrap();
        });
        s.release();
        let _ = rx.recv();

        /* Parent waits and child signals */
        let (tx, rx) = channel();
        let s = Arc::new(Semaphore::new(0));
        let s2 = s.clone();
        let _t = thread::spawn(move|| {
            s2.release();
            let _ = rx.recv();
        });
        s.acquire();
        tx.send(()).unwrap();
    }

    #[test]
    fn test_sem_multi_resource() {
        // Parent and child both get in the critical section at the same
        // time, and shake hands.
        let s = Arc::new(Semaphore::new(2));
        let s2 = s.clone();
        let (tx1, rx1) = channel();
        let (tx2, rx2) = channel();
        let _t = thread::spawn(move|| {
            let _g = s2.access();
            let _ = rx2.recv();
            tx1.send(()).unwrap();
        });
        let _g = s.access();
        tx2.send(()).unwrap();
        rx1.recv().unwrap();
    }

    #[test]
    fn test_sem_runtime_friendly_blocking() {
        let s = Arc::new(Semaphore::new(1));
        let s2 = s.clone();
        let (tx, rx) = channel();
        {
            let _g = s.access();
            thread::spawn(move|| {
                tx.send(()).unwrap();
                drop(s2.access());
                tx.send(()).unwrap();
            });
            rx.recv().unwrap(); // wait for child to come alive
        }
        rx.recv().unwrap(); // wait for child to be done
    }
}
<commit_msg>Rollup merge of #31146 - angelsl:patch-1, r=steveklabnik<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.

#![unstable(feature = "semaphore",
            reason = "the interaction between semaphores and the acquisition/release \
                      of resources is currently unclear",
            issue = "27798")]
#![rustc_deprecated(since = "1.7.0",
                    reason = "easily confused with system semaphores and not \
                              used enough to pull its weight")]
#![allow(deprecated)]

use ops::Drop;
use sync::{Mutex, Condvar};

/// A counting, blocking, semaphore.
///
/// Semaphores are a form of atomic counter where access is only granted if the
/// counter is a positive value. Each acquisition will block the calling thread
/// until the counter is positive, and each release will increment the counter
/// and unblock any threads if necessary.
///
/// # Examples
///
/// ```
/// #![feature(semaphore)]
///
/// use std::sync::Semaphore;
///
/// // Create a semaphore that represents 5 resources
/// let sem = Semaphore::new(5);
///
/// // Acquire one of the resources
/// sem.acquire();
///
/// // Acquire one of the resources for a limited period of time
/// {
///     let _guard = sem.access();
///     // ...
/// } // resources is released here
///
/// // Release our initially acquired resource
/// sem.release();
/// ```
pub struct Semaphore {
    lock: Mutex<isize>,
    cvar: Condvar,
}

/// An RAII guard which will release a resource acquired from a semaphore when
/// dropped.
pub struct SemaphoreGuard<'a> {
    sem: &'a Semaphore,
}

impl Semaphore {
    /// Creates a new semaphore with the initial count specified.
    ///
    /// The count specified can be thought of as a number of resources, and a
    /// call to `acquire` or `access` will block until at least one resource is
    /// available. It is valid to initialize a semaphore with a negative count.
    pub fn new(count: isize) -> Semaphore {
        Semaphore {
            lock: Mutex::new(count),
            cvar: Condvar::new(),
        }
    }

    /// Acquires a resource of this semaphore, blocking the current thread until
    /// it can do so.
    ///
    /// This method will block until the internal count of the semaphore is at
    /// least 1.
    pub fn acquire(&self) {
        let mut count = self.lock.lock().unwrap();
        while *count <= 0 {
            count = self.cvar.wait(count).unwrap();
        }
        *count -= 1;
    }

    /// Release a resource from this semaphore.
    ///
    /// This will increment the number of resources in this semaphore by 1 and
    /// will notify any pending waiters in `acquire` or `access` if necessary.
    pub fn release(&self) {
        *self.lock.lock().unwrap() += 1;
        self.cvar.notify_one();
    }

    /// Acquires a resource of this semaphore, returning an RAII guard to
    /// release the semaphore when dropped.
    ///
    /// This function is semantically equivalent to an `acquire` followed by a
    /// `release` when the guard returned is dropped.
    pub fn access(&self) -> SemaphoreGuard {
        self.acquire();
        SemaphoreGuard { sem: self }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Drop for SemaphoreGuard<'a> {
    fn drop(&mut self) {
        self.sem.release();
    }
}

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

    use sync::Arc;
    use super::Semaphore;
    use sync::mpsc::channel;
    use thread;

    #[test]
    fn test_sem_acquire_release() {
        let s = Semaphore::new(1);
        s.acquire();
        s.release();
        s.acquire();
    }

    #[test]
    fn test_sem_basic() {
        let s = Semaphore::new(1);
        let _g = s.access();
    }

    #[test]
    fn test_sem_as_mutex() {
        let s = Arc::new(Semaphore::new(1));
        let s2 = s.clone();
        let _t = thread::spawn(move|| {
            let _g = s2.access();
        });
        let _g = s.access();
    }

    #[test]
    fn test_sem_as_cvar() {
        /* Child waits and parent signals */
        let (tx, rx) = channel();
        let s = Arc::new(Semaphore::new(0));
        let s2 = s.clone();
        let _t = thread::spawn(move|| {
            s2.acquire();
            tx.send(()).unwrap();
        });
        s.release();
        let _ = rx.recv();

        /* Parent waits and child signals */
        let (tx, rx) = channel();
        let s = Arc::new(Semaphore::new(0));
        let s2 = s.clone();
        let _t = thread::spawn(move|| {
            s2.release();
            let _ = rx.recv();
        });
        s.acquire();
        tx.send(()).unwrap();
    }

    #[test]
    fn test_sem_multi_resource() {
        // Parent and child both get in the critical section at the same
        // time, and shake hands.
        let s = Arc::new(Semaphore::new(2));
        let s2 = s.clone();
        let (tx1, rx1) = channel();
        let (tx2, rx2) = channel();
        let _t = thread::spawn(move|| {
            let _g = s2.access();
            let _ = rx2.recv();
            tx1.send(()).unwrap();
        });
        let _g = s.access();
        tx2.send(()).unwrap();
        rx1.recv().unwrap();
    }

    #[test]
    fn test_sem_runtime_friendly_blocking() {
        let s = Arc::new(Semaphore::new(1));
        let s2 = s.clone();
        let (tx, rx) = channel();
        {
            let _g = s.access();
            thread::spawn(move|| {
                tx.send(()).unwrap();
                drop(s2.access());
                tx.send(()).unwrap();
            });
            rx.recv().unwrap(); // wait for child to come alive
        }
        rx.recv().unwrap(); // wait for child to be done
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix Realiability enum warning<commit_after><|endoftext|>


<commit_before><commit_msg>factors used for data generation can be generated<commit_after>use std::ops::IndexMut;

extern crate nalgebra;
use nalgebra::{DMat};

type FloatType = f64;
type Mat = DMat<FloatType>;

fn horizontal_line<I: Iterator<Item = usize>>(row: usize, cols: I) -> Mat {
    let mut factor: Mat = DMat::new_zeros(10, 10);
    for col in cols {
        *factor.index_mut((row, col)) = 1.;
    }
    factor
}

fn vertical_line<I: Iterator<Item = usize>>(rows: I, col: usize) -> Mat {
    let mut factor: Mat = DMat::new_zeros(10, 10);
    for row in rows {
        *factor.index_mut((row, col)) = 1.;
    }
    factor
}

fn main() {
    let mut factors: Vec<DMat<f64>> = Vec::new();

    factors.push(horizontal_line(9, 0..5));
    for row in (0..9).rev() {
        factors.push(horizontal_line(row, 0..10));
    }

    factors.push(vertical_line(5..10, 0));
    for col in 1..10 {
        factors.push(vertical_line(0..10, col));
    }

    for factor in factors {
        println!("{:?}", factor);
    }
}

<|endoftext|>


<commit_before><commit_msg>test: external subcommand inherits jobserver<commit_after><|endoftext|>


<commit_before><commit_msg>Add colors example<commit_after>extern crate termion;

use termion::{TermWrite, Color, Style};
use std::io::{self, Write};

const LINE_NUM_BG: Color = Color::Grayscale(5);
const LINE_NUM_FG: Color = Color::Grayscale(18);
const ERROR_FG: Color = Color::Grayscale(17);
const INFO_LINE: &'static str = "│  ";

fn main() {
    let stdout = io::stdout();
    let mut stdout = stdout.lock();

    stdout.color(Color::LightGreen).unwrap();
    stdout.write("—— src/test/ui/borrow-errors.rs at 82:18 ——\n".as_bytes()).unwrap();
    stdout.reset().unwrap();

    stdout.color(Color::Red).unwrap();
    stdout.style(Style::Bold).unwrap();
    stdout.write(b"error: ").unwrap();
    stdout.reset().unwrap();

    stdout.style(Style::Bold).unwrap();
    stdout.write(b"two closures require unique access to `vec` at the same time").unwrap();
    stdout.reset().unwrap();

    stdout.style(Style::Bold).unwrap();
    stdout.color(Color::Magenta).unwrap();
    stdout.write(b" [E0524]\n").unwrap();
    stdout.reset().unwrap();

    stdout.color(LINE_NUM_FG).unwrap();
    stdout.bg_color(LINE_NUM_BG).unwrap();
    stdout.write(b"79 ").unwrap();
    stdout.reset().unwrap();

    stdout.write(b"     let append = |e| {\n").unwrap();

    stdout.color(LINE_NUM_FG).unwrap();
    stdout.bg_color(LINE_NUM_BG).unwrap();
    stdout.write(INFO_LINE.as_bytes()).unwrap();
    stdout.reset().unwrap();
    stdout.color(Color::Red).unwrap();
    stdout.write("                  ━━━ ".as_bytes()).unwrap();
    stdout.reset().unwrap();

    stdout.color(ERROR_FG).unwrap();
    stdout.write(b"first closure is constructed here\n").unwrap();
    stdout.reset().unwrap();

    stdout.color(LINE_NUM_FG).unwrap();
    stdout.bg_color(LINE_NUM_BG).unwrap();
    stdout.write(b"80 ").unwrap();
    stdout.reset().unwrap();

    stdout.write(b"         vec.push(e)\n").unwrap();

    stdout.color(LINE_NUM_FG).unwrap();
    stdout.bg_color(LINE_NUM_BG).unwrap();
    stdout.write(INFO_LINE.as_bytes()).unwrap();
    stdout.reset().unwrap();
    stdout.color(Color::Red).unwrap();
    stdout.write("         ━━━ ".as_bytes()).unwrap();
    stdout.reset().unwrap();

    stdout.color(ERROR_FG).unwrap();
    stdout.write(b"previous borrow occurs due to use of `vec` in closure\n").unwrap();
    stdout.reset().unwrap();

    stdout.color(LINE_NUM_FG).unwrap();
    stdout.bg_color(LINE_NUM_BG).unwrap();
    stdout.write(b"81 ").unwrap();
    stdout.reset().unwrap();
    stdout.write(b"     };\n").unwrap();

    stdout.color(LINE_NUM_FG).unwrap();
    stdout.bg_color(LINE_NUM_BG).unwrap();
    stdout.write(b"82 ").unwrap();
    stdout.reset().unwrap();
    stdout.write(b"     let append = |e| {\n").unwrap();

    stdout.color(LINE_NUM_FG).unwrap();
    stdout.bg_color(LINE_NUM_BG).unwrap();
    stdout.write(INFO_LINE.as_bytes()).unwrap();
    stdout.reset().unwrap();
    stdout.color(Color::Red).unwrap();
    stdout.write("                  ━━━ ".as_bytes()).unwrap();
    stdout.reset().unwrap();

    stdout.color(ERROR_FG).unwrap();
    stdout.write(b"second closure is constructed here\n").unwrap();
    stdout.reset().unwrap();

    stdout.color(LINE_NUM_FG).unwrap();
    stdout.bg_color(LINE_NUM_BG).unwrap();
    stdout.write(b"83 ").unwrap();
    stdout.reset().unwrap();

    stdout.write(b"         vec.push(e)\n").unwrap();

    stdout.color(LINE_NUM_FG).unwrap();
    stdout.bg_color(LINE_NUM_BG).unwrap();
    stdout.write(INFO_LINE.as_bytes()).unwrap();
    stdout.reset().unwrap();
    stdout.color(Color::Red).unwrap();
    stdout.write("         ━━━ ".as_bytes()).unwrap();
    stdout.reset().unwrap();

    stdout.color(ERROR_FG).unwrap();
    stdout.write(b"borrow occurs due to use of `vec` in closure\n").unwrap();
    stdout.reset().unwrap();

    stdout.color(LINE_NUM_FG).unwrap();
    stdout.bg_color(LINE_NUM_BG).unwrap();
    stdout.write(b"84 ").unwrap();
    stdout.reset().unwrap();
    stdout.write(b"     };\n").unwrap();

    stdout.color(LINE_NUM_FG).unwrap();
    stdout.bg_color(LINE_NUM_BG).unwrap();
    stdout.write(b"85 ").unwrap();
    stdout.reset().unwrap();
    stdout.write(b" }\n").unwrap();

    stdout.color(LINE_NUM_FG).unwrap();
    stdout.bg_color(LINE_NUM_BG).unwrap();
    stdout.write(INFO_LINE.as_bytes()).unwrap();
    stdout.reset().unwrap();
    stdout.color(Color::Red).unwrap();
    stdout.write(" ━ ".as_bytes()).unwrap();
    stdout.reset().unwrap();

    stdout.color(ERROR_FG).unwrap();
    stdout.write(b"borrow from first closure ends here\n").unwrap();
    stdout.reset().unwrap();
}
<|endoftext|>


<commit_before>// Copyright 2014-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.

use core::ptr::PtrExt;

// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`

/// Return a pointer to `size` bytes of memory aligned to `align`.
///
/// On failure, return a null pointer.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
#[inline]
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
    imp::allocate(size, align)
}

/// Resize the allocation referenced by `ptr` to `size` bytes.
///
/// On failure, return a null pointer and leave the original allocation intact.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 {
    imp::reallocate(ptr, old_size, size, align)
}

/// Resize the allocation referenced by `ptr` to `size` bytes.
///
/// If the operation succeeds, it returns `usable_size(size, align)` and if it
/// fails (or is a no-op) it returns `usable_size(old_size, align)`.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> uint {
    imp::reallocate_inplace(ptr, old_size, size, align)
}

/// Deallocates the memory referenced by `ptr`.
///
/// The `ptr` parameter must not be null.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
    imp::deallocate(ptr, old_size, align)
}

/// Returns the usable size of an allocation created with the specified the
/// `size` and `align`.
#[inline]
pub fn usable_size(size: uint, align: uint) -> uint {
    imp::usable_size(size, align)
}

/// Prints implementation-defined allocator statistics.
///
/// These statistics may be inconsistent if other threads use the allocator
/// during the call.
#[unstable]
pub fn stats_print() {
    imp::stats_print();
}

/// An arbitrary non-null address to represent zero-size allocations.
///
/// This preserves the non-null invariant for types like `Box<T>`. The address may overlap with
/// non-zero-size memory allocations.
pub const EMPTY: *mut () = 0x1 as *mut ();

/// The allocator for unique pointers.
#[cfg(not(test))]
#[lang="exchange_malloc"]
#[inline]
unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 {
    if size == 0 {
        EMPTY as *mut u8
    } else {
        let ptr = allocate(size, align);
        if ptr.is_null() { ::oom() }
        ptr
    }
}

#[cfg(not(test))]
#[lang="exchange_free"]
#[inline]
unsafe fn exchange_free(ptr: *mut u8, old_size: uint, align: uint) {
    deallocate(ptr, old_size, align);
}

// The minimum alignment guaranteed by the architecture. This value is used to
// add fast paths for low alignment values. In practice, the alignment is a
// constant at the call site and the branch will be optimized out.
#[cfg(any(target_arch = "arm",
          target_arch = "mips",
          target_arch = "mipsel"))]
const MIN_ALIGN: uint = 8;
#[cfg(any(target_arch = "x86",
          target_arch = "x86_64",
          target_arch = "aarch64"))]
const MIN_ALIGN: uint = 16;

#[cfg(feature = "external_funcs")]
mod imp {
    extern {
        fn rust_allocate(size: uint, align: uint) -> *mut u8;
        fn rust_deallocate(ptr: *mut u8, old_size: uint, align: uint);
        fn rust_reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8;
        fn rust_reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint,
                                   align: uint) -> uint;
        fn rust_usable_size(size: uint, align: uint) -> uint;
        fn rust_stats_print();
    }

    #[inline]
    pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
        rust_allocate(size, align)
    }

    #[inline]
    pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
        rust_deallocate(ptr, old_size, align)
    }

    #[inline]
    pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 {
        rust_reallocate(ptr, old_size, size, align)
    }

    #[inline]
    pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint,
                                     align: uint) -> uint {
        rust_reallocate_inplace(ptr, old_size, size, align)
    }

    #[inline]
    pub fn usable_size(size: uint, align: uint) -> uint {
        unsafe { rust_usable_size(size, align) }
    }

    #[inline]
    pub fn stats_print() {
        unsafe { rust_stats_print() }
    }
}

#[cfg(feature = "external_crate")]
mod imp {
    extern crate external;
    pub use self::external::{allocate, deallocate, reallocate_inplace, reallocate};
    pub use self::external::{usable_size, stats_print};
}

#[cfg(all(not(feature = "external_funcs"),
          not(feature = "external_crate"),
          jemalloc))]
mod imp {
    use core::option::Option;
    use core::option::Option::None;
    use core::ptr::{null_mut, null};
    use core::num::Int;
    use libc::{c_char, c_int, c_void, size_t};
    use super::MIN_ALIGN;

    #[link(name = "jemalloc", kind = "static")]
    #[cfg(not(test))]
    extern {}

    extern {
        fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void;
        fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
        fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
        fn je_sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
        fn je_nallocx(size: size_t, flags: c_int) -> size_t;
        fn je_malloc_stats_print(write_cb: Option<extern "C" fn(cbopaque: *mut c_void,
                                                                *const c_char)>,
                                 cbopaque: *mut c_void,
                                 opts: *const c_char);
    }

    // -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
    #[cfg(all(not(windows), not(target_os = "android")))]
    #[link(name = "pthread")]
    extern {}

    // MALLOCX_ALIGN(a) macro
    #[inline(always)]
    fn mallocx_align(a: uint) -> c_int { a.trailing_zeros() as c_int }

    #[inline(always)]
    fn align_to_flags(align: uint) -> c_int {
        if align <= MIN_ALIGN { 0 } else { mallocx_align(align) }
    }

    #[inline]
    pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
        let flags = align_to_flags(align);
        je_mallocx(size as size_t, flags) as *mut u8
    }

    #[inline]
    pub unsafe fn reallocate(ptr: *mut u8, _old_size: uint, size: uint, align: uint) -> *mut u8 {
        let flags = align_to_flags(align);
        je_rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8
    }

    #[inline]
    pub unsafe fn reallocate_inplace(ptr: *mut u8, _old_size: uint, size: uint,
                                     align: uint) -> uint {
        let flags = align_to_flags(align);
        je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as uint
    }

    #[inline]
    pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
        let flags = align_to_flags(align);
        je_sdallocx(ptr as *mut c_void, old_size as size_t, flags)
    }

    #[inline]
    pub fn usable_size(size: uint, align: uint) -> uint {
        let flags = align_to_flags(align);
        unsafe { je_nallocx(size as size_t, flags) as uint }
    }

    pub fn stats_print() {
        unsafe {
            je_malloc_stats_print(None, null_mut(), null())
        }
    }
}

#[cfg(all(not(feature = "external_funcs"),
          not(feature = "external_crate"),
          not(jemalloc),
          unix))]
mod imp {
    use core::cmp;
    use core::ptr;
    use libc;
    use super::MIN_ALIGN;

    extern {
        fn posix_memalign(memptr: *mut *mut libc::c_void,
                          align: libc::size_t,
                          size: libc::size_t) -> libc::c_int;
    }

    #[inline]
    pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::malloc(size as libc::size_t) as *mut u8
        } else {
            let mut out = 0 as *mut libc::c_void;
            let ret = posix_memalign(&mut out,
                                     align as libc::size_t,
                                     size as libc::size_t);
            if ret != 0 {
                ptr::null_mut()
            } else {
                out as *mut u8
            }
        }
    }

    #[inline]
    pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
        } else {
            let new_ptr = allocate(size, align);
            ptr::copy_memory(new_ptr, ptr as *const u8, cmp::min(size, old_size));
            deallocate(ptr, old_size, align);
            new_ptr
        }
    }

    #[inline]
    pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: uint, _size: uint,
                                     _align: uint) -> uint {
        old_size
    }

    #[inline]
    pub unsafe fn deallocate(ptr: *mut u8, _old_size: uint, _align: uint) {
        libc::free(ptr as *mut libc::c_void)
    }

    #[inline]
    pub fn usable_size(size: uint, _align: uint) -> uint {
        size
    }

    pub fn stats_print() {}
}

#[cfg(all(not(feature = "external_funcs"),
          not(feature = "external_crate"),
          not(jemalloc),
          windows))]
mod imp {
    use libc::{c_void, size_t};
    use libc;
    use super::MIN_ALIGN;

    extern {
        fn _aligned_malloc(size: size_t, align: size_t) -> *mut c_void;
        fn _aligned_realloc(block: *mut c_void, size: size_t,
                            align: size_t) -> *mut c_void;
        fn _aligned_free(ptr: *mut c_void);
    }

    #[inline]
    pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::malloc(size as size_t) as *mut u8
        } else {
            _aligned_malloc(size as size_t, align as size_t) as *mut u8
        }
    }

    #[inline]
    pub unsafe fn reallocate(ptr: *mut u8, _old_size: uint, size: uint, align: uint) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::realloc(ptr as *mut c_void, size as size_t) as *mut u8
        } else {
            _aligned_realloc(ptr as *mut c_void, size as size_t, align as size_t) as *mut u8
        }
    }

    #[inline]
    pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: uint, _size: uint,
                                     _align: uint) -> uint {
        old_size
    }

    #[inline]
    pub unsafe fn deallocate(ptr: *mut u8, _old_size: uint, align: uint) {
        if align <= MIN_ALIGN {
            libc::free(ptr as *mut libc::c_void)
        } else {
            _aligned_free(ptr as *mut c_void)
        }
    }

    #[inline]
    pub fn usable_size(size: uint, _align: uint) -> uint {
        size
    }

    pub fn stats_print() {}
}

#[cfg(test)]
mod test {
    extern crate test;
    use self::test::Bencher;
    use core::ptr::PtrExt;
    use heap;

    #[test]
    fn basic_reallocate_inplace_noop() {
        unsafe {
            let size = 4000;
            let ptr = heap::allocate(size, 8);
            if ptr.is_null() { ::oom() }
            let ret = heap::reallocate_inplace(ptr, size, size, 8);
            heap::deallocate(ptr, size, 8);
            assert_eq!(ret, heap::usable_size(size, 8));
        }
    }

    #[bench]
    fn alloc_owned_small(b: &mut Bencher) {
        b.iter(|| {
            box 10i
        })
    }
}
<commit_msg>Fix warning in liballoc about unused constant MIN_ALIGN when cfg(feature = external_*)<commit_after>// Copyright 2014-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.

use core::ptr::PtrExt;

// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`

/// Return a pointer to `size` bytes of memory aligned to `align`.
///
/// On failure, return a null pointer.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
#[inline]
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
    imp::allocate(size, align)
}

/// Resize the allocation referenced by `ptr` to `size` bytes.
///
/// On failure, return a null pointer and leave the original allocation intact.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 {
    imp::reallocate(ptr, old_size, size, align)
}

/// Resize the allocation referenced by `ptr` to `size` bytes.
///
/// If the operation succeeds, it returns `usable_size(size, align)` and if it
/// fails (or is a no-op) it returns `usable_size(old_size, align)`.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> uint {
    imp::reallocate_inplace(ptr, old_size, size, align)
}

/// Deallocates the memory referenced by `ptr`.
///
/// The `ptr` parameter must not be null.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
    imp::deallocate(ptr, old_size, align)
}

/// Returns the usable size of an allocation created with the specified the
/// `size` and `align`.
#[inline]
pub fn usable_size(size: uint, align: uint) -> uint {
    imp::usable_size(size, align)
}

/// Prints implementation-defined allocator statistics.
///
/// These statistics may be inconsistent if other threads use the allocator
/// during the call.
#[unstable]
pub fn stats_print() {
    imp::stats_print();
}

/// An arbitrary non-null address to represent zero-size allocations.
///
/// This preserves the non-null invariant for types like `Box<T>`. The address may overlap with
/// non-zero-size memory allocations.
pub const EMPTY: *mut () = 0x1 as *mut ();

/// The allocator for unique pointers.
#[cfg(not(test))]
#[lang="exchange_malloc"]
#[inline]
unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 {
    if size == 0 {
        EMPTY as *mut u8
    } else {
        let ptr = allocate(size, align);
        if ptr.is_null() { ::oom() }
        ptr
    }
}

#[cfg(not(test))]
#[lang="exchange_free"]
#[inline]
unsafe fn exchange_free(ptr: *mut u8, old_size: uint, align: uint) {
    deallocate(ptr, old_size, align);
}

// The minimum alignment guaranteed by the architecture. This value is used to
// add fast paths for low alignment values. In practice, the alignment is a
// constant at the call site and the branch will be optimized out.
#[cfg(all(not(feature = "external_funcs"),
          not(feature = "external_crate"),
          any(target_arch = "arm",
              target_arch = "mips",
              target_arch = "mipsel")))]
const MIN_ALIGN: uint = 8;
#[cfg(all(not(feature = "external_funcs"),
          not(feature = "external_crate"),
          any(target_arch = "x86",
              target_arch = "x86_64",
              target_arch = "aarch64"))]
const MIN_ALIGN: uint = 16;

#[cfg(feature = "external_funcs")]
mod imp {
    extern {
        fn rust_allocate(size: uint, align: uint) -> *mut u8;
        fn rust_deallocate(ptr: *mut u8, old_size: uint, align: uint);
        fn rust_reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8;
        fn rust_reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint,
                                   align: uint) -> uint;
        fn rust_usable_size(size: uint, align: uint) -> uint;
        fn rust_stats_print();
    }

    #[inline]
    pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
        rust_allocate(size, align)
    }

    #[inline]
    pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
        rust_deallocate(ptr, old_size, align)
    }

    #[inline]
    pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 {
        rust_reallocate(ptr, old_size, size, align)
    }

    #[inline]
    pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint,
                                     align: uint) -> uint {
        rust_reallocate_inplace(ptr, old_size, size, align)
    }

    #[inline]
    pub fn usable_size(size: uint, align: uint) -> uint {
        unsafe { rust_usable_size(size, align) }
    }

    #[inline]
    pub fn stats_print() {
        unsafe { rust_stats_print() }
    }
}

#[cfg(feature = "external_crate")]
mod imp {
    extern crate external;
    pub use self::external::{allocate, deallocate, reallocate_inplace, reallocate};
    pub use self::external::{usable_size, stats_print};
}

#[cfg(all(not(feature = "external_funcs"),
          not(feature = "external_crate"),
          jemalloc))]
mod imp {
    use core::option::Option;
    use core::option::Option::None;
    use core::ptr::{null_mut, null};
    use core::num::Int;
    use libc::{c_char, c_int, c_void, size_t};
    use super::MIN_ALIGN;

    #[link(name = "jemalloc", kind = "static")]
    #[cfg(not(test))]
    extern {}

    extern {
        fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void;
        fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
        fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
        fn je_sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
        fn je_nallocx(size: size_t, flags: c_int) -> size_t;
        fn je_malloc_stats_print(write_cb: Option<extern "C" fn(cbopaque: *mut c_void,
                                                                *const c_char)>,
                                 cbopaque: *mut c_void,
                                 opts: *const c_char);
    }

    // -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
    #[cfg(all(not(windows), not(target_os = "android")))]
    #[link(name = "pthread")]
    extern {}

    // MALLOCX_ALIGN(a) macro
    #[inline(always)]
    fn mallocx_align(a: uint) -> c_int { a.trailing_zeros() as c_int }

    #[inline(always)]
    fn align_to_flags(align: uint) -> c_int {
        if align <= MIN_ALIGN { 0 } else { mallocx_align(align) }
    }

    #[inline]
    pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
        let flags = align_to_flags(align);
        je_mallocx(size as size_t, flags) as *mut u8
    }

    #[inline]
    pub unsafe fn reallocate(ptr: *mut u8, _old_size: uint, size: uint, align: uint) -> *mut u8 {
        let flags = align_to_flags(align);
        je_rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8
    }

    #[inline]
    pub unsafe fn reallocate_inplace(ptr: *mut u8, _old_size: uint, size: uint,
                                     align: uint) -> uint {
        let flags = align_to_flags(align);
        je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as uint
    }

    #[inline]
    pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
        let flags = align_to_flags(align);
        je_sdallocx(ptr as *mut c_void, old_size as size_t, flags)
    }

    #[inline]
    pub fn usable_size(size: uint, align: uint) -> uint {
        let flags = align_to_flags(align);
        unsafe { je_nallocx(size as size_t, flags) as uint }
    }

    pub fn stats_print() {
        unsafe {
            je_malloc_stats_print(None, null_mut(), null())
        }
    }
}

#[cfg(all(not(feature = "external_funcs"),
          not(feature = "external_crate"),
          not(jemalloc),
          unix))]
mod imp {
    use core::cmp;
    use core::ptr;
    use libc;
    use super::MIN_ALIGN;

    extern {
        fn posix_memalign(memptr: *mut *mut libc::c_void,
                          align: libc::size_t,
                          size: libc::size_t) -> libc::c_int;
    }

    #[inline]
    pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::malloc(size as libc::size_t) as *mut u8
        } else {
            let mut out = 0 as *mut libc::c_void;
            let ret = posix_memalign(&mut out,
                                     align as libc::size_t,
                                     size as libc::size_t);
            if ret != 0 {
                ptr::null_mut()
            } else {
                out as *mut u8
            }
        }
    }

    #[inline]
    pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
        } else {
            let new_ptr = allocate(size, align);
            ptr::copy_memory(new_ptr, ptr as *const u8, cmp::min(size, old_size));
            deallocate(ptr, old_size, align);
            new_ptr
        }
    }

    #[inline]
    pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: uint, _size: uint,
                                     _align: uint) -> uint {
        old_size
    }

    #[inline]
    pub unsafe fn deallocate(ptr: *mut u8, _old_size: uint, _align: uint) {
        libc::free(ptr as *mut libc::c_void)
    }

    #[inline]
    pub fn usable_size(size: uint, _align: uint) -> uint {
        size
    }

    pub fn stats_print() {}
}

#[cfg(all(not(feature = "external_funcs"),
          not(feature = "external_crate"),
          not(jemalloc),
          windows))]
mod imp {
    use libc::{c_void, size_t};
    use libc;
    use super::MIN_ALIGN;

    extern {
        fn _aligned_malloc(size: size_t, align: size_t) -> *mut c_void;
        fn _aligned_realloc(block: *mut c_void, size: size_t,
                            align: size_t) -> *mut c_void;
        fn _aligned_free(ptr: *mut c_void);
    }

    #[inline]
    pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::malloc(size as size_t) as *mut u8
        } else {
            _aligned_malloc(size as size_t, align as size_t) as *mut u8
        }
    }

    #[inline]
    pub unsafe fn reallocate(ptr: *mut u8, _old_size: uint, size: uint, align: uint) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::realloc(ptr as *mut c_void, size as size_t) as *mut u8
        } else {
            _aligned_realloc(ptr as *mut c_void, size as size_t, align as size_t) as *mut u8
        }
    }

    #[inline]
    pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: uint, _size: uint,
                                     _align: uint) -> uint {
        old_size
    }

    #[inline]
    pub unsafe fn deallocate(ptr: *mut u8, _old_size: uint, align: uint) {
        if align <= MIN_ALIGN {
            libc::free(ptr as *mut libc::c_void)
        } else {
            _aligned_free(ptr as *mut c_void)
        }
    }

    #[inline]
    pub fn usable_size(size: uint, _align: uint) -> uint {
        size
    }

    pub fn stats_print() {}
}

#[cfg(test)]
mod test {
    extern crate test;
    use self::test::Bencher;
    use core::ptr::PtrExt;
    use heap;

    #[test]
    fn basic_reallocate_inplace_noop() {
        unsafe {
            let size = 4000;
            let ptr = heap::allocate(size, 8);
            if ptr.is_null() { ::oom() }
            let ret = heap::reallocate_inplace(ptr, size, size, 8);
            heap::deallocate(ptr, size, 8);
            assert_eq!(ret, heap::usable_size(size, 8));
        }
    }

    #[bench]
    fn alloc_owned_small(b: &mut Bencher) {
        b.iter(|| {
            box 10i
        })
    }
}
<|endoftext|>


<commit_before><commit_msg>Main example for bigint usage.<commit_after><|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.

use spec::{LinkerFlavor, LldFlavor, PanicStrategy,
           Target, TargetOptions, TargetResult};
use spec::abi::{Abi};

pub fn target() -> TargetResult {
    Ok(Target {
        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
        llvm_target: "riscv32".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        target_os: "none".to_string(),
        target_env: String::new(),
        target_vendor: "unknown".to_string(),
        arch: "riscv32".to_string(),
        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),

        options: TargetOptions {
            linker: Some("rust-lld".to_string()),
            cpu: "generic-rv32".to_string(),
            max_atomic_width: Some(32),
            atomic_cas: false, // incomplete +a extension
            features: "+m,+a".to_string(), // disable +c extension
            executables: true,
            panic_strategy: PanicStrategy::Abort,
            relocation_model: "static".to_string(),
            emit_debug_gdb_scripts: false,
            abi_blacklist: vec![
                Abi::Cdecl,
                Abi::Stdcall,
                Abi::Fastcall,
                Abi::Vectorcall,
                Abi::Thiscall,
                Abi::Aapcs,
                Abi::Win64,
                Abi::SysV64,
                Abi::PtxKernel,
                Abi::Msp430Interrupt,
                Abi::X86Interrupt,
            ],
            .. Default::default()
        },
    })
}
<commit_msg>[RISCV] Enable C extension.<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.

use spec::{LinkerFlavor, LldFlavor, PanicStrategy,
           Target, TargetOptions, TargetResult};
use spec::abi::{Abi};

pub fn target() -> TargetResult {
    Ok(Target {
        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
        llvm_target: "riscv32".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        target_os: "none".to_string(),
        target_env: String::new(),
        target_vendor: "unknown".to_string(),
        arch: "riscv32".to_string(),
        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),

        options: TargetOptions {
            linker: Some("rust-lld".to_string()),
            cpu: "generic-rv32".to_string(),
            max_atomic_width: Some(32),
            atomic_cas: false, // incomplete +a extension
            features: "+m,+a,+c".to_string(),
            executables: true,
            panic_strategy: PanicStrategy::Abort,
            relocation_model: "static".to_string(),
            emit_debug_gdb_scripts: false,
            abi_blacklist: vec![
                Abi::Cdecl,
                Abi::Stdcall,
                Abi::Fastcall,
                Abi::Vectorcall,
                Abi::Thiscall,
                Abi::Aapcs,
                Abi::Win64,
                Abi::SysV64,
                Abi::PtxKernel,
                Abi::Msp430Interrupt,
                Abi::X86Interrupt,
            ],
            .. Default::default()
        },
    })
}
<|endoftext|>


<commit_before><commit_msg>Added an example with dynamic bar creation<commit_after>extern crate indicatif;

use std::thread;
use std::time::Duration;
use std::sync::Arc;

use indicatif::{ProgressBar, MultiProgress, ProgressStyle};

fn main() {
    let m = Arc::new(MultiProgress::new());
    let sty = ProgressStyle::default_bar()
        .template("{bar:40.green/yellow} {pos:>7}/{len:7}")
        .progress_chars("##-");

    let pb = m.add(ProgressBar::new(5));
    pb.set_style(sty.clone());

    let m2 = m.clone();
    let _ = thread::spawn(move || {
        // make sure we show up at all.  otherwise no rendering
        // event.
        pb.tick();
        for _ in 0..5 {
            let pb2 = m2.add(ProgressBar::new(128));
            pb2.set_style(sty.clone());
            for _ in 0..128 {
                pb2.inc(1);
                thread::sleep(Duration::from_millis(5));
            }
            pb2.finish();
            pb.inc(1);
        }
        pb.finish_with_message("done");
    });

    m.join().unwrap();
}
<|endoftext|>


<commit_before><commit_msg>add test for caller ABI check<commit_after>fn main() {
    extern "Rust" {
        fn malloc(size: usize) -> *mut std::ffi::c_void;
    }

    unsafe {
        let _ = malloc(0); //~ ERROR calling a function with ABI C using caller ABI Rust
    };
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

//! Operations on tuples
//!
//! To access a single element of a tuple one can use the following
//! methods:
//!
//! * `valN` - returns a value of _N_-th element
//! * `refN` - returns a reference to _N_-th element
//! * `mutN` - returns a mutable reference to _N_-th element
//!
//! Indexing starts from zero, so `val0` returns first value, `val1`
//! returns second value, and so on. In general, a tuple with _S_
//! elements provides aforementioned methods suffixed with numbers
//! from `0` to `S-1`. Traits which contain these methods are
//! implemented for tuples with up to 12 elements.
//!
//! If every type inside a tuple implements one of the following
//! traits, then a tuple itself also implements it.
//!
//! * `Clone`
//! * `PartialEq`
//! * `Eq`
//! * `PartialOrd`
//! * `Ord`
//! * `Default`

#![stable]

#[unstable = "this is just a documentation module and should not be part \
              of the public api"]

use clone::Clone;
use cmp::*;
use cmp::Ordering::*;
use default::Default;
use option::Option;
use option::Option::Some;

// FIXME(#19630) Remove this work-around
macro_rules! e {
    ($e:expr) => { $e }
}

// macro for implementing n-ary tuple functions and operations
macro_rules! tuple_impls {
    ($(
        $Tuple:ident {
            $(($valN:ident, $refN:ident, $mutN:ident, $idx:tt) -> $T:ident)+
        }
    )+) => {
        $(
            #[stable]
            impl<$($T:Clone),+> Clone for ($($T,)+) {
                fn clone(&self) -> ($($T,)+) {
                    ($(e!(self.$idx.clone()),)+)
                }
            }

            #[stable]
            impl<$($T:PartialEq),+> PartialEq for ($($T,)+) {
                #[inline]
                fn eq(&self, other: &($($T,)+)) -> bool {
                    e!($(self.$idx == other.$idx)&&+)
                }
                #[inline]
                fn ne(&self, other: &($($T,)+)) -> bool {
                    e!($(self.$idx != other.$idx)||+)
                }
            }

            #[stable]
            impl<$($T:Eq),+> Eq for ($($T,)+) {}

            #[stable]
            impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) {
                #[inline]
                fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> {
                    lexical_partial_cmp!($(self.$idx, other.$idx),+)
                }
                #[inline]
                fn lt(&self, other: &($($T,)+)) -> bool {
                    lexical_ord!(lt, $(self.$idx, other.$idx),+)
                }
                #[inline]
                fn le(&self, other: &($($T,)+)) -> bool {
                    lexical_ord!(le, $(self.$idx, other.$idx),+)
                }
                #[inline]
                fn ge(&self, other: &($($T,)+)) -> bool {
                    lexical_ord!(ge, $(self.$idx, other.$idx),+)
                }
                #[inline]
                fn gt(&self, other: &($($T,)+)) -> bool {
                    lexical_ord!(gt, $(self.$idx, other.$idx),+)
                }
            }

            #[stable]
            impl<$($T:Ord),+> Ord for ($($T,)+) {
                #[inline]
                fn cmp(&self, other: &($($T,)+)) -> Ordering {
                    lexical_cmp!($(self.$idx, other.$idx),+)
                }
            }

            #[stable]
            impl<$($T:Default),+> Default for ($($T,)+) {
                #[stable]
                #[inline]
                fn default() -> ($($T,)+) {
                    ($({ let x: $T = Default::default(); x},)+)
                }
            }
        )+
    }
}

// Constructs an expression that performs a lexical ordering using method $rel.
// The values are interleaved, so the macro invocation for
// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, a1, b1, a2, b2,
// a3, b3)` (and similarly for `lexical_cmp`)
macro_rules! lexical_ord {
    ($rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
        if $a != $b { lexical_ord!($rel, $a, $b) }
        else { lexical_ord!($rel, $($rest_a, $rest_b),+) }
    };
    ($rel: ident, $a:expr, $b:expr) => { ($a) . $rel (& $b) };
}

macro_rules! lexical_partial_cmp {
    ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
        match ($a).partial_cmp(&$b) {
            Some(Equal) => lexical_partial_cmp!($($rest_a, $rest_b),+),
            ordering   => ordering
        }
    };
    ($a:expr, $b:expr) => { ($a).partial_cmp(&$b) };
}

macro_rules! lexical_cmp {
    ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
        match ($a).cmp(&$b) {
            Equal => lexical_cmp!($($rest_a, $rest_b),+),
            ordering   => ordering
        }
    };
    ($a:expr, $b:expr) => { ($a).cmp(&$b) };
}

tuple_impls! {
    Tuple1 {
        (val0, ref0, mut0, 0) -> A
    }
    Tuple2 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
    }
    Tuple3 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
    }
    Tuple4 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
    }
    Tuple5 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
        (val4, ref4, mut4, 4) -> E
    }
    Tuple6 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
        (val4, ref4, mut4, 4) -> E
        (val5, ref5, mut5, 5) -> F
    }
    Tuple7 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
        (val4, ref4, mut4, 4) -> E
        (val5, ref5, mut5, 5) -> F
        (val6, ref6, mut6, 6) -> G
    }
    Tuple8 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
        (val4, ref4, mut4, 4) -> E
        (val5, ref5, mut5, 5) -> F
        (val6, ref6, mut6, 6) -> G
        (val7, ref7, mut7, 7) -> H
    }
    Tuple9 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
        (val4, ref4, mut4, 4) -> E
        (val5, ref5, mut5, 5) -> F
        (val6, ref6, mut6, 6) -> G
        (val7, ref7, mut7, 7) -> H
        (val8, ref8, mut8, 8) -> I
    }
    Tuple10 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
        (val4, ref4, mut4, 4) -> E
        (val5, ref5, mut5, 5) -> F
        (val6, ref6, mut6, 6) -> G
        (val7, ref7, mut7, 7) -> H
        (val8, ref8, mut8, 8) -> I
        (val9, ref9, mut9, 9) -> J
    }
    Tuple11 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
        (val4, ref4, mut4, 4) -> E
        (val5, ref5, mut5, 5) -> F
        (val6, ref6, mut6, 6) -> G
        (val7, ref7, mut7, 7) -> H
        (val8, ref8, mut8, 8) -> I
        (val9, ref9, mut9, 9) -> J
        (val10, ref10, mut10, 10) -> K
    }
    Tuple12 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
        (val4, ref4, mut4, 4) -> E
        (val5, ref5, mut5, 5) -> F
        (val6, ref6, mut6, 6) -> G
        (val7, ref7, mut7, 7) -> H
        (val8, ref8, mut8, 8) -> I
        (val9, ref9, mut9, 9) -> J
        (val10, ref10, mut10, 10) -> K
        (val11, ref11, mut11, 11) -> L
    }
}
<commit_msg>rollup merge of #21172: brson/tuple<commit_after>// Copyright 2012 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.

//! Operations on tuples
//!
//! To access a single element of a tuple one can use the following
//! methods:
//!
//! * `valN` - returns a value of _N_-th element
//! * `refN` - returns a reference to _N_-th element
//! * `mutN` - returns a mutable reference to _N_-th element
//!
//! Indexing starts from zero, so `val0` returns first value, `val1`
//! returns second value, and so on. In general, a tuple with _S_
//! elements provides aforementioned methods suffixed with numbers
//! from `0` to `S-1`. Traits which contain these methods are
//! implemented for tuples with up to 12 elements.
//!
//! If every type inside a tuple implements one of the following
//! traits, then a tuple itself also implements it.
//!
//! * `Clone`
//! * `PartialEq`
//! * `Eq`
//! * `PartialOrd`
//! * `Ord`
//! * `Default`

#![stable]

use clone::Clone;
use cmp::*;
use cmp::Ordering::*;
use default::Default;
use option::Option;
use option::Option::Some;

// FIXME(#19630) Remove this work-around
macro_rules! e {
    ($e:expr) => { $e }
}

// macro for implementing n-ary tuple functions and operations
macro_rules! tuple_impls {
    ($(
        $Tuple:ident {
            $(($valN:ident, $refN:ident, $mutN:ident, $idx:tt) -> $T:ident)+
        }
    )+) => {
        $(
            #[stable]
            impl<$($T:Clone),+> Clone for ($($T,)+) {
                fn clone(&self) -> ($($T,)+) {
                    ($(e!(self.$idx.clone()),)+)
                }
            }

            #[stable]
            impl<$($T:PartialEq),+> PartialEq for ($($T,)+) {
                #[inline]
                fn eq(&self, other: &($($T,)+)) -> bool {
                    e!($(self.$idx == other.$idx)&&+)
                }
                #[inline]
                fn ne(&self, other: &($($T,)+)) -> bool {
                    e!($(self.$idx != other.$idx)||+)
                }
            }

            #[stable]
            impl<$($T:Eq),+> Eq for ($($T,)+) {}

            #[stable]
            impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) {
                #[inline]
                fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> {
                    lexical_partial_cmp!($(self.$idx, other.$idx),+)
                }
                #[inline]
                fn lt(&self, other: &($($T,)+)) -> bool {
                    lexical_ord!(lt, $(self.$idx, other.$idx),+)
                }
                #[inline]
                fn le(&self, other: &($($T,)+)) -> bool {
                    lexical_ord!(le, $(self.$idx, other.$idx),+)
                }
                #[inline]
                fn ge(&self, other: &($($T,)+)) -> bool {
                    lexical_ord!(ge, $(self.$idx, other.$idx),+)
                }
                #[inline]
                fn gt(&self, other: &($($T,)+)) -> bool {
                    lexical_ord!(gt, $(self.$idx, other.$idx),+)
                }
            }

            #[stable]
            impl<$($T:Ord),+> Ord for ($($T,)+) {
                #[inline]
                fn cmp(&self, other: &($($T,)+)) -> Ordering {
                    lexical_cmp!($(self.$idx, other.$idx),+)
                }
            }

            #[stable]
            impl<$($T:Default),+> Default for ($($T,)+) {
                #[stable]
                #[inline]
                fn default() -> ($($T,)+) {
                    ($({ let x: $T = Default::default(); x},)+)
                }
            }
        )+
    }
}

// Constructs an expression that performs a lexical ordering using method $rel.
// The values are interleaved, so the macro invocation for
// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, a1, b1, a2, b2,
// a3, b3)` (and similarly for `lexical_cmp`)
macro_rules! lexical_ord {
    ($rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
        if $a != $b { lexical_ord!($rel, $a, $b) }
        else { lexical_ord!($rel, $($rest_a, $rest_b),+) }
    };
    ($rel: ident, $a:expr, $b:expr) => { ($a) . $rel (& $b) };
}

macro_rules! lexical_partial_cmp {
    ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
        match ($a).partial_cmp(&$b) {
            Some(Equal) => lexical_partial_cmp!($($rest_a, $rest_b),+),
            ordering   => ordering
        }
    };
    ($a:expr, $b:expr) => { ($a).partial_cmp(&$b) };
}

macro_rules! lexical_cmp {
    ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
        match ($a).cmp(&$b) {
            Equal => lexical_cmp!($($rest_a, $rest_b),+),
            ordering   => ordering
        }
    };
    ($a:expr, $b:expr) => { ($a).cmp(&$b) };
}

tuple_impls! {
    Tuple1 {
        (val0, ref0, mut0, 0) -> A
    }
    Tuple2 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
    }
    Tuple3 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
    }
    Tuple4 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
    }
    Tuple5 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
        (val4, ref4, mut4, 4) -> E
    }
    Tuple6 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
        (val4, ref4, mut4, 4) -> E
        (val5, ref5, mut5, 5) -> F
    }
    Tuple7 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
        (val4, ref4, mut4, 4) -> E
        (val5, ref5, mut5, 5) -> F
        (val6, ref6, mut6, 6) -> G
    }
    Tuple8 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
        (val4, ref4, mut4, 4) -> E
        (val5, ref5, mut5, 5) -> F
        (val6, ref6, mut6, 6) -> G
        (val7, ref7, mut7, 7) -> H
    }
    Tuple9 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
        (val4, ref4, mut4, 4) -> E
        (val5, ref5, mut5, 5) -> F
        (val6, ref6, mut6, 6) -> G
        (val7, ref7, mut7, 7) -> H
        (val8, ref8, mut8, 8) -> I
    }
    Tuple10 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
        (val4, ref4, mut4, 4) -> E
        (val5, ref5, mut5, 5) -> F
        (val6, ref6, mut6, 6) -> G
        (val7, ref7, mut7, 7) -> H
        (val8, ref8, mut8, 8) -> I
        (val9, ref9, mut9, 9) -> J
    }
    Tuple11 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
        (val4, ref4, mut4, 4) -> E
        (val5, ref5, mut5, 5) -> F
        (val6, ref6, mut6, 6) -> G
        (val7, ref7, mut7, 7) -> H
        (val8, ref8, mut8, 8) -> I
        (val9, ref9, mut9, 9) -> J
        (val10, ref10, mut10, 10) -> K
    }
    Tuple12 {
        (val0, ref0, mut0, 0) -> A
        (val1, ref1, mut1, 1) -> B
        (val2, ref2, mut2, 2) -> C
        (val3, ref3, mut3, 3) -> D
        (val4, ref4, mut4, 4) -> E
        (val5, ref5, mut5, 5) -> F
        (val6, ref6, mut6, 6) -> G
        (val7, ref7, mut7, 7) -> H
        (val8, ref8, mut8, 8) -> I
        (val9, ref9, mut9, 9) -> J
        (val10, ref10, mut10, 10) -> K
        (val11, ref11, mut11, 11) -> L
    }
}
<|endoftext|>