<commit_before>/* Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of Dmitry Vyukov.
 */

#![allow(missing_docs, dead_code)]

// http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue

// This queue is copy pasted from old rust stdlib.

use std::sync::Arc;
use std::num::UnsignedInt;
use std::cell::UnsafeCell;

use std::sync::atomic::{AtomicUint,Relaxed,Release,Acquire};

struct Node<T> {
    sequence: AtomicUint,
    value: Option<T>,
}

struct State<T> {
    pad0: [u8, ..64],
    buffer: Vec<UnsafeCell<Node<T>>>,
    mask: uint,
    pad1: [u8, ..64],
    enqueue_pos: AtomicUint,
    pad2: [u8, ..64],
    dequeue_pos: AtomicUint,
    pad3: [u8, ..64],
}

pub struct Queue<T> {
    state: Arc<State<T>>,
}

impl<T: Send> State<T> {
    fn with_capacity(capacity: uint) -> State<T> {
        let capacity = if capacity < 2 || (capacity & (capacity - 1)) != 0 {
            if capacity < 2 {
                2u
            } else {
                // use next power of 2 as capacity
                capacity.next_power_of_two()
            }
        } else {
            capacity
        };
        let buffer = Vec::from_fn(capacity, |i| {
            UnsafeCell::new(Node { sequence:AtomicUint::new(i), value: None })
        });
        State{
            pad0: [0, ..64],
            buffer: buffer,
            mask: capacity-1,
            pad1: [0, ..64],
            enqueue_pos: AtomicUint::new(0),
            pad2: [0, ..64],
            dequeue_pos: AtomicUint::new(0),
            pad3: [0, ..64],
        }
    }

    fn push(&self, value: T) -> bool {
        let mask = self.mask;
        let mut pos = self.enqueue_pos.load(Relaxed);
        loop {
            let node = &self.buffer[pos & mask];
            let seq = unsafe { (*node.get()).sequence.load(Acquire) };
            let diff: int = seq as int - pos as int;

            if diff == 0 {
                let enqueue_pos = self.enqueue_pos.compare_and_swap(pos, pos+1, Relaxed);
                if enqueue_pos == pos {
                    unsafe {
                        (*node.get()).value = Some(value);
                        (*node.get()).sequence.store(pos+1, Release);
                    }
                    break
                } else {
                    pos = enqueue_pos;
                }
            } else if diff < 0 {
                return false
            } else {
                pos = self.enqueue_pos.load(Relaxed);
            }
        }
        true
    }

    fn pop(&self) -> Option<T> {
        let mask = self.mask;
        let mut pos = self.dequeue_pos.load(Relaxed);
        loop {
            let node = &self.buffer[pos & mask];
            let seq = unsafe { (*node.get()).sequence.load(Acquire) };
            let diff: int = seq as int - (pos + 1) as int;
            if diff == 0 {
                let dequeue_pos = self.dequeue_pos.compare_and_swap(pos, pos+1, Relaxed);
                if dequeue_pos == pos {
                    unsafe {
                        let value = (*node.get()).value.take();
                        (*node.get()).sequence.store(pos + mask + 1, Release);
                        return value
                    }
                } else {
                    pos = dequeue_pos;
                }
            } else if diff < 0 {
                return None
            } else {
                pos = self.dequeue_pos.load(Relaxed);
            }
        }
    }
}

impl<T: Send> Queue<T> {
    pub fn with_capacity(capacity: uint) -> Queue<T> {
        Queue{
            state: Arc::new(State::with_capacity(capacity))
        }
    }

    pub fn push(&self, value: T) -> bool {
        self.state.push(value)
    }

    pub fn pop(&self) -> Option<T> {
        self.state.pop()
    }
}

impl<T: Send> Clone for Queue<T> {
    fn clone(&self) -> Queue<T> {
        Queue { state: self.state.clone() }
    }
}

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

    #[test]
    fn test() {
        let nthreads = 8u;
        let nmsgs = 1000u;
        let q = Queue::with_capacity(nthreads*nmsgs);
        assert_eq!(None, q.pop());
        let (tx, rx) = channel();

        for _ in range(0, nthreads) {
            let q = q.clone();
            let tx = tx.clone();
            spawn(proc() {
                let q = q;
                for i in range(0, nmsgs) {
                    assert!(q.push(i));
                }
                tx.send(());
            });
        }

        let mut completion_rxs = vec![];
        for _ in range(0, nthreads) {
            let (tx, rx) = channel();
            completion_rxs.push(rx);
            let q = q.clone();
            spawn(proc() {
                let q = q;
                let mut i = 0u;
                loop {
                    match q.pop() {
                        None => {},
                        Some(_) => {
                            i += 1;
                            if i == nmsgs { break }
                        }
                    }
                }
                tx.send(i);
            });
        }

        for rx in completion_rxs.iter_mut() {
            assert_eq!(nmsgs, rx.recv());
        }
        for _ in range(0, nthreads) {
            rx.recv();
        }
    }
}
<commit_msg>mpmc_queue: fix for the removal of proc().<commit_after>/* Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of Dmitry Vyukov.
 */

#![allow(missing_docs, dead_code)]

// http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue

// This queue is copy pasted from old rust stdlib.

use std::sync::Arc;
use std::num::UnsignedInt;
use std::cell::UnsafeCell;

use std::sync::atomic::{AtomicUint,Relaxed,Release,Acquire};

struct Node<T> {
    sequence: AtomicUint,
    value: Option<T>,
}

struct State<T> {
    pad0: [u8, ..64],
    buffer: Vec<UnsafeCell<Node<T>>>,
    mask: uint,
    pad1: [u8, ..64],
    enqueue_pos: AtomicUint,
    pad2: [u8, ..64],
    dequeue_pos: AtomicUint,
    pad3: [u8, ..64],
}

pub struct Queue<T> {
    state: Arc<State<T>>,
}

impl<T: Send> State<T> {
    fn with_capacity(capacity: uint) -> State<T> {
        let capacity = if capacity < 2 || (capacity & (capacity - 1)) != 0 {
            if capacity < 2 {
                2u
            } else {
                // use next power of 2 as capacity
                capacity.next_power_of_two()
            }
        } else {
            capacity
        };
        let buffer = Vec::from_fn(capacity, |i| {
            UnsafeCell::new(Node { sequence:AtomicUint::new(i), value: None })
        });
        State{
            pad0: [0, ..64],
            buffer: buffer,
            mask: capacity-1,
            pad1: [0, ..64],
            enqueue_pos: AtomicUint::new(0),
            pad2: [0, ..64],
            dequeue_pos: AtomicUint::new(0),
            pad3: [0, ..64],
        }
    }

    fn push(&self, value: T) -> bool {
        let mask = self.mask;
        let mut pos = self.enqueue_pos.load(Relaxed);
        loop {
            let node = &self.buffer[pos & mask];
            let seq = unsafe { (*node.get()).sequence.load(Acquire) };
            let diff: int = seq as int - pos as int;

            if diff == 0 {
                let enqueue_pos = self.enqueue_pos.compare_and_swap(pos, pos+1, Relaxed);
                if enqueue_pos == pos {
                    unsafe {
                        (*node.get()).value = Some(value);
                        (*node.get()).sequence.store(pos+1, Release);
                    }
                    break
                } else {
                    pos = enqueue_pos;
                }
            } else if diff < 0 {
                return false
            } else {
                pos = self.enqueue_pos.load(Relaxed);
            }
        }
        true
    }

    fn pop(&self) -> Option<T> {
        let mask = self.mask;
        let mut pos = self.dequeue_pos.load(Relaxed);
        loop {
            let node = &self.buffer[pos & mask];
            let seq = unsafe { (*node.get()).sequence.load(Acquire) };
            let diff: int = seq as int - (pos + 1) as int;
            if diff == 0 {
                let dequeue_pos = self.dequeue_pos.compare_and_swap(pos, pos+1, Relaxed);
                if dequeue_pos == pos {
                    unsafe {
                        let value = (*node.get()).value.take();
                        (*node.get()).sequence.store(pos + mask + 1, Release);
                        return value
                    }
                } else {
                    pos = dequeue_pos;
                }
            } else if diff < 0 {
                return None
            } else {
                pos = self.dequeue_pos.load(Relaxed);
            }
        }
    }
}

impl<T: Send> Queue<T> {
    pub fn with_capacity(capacity: uint) -> Queue<T> {
        Queue{
            state: Arc::new(State::with_capacity(capacity))
        }
    }

    pub fn push(&self, value: T) -> bool {
        self.state.push(value)
    }

    pub fn pop(&self) -> Option<T> {
        self.state.pop()
    }
}

impl<T: Send> Clone for Queue<T> {
    fn clone(&self) -> Queue<T> {
        Queue { state: self.state.clone() }
    }
}

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

    #[test]
    fn test() {
        let nthreads = 8u;
        let nmsgs = 1000u;
        let q = Queue::with_capacity(nthreads*nmsgs);
        assert_eq!(None, q.pop());
        let (tx, rx) = channel();

        for _ in range(0, nthreads) {
            let q = q.clone();
            let tx = tx.clone();
            spawn(move || {
                let q = q;
                for i in range(0, nmsgs) {
                    assert!(q.push(i));
                }
                tx.send(());
            });
        }

        let mut completion_rxs = vec![];
        for _ in range(0, nthreads) {
            let (tx, rx) = channel();
            completion_rxs.push(rx);
            let q = q.clone();
            spawn(move || {
                let q = q;
                let mut i = 0u;
                loop {
                    match q.pop() {
                        None => {},
                        Some(_) => {
                            i += 1;
                            if i == nmsgs { break }
                        }
                    }
                }
                tx.send(i);
            });
        }

        for rx in completion_rxs.iter_mut() {
            assert_eq!(nmsgs, rx.recv());
        }
        for _ in range(0, nthreads) {
            rx.recv();
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add test case for exported macros vs incremental compilation.<commit_after>// Copyright 2016 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.

// compile-flags: -Zincremental=tmp/cfail-tests/incr_comp_with_macro_export
// must-compile-successfully

// This test case makes sure that we can compile with incremental compilation
// enabled when there are macros exported from this crate. (See #37756)

#![crate_type="rlib"]

#[macro_export]
macro_rules! some_macro {
    ($e:expr) => ($e + 1)
}
<|endoftext|>


<commit_before><commit_msg>use to_wide_null<commit_after><|endoftext|>


<commit_before>extern crate crossbeam;

use std::collections::VecDeque;
use std::sync::Mutex;
use std::sync::mpsc::channel;
use std::time::Duration;

use crossbeam::scope;
use crossbeam::sync::MsQueue;
use crossbeam::sync::SegQueue;

use extra_impls::mpsc_queue::Queue as MpscQueue;

mod extra_impls;

const COUNT: u64 = 10000000;
const THREADS: u64 = 2;

#[cfg(feature = "nightly")]
fn time<F: FnOnce()>(f: F) -> Duration {
    let start = ::std::time::Instant::now();
    f();
    start.elapsed()
}

#[cfg(not(feature = "nightly"))]
fn time<F: FnOnce()>(_f: F) -> Duration {
    Duration::new(0, 0)
}

fn nanos(d: Duration) -> f64 {
    d.as_secs() as f64 * 1000000000f64 + (d.subsec_nanos() as f64)
}

trait Queue<T> {
    fn push(&self, T);
    fn try_pop(&self) -> Option<T>;
}

impl<T> Queue<T> for MsQueue<T> {
    fn push(&self, t: T) { self.push(t) }
    fn try_pop(&self) -> Option<T> { self.try_pop() }
}

impl<T> Queue<T> for SegQueue<T> {
    fn push(&self, t: T) { self.push(t) }
    fn try_pop(&self) -> Option<T> { self.try_pop() }
}

impl<T> Queue<T> for MpscQueue<T> {
    fn push(&self, t: T) { self.push(t) }
    fn try_pop(&self) -> Option<T> {
        use extra_impls::mpsc_queue::*;

        loop {
            match self.pop() {
                Data(t) => return Some(t),
                Empty => return None,
                Inconsistent => (),
            }
        }
    }
}

impl<T> Queue<T> for Mutex<VecDeque<T>> {
    fn push(&self, t: T) { self.lock().unwrap().push_back(t) }
    fn try_pop(&self) -> Option<T> { self.lock().unwrap().pop_front() }
}

fn bench_queue_mpsc<Q: Queue<u64> + Sync>(q: Q) -> f64 {
    let d = time(|| {
        scope(|scope| {
            for _i in 0..THREADS {
                let qr = &q;
                scope.spawn(move || {
                    for x in 0..COUNT {
                        let _ = qr.push(x);
                    }
                });
            }

            let mut count = 0;
            while count < COUNT*THREADS {
                if q.try_pop().is_some() {
                    count += 1;
                }
            }
        });
    });

    nanos(d) / ((COUNT * THREADS) as f64)
}

fn bench_queue_mpmc<Q: Queue<bool> + Sync>(q: Q) -> f64 {
    use std::sync::atomic::AtomicUsize;
    use std::sync::atomic::Ordering::Relaxed;

    let prod_count = AtomicUsize::new(0);

    let d = time(|| {
        scope(|scope| {
            for _i in 0..THREADS {
                let qr = &q;
                let pcr = &prod_count;
                scope.spawn(move || {
                    for _x in 0..COUNT {
                        qr.push(true);
                    }
                    if pcr.fetch_add(1, Relaxed) == (THREADS as usize) - 1 {
                        for _x in 0..THREADS {
                            qr.push(false)
                        }
                    }
                });
                scope.spawn(move || {
                    loop {
                        if let Some(false) = qr.try_pop() { break }
                    }
                });
            }

        });
    });

    nanos(d) / ((COUNT * THREADS) as f64)
}

fn bench_chan_mpsc() -> f64 {
    let (tx, rx) = channel();

    let d = time(|| {
        scope(|scope| {
            for _i in 0..THREADS {
                let my_tx = tx.clone();

                scope.spawn(move || {
                    for x in 0..COUNT {
                        let _ = my_tx.send(x);
                    }
                });
            }

            for _i in 0..COUNT*THREADS {
                let _ = rx.recv().unwrap();
            }
        });
    });

    nanos(d) / ((COUNT * THREADS) as f64)
}

fn main() {
    println!("MSQ mpsc: {}", bench_queue_mpsc(MsQueue::new()));
    println!("chan mpsc: {}", bench_chan_mpsc());
    println!("mpsc mpsc: {}", bench_queue_mpsc(MpscQueue::new()));
    println!("Seg mpsc: {}", bench_queue_mpsc(SegQueue::new()));

    println!("MSQ mpmc: {}", bench_queue_mpmc(MsQueue::new()));
    println!("Seg mpmc: {}", bench_queue_mpmc(SegQueue::new()));

//    println!("queue_mpsc: {}", bench_queue_mpsc());
//    println!("queue_mpmc: {}", bench_queue_mpmc());
//   println!("mutex_mpmc: {}", bench_mutex_mpmc());
}
<commit_msg>Mark `src/bin/bench.rs` non-executable<commit_after>extern crate crossbeam;

use std::collections::VecDeque;
use std::sync::Mutex;
use std::sync::mpsc::channel;
use std::time::Duration;

use crossbeam::scope;
use crossbeam::sync::MsQueue;
use crossbeam::sync::SegQueue;

use extra_impls::mpsc_queue::Queue as MpscQueue;

mod extra_impls;

const COUNT: u64 = 10000000;
const THREADS: u64 = 2;

#[cfg(feature = "nightly")]
fn time<F: FnOnce()>(f: F) -> Duration {
    let start = ::std::time::Instant::now();
    f();
    start.elapsed()
}

#[cfg(not(feature = "nightly"))]
fn time<F: FnOnce()>(_f: F) -> Duration {
    Duration::new(0, 0)
}

fn nanos(d: Duration) -> f64 {
    d.as_secs() as f64 * 1000000000f64 + (d.subsec_nanos() as f64)
}

trait Queue<T> {
    fn push(&self, T);
    fn try_pop(&self) -> Option<T>;
}

impl<T> Queue<T> for MsQueue<T> {
    fn push(&self, t: T) { self.push(t) }
    fn try_pop(&self) -> Option<T> { self.try_pop() }
}

impl<T> Queue<T> for SegQueue<T> {
    fn push(&self, t: T) { self.push(t) }
    fn try_pop(&self) -> Option<T> { self.try_pop() }
}

impl<T> Queue<T> for MpscQueue<T> {
    fn push(&self, t: T) { self.push(t) }
    fn try_pop(&self) -> Option<T> {
        use extra_impls::mpsc_queue::*;

        loop {
            match self.pop() {
                Data(t) => return Some(t),
                Empty => return None,
                Inconsistent => (),
            }
        }
    }
}

impl<T> Queue<T> for Mutex<VecDeque<T>> {
    fn push(&self, t: T) { self.lock().unwrap().push_back(t) }
    fn try_pop(&self) -> Option<T> { self.lock().unwrap().pop_front() }
}

fn bench_queue_mpsc<Q: Queue<u64> + Sync>(q: Q) -> f64 {
    let d = time(|| {
        scope(|scope| {
            for _i in 0..THREADS {
                let qr = &q;
                scope.spawn(move || {
                    for x in 0..COUNT {
                        let _ = qr.push(x);
                    }
                });
            }

            let mut count = 0;
            while count < COUNT*THREADS {
                if q.try_pop().is_some() {
                    count += 1;
                }
            }
        });
    });

    nanos(d) / ((COUNT * THREADS) as f64)
}

fn bench_queue_mpmc<Q: Queue<bool> + Sync>(q: Q) -> f64 {
    use std::sync::atomic::AtomicUsize;
    use std::sync::atomic::Ordering::Relaxed;

    let prod_count = AtomicUsize::new(0);

    let d = time(|| {
        scope(|scope| {
            for _i in 0..THREADS {
                let qr = &q;
                let pcr = &prod_count;
                scope.spawn(move || {
                    for _x in 0..COUNT {
                        qr.push(true);
                    }
                    if pcr.fetch_add(1, Relaxed) == (THREADS as usize) - 1 {
                        for _x in 0..THREADS {
                            qr.push(false)
                        }
                    }
                });
                scope.spawn(move || {
                    loop {
                        if let Some(false) = qr.try_pop() { break }
                    }
                });
            }

        });
    });

    nanos(d) / ((COUNT * THREADS) as f64)
}

fn bench_chan_mpsc() -> f64 {
    let (tx, rx) = channel();

    let d = time(|| {
        scope(|scope| {
            for _i in 0..THREADS {
                let my_tx = tx.clone();

                scope.spawn(move || {
                    for x in 0..COUNT {
                        let _ = my_tx.send(x);
                    }
                });
            }

            for _i in 0..COUNT*THREADS {
                let _ = rx.recv().unwrap();
            }
        });
    });

    nanos(d) / ((COUNT * THREADS) as f64)
}

fn main() {
    println!("MSQ mpsc: {}", bench_queue_mpsc(MsQueue::new()));
    println!("chan mpsc: {}", bench_chan_mpsc());
    println!("mpsc mpsc: {}", bench_queue_mpsc(MpscQueue::new()));
    println!("Seg mpsc: {}", bench_queue_mpsc(SegQueue::new()));

    println!("MSQ mpmc: {}", bench_queue_mpmc(MsQueue::new()));
    println!("Seg mpmc: {}", bench_queue_mpmc(SegQueue::new()));

//    println!("queue_mpsc: {}", bench_queue_mpsc());
//    println!("queue_mpmc: {}", bench_queue_mpmc());
//   println!("mutex_mpmc: {}", bench_mutex_mpmc());
}
<|endoftext|>


<commit_before><commit_msg>Shuffle some comments in fs_notify<commit_after><|endoftext|>


<commit_before><commit_msg>[kernel] first pass on a serial driver<commit_after>use super::{Read, Write, Port};
use ::util;

#[derive(Debug, Copy, Clone)]
#[repr(usize)]
pub enum Serial { Com1 = 0
                , Com2 = 1
                , Com3 = 2
                , Com4 = 3
                }

impl Serial {
    #[inline]
    fn get_port_addr(&self) -> Option<u16> {
        match BDA_SERIAL_INFO[*self as usize] {
            n if n > 0 => Some(n)
          , _ => None
        }
    }

    /// Returns `Some(SerialPort)` if this port exists, `None` if it does not
    pub fn new(&self) -> Option<SerialPort> {
        self.get_port_addr().map(|port| {
            Port::<u8>::new(port + 1).write(0x00);
            Port::<u8>::new(port + 3).write(0x80);
            Port::<u8>::new(port + 0).write(0x03);
            Port::<u8>::new(port + 1).write(0x00);
            Port::<u8>::new(port + 3).write(0x03);
            Port::<u8>::new(port + 2).write(0xC7);
            Port::<u8>::new(port + 4).write(0x0B);
            Port::<u8>::new(port + 1).write(0x01);

            SerialPort { data_port: Port::<u8>::new(port)
                       , status_port: Port::<u8>::new(port + 5)
                       }
        })
    }
}

/// Address of the BIOS Data Area (BDA)
/// where the serial port addresses are stored.
const BDA_ADDR: usize = 0x400;

lazy_static! {
    static ref BDA_SERIAL_INFO: [u16; 4]
        = unsafe { *(BDA_ADDR as *const [u16; 4]) };

}

pub struct SerialPort { data_port: Port<u8>
                      , status_port: Port<u8>
                      }

impl SerialPort {
    /// Returns true if the serial port has recieved data
    #[inline]
    pub fn has_byte(&self) -> bool {
        self.status_port.read() & 1 != 0
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.status_port.read() & 0x20 == 0x20
    }

    #[inline]
    pub fn read_byte(&self) -> u8 {
        while !self.has_byte() {};
        self.data_port.read()
    }

    #[inline]
    pub fn write_byte(&self, byte: u8) {
        while !self.is_empty() {};
        self.data_port.write(byte)
    }
}

impl Read for SerialPort {
    type Error = util::Void;

    /// Reads a single byte into the given buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
        Ok(match &mut *buf {
            // if the length of the buffer is 0, then obviously
            // no bytes were read
            &mut []                  => 0
            // otherwise, read one byte into the head of the buffer
          , &mut [ref mut head, _..] => { *head = self.read_byte(); 1 }
        })
    }

    /// Reads a new byte into each position in the buffer.
    fn read_all(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
        let mut read_bytes = 0;
        for idx in buf.iter_mut() {
            // for each index in the buffer, read another byte from the port
            *idx = self.read_byte();
            // and increment the number of bytes read (this should be faster
            // than calling `buf.len()` later; as we only need 1 loop)
            read_bytes += 1;
        }
        Ok(read_bytes)
    }
}

impl Write for SerialPort {
    type Error = util::Void;

    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
        let mut written_bytes = 0;
        for byte in buf {
            // write each byte in the buffer to the port
            self.write_byte(*byte);
            // and increment the number of bytes written (this should be faster
            // than calling `buf.len()` later; as we only need 1 loop)
            written_bytes += 1;
        }
        Ok(written_bytes)
    }
}
<|endoftext|>


<commit_before>use super::*;
use redox::*;

impl Editor {
    /// Execute a instruction
    pub fn exec(&mut self, Inst(repeat, cmd): Inst) {
        use super::Key::*;
        use super::Mode::*;
        use super::PrimitiveMode::*;
        use super::CommandMode::*;

        let n = repeat.d();
        match cmd {
            Ctrl(b) => self.key_state.ctrl = b,
            Alt(b) => self.key_state.alt = b,
            Shift(b) => self.key_state.shift = b,
            _ => {},
        }

        if cmd == Char(' ') && self.key_state.shift {
            self.cursor_mut().mode = Mode::Command(CommandMode::Normal);
        } else {
            match self.cursor().mode {
                Command(Normal) => match cmd {
                    Char('i') => {
                        self.cursor_mut().mode = Mode::Primitive(PrimitiveMode::Insert(
                            InsertOptions {
                                mode: InsertMode::Insert,
                            }));

                    },
                    Char('h') => self.goto_left(n),
                    Char('j') => self.goto_down(n),
                    Char('k') => self.goto_up(n),
                    Char('l') => self.goto_right(n),
                    Char('J') => self.goto_down(15),
                    Char('K') => self.goto_up(15),
                    Char('x') => self.delete(),
                    Char('X') => {
                        self.goto_previous();
                        self.delete();
                    },
                    Char('L') => self.goto_ln_end(),
                    Char('H') => self.cursor_mut().x = 0,
                    Char('r') => {
                        loop {
                            if let EventOption::Key(k) = self.window.poll()
                                                         .unwrap_or(Event::new())
                                                         .to_option() {
                                if k.pressed {
                                    let x = self.x();
                                    let y = self.y();
                                    self.text[y][x] = k.character;
                                    break;
                                }
                            }
                        }
                    },
                    Char('R') => {
                        self.cursor_mut().mode = Mode::Primitive(PrimitiveMode::Insert(
                            InsertOptions {
                                mode: InsertMode::Replace,
                            }));
                    },
                    Char('d') => {
                    },
                    Char('g') => {
                        let inst = self.next_inst();
                        let new = self.to_motion(inst);
                        self.cursor_mut().x = new.0;
                        self.cursor_mut().y = new.1;

                    },
                    Char(' ') => self.goto_next(),
                    _ => {},
                },
                Primitive(Insert(opt)) => {
                    self.insert(cmd, opt);
                },
            }
        }
    }
}
<commit_msg>Utilize alt modifier for motion<commit_after>use super::*;
use redox::*;

impl Editor {
    /// Execute a instruction
    pub fn exec(&mut self, Inst(repeat, cmd): Inst) {
        use super::Key::*;
        use super::Mode::*;
        use super::PrimitiveMode::*;
        use super::CommandMode::*;

        let n = repeat.d();
        match cmd {
            Ctrl(b) => self.key_state.ctrl = b,
            Alt(b) => self.key_state.alt = b,
            Shift(b) => self.key_state.shift = b,
            _ => {},
        }

        if cmd == Char(' ') && self.key_state.shift {
            self.cursor_mut().mode = Mode::Command(CommandMode::Normal);
        } else if self.key_state.alt {
            let new_pos = self.to_motion(Inst(repeat, cmd));
            self.goto(new_pos);
        } else {
            match self.cursor().mode {
                Command(Normal) => match cmd {
                    Char('i') => {
                        self.cursor_mut().mode = Mode::Primitive(PrimitiveMode::Insert(
                            InsertOptions {
                                mode: InsertMode::Insert,
                            }));

                    },
                    Char('h') => self.goto_left(n),
                    Char('j') => self.goto_down(n),
                    Char('k') => self.goto_up(n),
                    Char('l') => self.goto_right(n),
                    Char('J') => self.goto_down(15),
                    Char('K') => self.goto_up(15),
                    Char('x') => self.delete(),
                    Char('X') => {
                        self.goto_previous();
                        self.delete();
                    },
                    Char('L') => self.goto_ln_end(),
                    Char('H') => self.cursor_mut().x = 0,
                    Char('r') => {
                        loop {
                            if let EventOption::Key(k) = self.window.poll()
                                                         .unwrap_or(Event::new())
                                                         .to_option() {
                                if k.pressed {
                                    let x = self.x();
                                    let y = self.y();
                                    self.text[y][x] = k.character;
                                    break;
                                }
                            }
                        }
                    },
                    Char('R') => {
                        self.cursor_mut().mode = Mode::Primitive(PrimitiveMode::Insert(
                            InsertOptions {
                                mode: InsertMode::Replace,
                            }));
                    },
                    Char('d') => {
                    },
                    Char('g') => {
                        let inst = self.next_inst();
                        let new = self.to_motion(inst);
                        self.cursor_mut().x = new.0;
                        self.cursor_mut().y = new.1;

                    },
                    Char(' ') => self.goto_next(),
                    _ => {},
                },
                Primitive(Insert(opt)) => {
                    self.insert(cmd, opt);
                },
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add RS testing for long and long long.<commit_after><|endoftext|>


<commit_before><commit_msg>Test(lib): fix config::parse call<commit_after><|endoftext|>


<commit_before><commit_msg>begin texture work<commit_after>use std::io::{BufReader, Reader, SeekSet};
use std::{str, mem};
use super::types::*;
use super::Archive;
use super::util::read_binary;

static PNAMES_LUMP_NAME: &'static [u8, ..8] =
    &[b'P', b'N', b'A', b'M', b'E', b'S', b'\0', b'\0'];

static TEXTURE_LUMP_NAMES: &'static [[u8, ..8]] =
    &[[b'T', b'E', b'X', b'T', b'U', b'R', b'E', b'1'],
      [b'T', b'E', b'X', b'T', b'U', b'R', b'E', b'2']];

pub struct TextureDirectory {
    //textures: HashMap<Vec<u8>, Image>,
    patches: Vec<(WadName, Option<Image>)>,
}

pub struct Image {
    width: uint,
    height: uint,
    x_offset: int,
    y_offset: int,
    pixels: Vec<i16>,
}

impl Image {
    pub fn new(width: uint, height: uint) -> Image{
        Image { width: width,
                height: height,
                x_offset: 0,
                y_offset: 0,
                pixels: Vec::from_elem(width * height, 0) }
    }

    pub fn new_from_header(header: &WadTextureHeader) -> Image {
        Image::new(header.width as uint, header.height as uint)
    }

    pub fn from_buffer(buffer: &[u8]) -> Image {
        let mut reader = BufReader::new(buffer);

        let width = reader.read_le_u16().unwrap() as uint;
        let height = reader.read_le_u16().unwrap() as uint;
        let x_offset = reader.read_le_i16().unwrap() as int;
        let y_offset = reader.read_le_i16().unwrap() as int;

        // This allocation isn't strictly necessary.
        let mut column_offsets = Vec::with_capacity(width);
        for i_column in range(0, width) {
            column_offsets.push(reader.read_le_u32().unwrap() as i64);
        }
        let column_offsets = column_offsets;

        let mut pixels = Vec::from_elem(width * height, -1);
        for i_column in range(0, width) {
            reader.seek(column_offsets[i_column], SeekSet).unwrap();
            loop {
                let row_start = reader.read_u8().unwrap() as uint;
                if row_start == 255 { break }
                let run_length = reader.read_u8().unwrap() as uint;
                reader.read_u8().unwrap();  // Ignore first byte.
                for i_run in range(0, run_length) {
                    let index = (i_run + row_start) * width + i_column;
                    let pixel = reader.read_u8().unwrap() as i16;
                    *pixels.get_mut(index) = pixel;
                }
                reader.read_u8().unwrap();  // Ignore last byte.
            }
        }
        let pixels = pixels;

        Image { width: width,
                height: height,
                x_offset: x_offset,
                y_offset: y_offset,
                pixels: pixels }
    }

    pub fn blit(&mut self, source: &Image, x_offset: int, y_offset: int,
                overwrite: bool) {
        for source_y in range(0, source.height) {
            let self_y = source_y as int + y_offset;
            if self_y < 0 || self_y >= self.height as int { continue; }

            for source_x in range(0, source.width) {
                let self_x = source_x as int + x_offset;
                if self_x < 0 || self_x >= self.width as int { continue; }

                let (self_x, self_y) = (self_x as uint, self_y as uint);
                let source_index = source_x + source_y * source.width;
                let self_index = self_x + self_y * self.width;

                let self_pixel = self.pixels.get_mut(self_index);
                let source_pixel = source.pixels[source_index];
                if source_pixel >= 0 || overwrite {
                    *self_pixel = source_pixel;
                }
            }
        }
    }

    pub fn get_x_offset(&self) -> int { self.x_offset }
    pub fn get_y_offset(&self) -> int { self.y_offset }
}

macro_rules! io_try(
    ($e:expr) => (try!($e.map_err(|e| String::from_str(e.desc))))
)

impl TextureDirectory {
    pub fn from_archive(wad: &mut Archive) -> Result<TextureDirectory, String> {
        info!("Reading texture directory...");

        // Read patches.
        let lump_buffer = wad.read_lump_by_name(PNAMES_LUMP_NAME);
        let mut lump = BufReader::new(lump_buffer.as_slice());

        let num_patches = io_try!(lump.read_le_u32()) as uint;
        info!("  {:4} patches", num_patches);
        let mut patches = Vec::with_capacity(num_patches);
        let mut missing_patches = 0u;
        for i_patch in range(0, num_patches) {
            let name = read_binary::<WadName, _>(&mut lump);
            let patch = wad.get_lump_index(&name).map(|index| {
                let patch_buffer = wad.read_lump(index);
                Image::from_buffer(patch_buffer.as_slice())
            });
            if patch.is_none() { missing_patches += 1; }
            patches.push((name, patch));
        }
        let patches = patches;

        // Read textures.
        for lump_name in TEXTURE_LUMP_NAMES.iter() {
            let lump_index = match wad.get_lump_index(lump_name) {
                Some(i) => i,
                None => continue
            };

            let lump_buffer = wad.read_lump(lump_index);
            let mut lump = BufReader::new(lump_buffer.as_slice());

            let num_textures = io_try!(lump.read_le_u32()) as uint;
            info!("  {:4} textures in {}", num_textures,
                  str::from_utf8(lump_name).unwrap());

            let mut offsets = BufReader::new({
                let begin = io_try!(lump.tell()) as uint;
                let size = num_textures * mem::size_of::<u32>();
                lump_buffer.slice(begin, begin + size)
            });

            for i_texture in range(0, num_textures) {
                io_try!(lump.seek(io_try!(offsets.read_le_u32()) as i64,
                                  SeekSet));
                let header = read_binary::<WadTextureHeader, _>(&mut lump);
                let mut image = Image::new_from_header(&header);

                for i_patch in range(0, header.num_patches) {
                    let pref = read_binary::<WadTexturePatchRef, _>(&mut lump);
                    match patches[pref.patch as uint] {
                        (_, Some(ref patch)) => {
                            image.blit(patch,
                                       pref.origin_x as int,
                                       pref.origin_y as int,
                                       i_patch == 0);
                        },
                        (ref patch_name, None) => {
                            fail!("Texture {} uses missing patch {}.",
                                  str::from_utf8(header.name).unwrap(),
                                  str::from_utf8(patch_name).unwrap());
                        }
                    }
                }
            }
        }

        warn!("{} missing patches from PNAMES.", missing_patches);
        Ok(TextureDirectory { patches: patches })
    }
}
<|endoftext|>


<commit_before><commit_msg>implement random circle points<commit_after>#![feature(inclusive_range_syntax)]

extern crate rand;

use rand::Rng;

const POINTS_N: usize = 100;

fn generate_point<R: Rng>(rng: &mut R) -> (i32, i32) {
    loop {
        let x = rng.gen_range(-15, 16); // exclusive
        let y = rng.gen_range(-15, 16);

        let r2 = x * x + y * y;
        if r2 >= 100 && r2 <= 225 {
            return (x, y);
        }
    }
}

fn filtering_method<R: Rng>(rng: &mut R) {
    let mut rows = [[" "; 62]; 31];

    // Generate points
    for _ in 0..POINTS_N {
        let (x, y) = generate_point(rng);
        rows[(y + 15) as usize][(x + 15) as usize * 2] = "*";
    }

    // draw the points
    for row in &rows {
        println!("{}", row.concat());
    }
}

fn precalculating_method<R: Rng>(rng: &mut R) {
    // Generate all possible points
    let mut possible_points = Vec::with_capacity(404);
    for y in -15..=15 {
        for x in -15..=15 {
            let r2 = x * x + y * y;
            if r2 >= 100 && r2 <= 225 {
                possible_points.push((x, y));
            }
        }
    }

    // A truncated Fisher-Yates shuffle
    let len = possible_points.len();
    for i in (len - POINTS_N..len).rev() {
        let j = rng.gen_range(0, i + 1);
        possible_points.swap(i, j);
    }

    // turn the selected points into "pixels"
    let mut rows = [[" "; 62]; 31];
    for &(x, y) in &possible_points[len - POINTS_N..] {
        rows[(y + 15) as usize][(x + 15) as usize * 2] = "*";
    }

    // draw the "pixels"
    for row in &rows {
        println!("{}", row.concat());
    }
}

fn main() {
    let mut rng = rand::weak_rng();

    filtering_method(&mut rng);

    precalculating_method(&mut rng);
}
<|endoftext|>


<commit_before><commit_msg>theme: vector_graphics: rename ttf definition<commit_after>/// List of material font icons. Use this to generate a font Icon.
// emacs: use C-x 8 Ret => #xf207 ("BUS"-Glyph)
// pub const FLOPPY_FONT_ICON: &str = "";
// pub const ADD_FONT_ICON: &str = "";
// pub const LOAD_FONT_ICON: &str = "";
// pub const SAVE_FONT_ICON: &str = "";
// pub const KEYBOARD_ARROW_LEFT_FONT_ICON: &str = "";
// pub const KEYBOARD_ARROW_RIGHT_FONT_ICON: &str = "";
// pub const REMOVE_ICON: &str = "";
// pub const ARROW_DOWN_ICON: &str = "";

// pub const MENU_FONT_ICON: &str = "";
// pub const SETTINGS_FONT_ICON: &str = "";
// pub const HELP_OUTLINE_FONT_ICON: &str = "";

// // category: Social
// pub const ANDROID_FONT_ICON: &str = "";
// pub const APPLE_FONT_ICON: &str = "";
// pub const GITHUB_FONT_ICON: &str = "";
// pub const GOOGLE_FONT_ICON: &str = "";
// pub const GOOGLE_DRIVE_FONT_ICON: &str = "";
// pub const GOOGLE_MAPS_FONT_ICON: &str = "";
// pub const LANGUAGE_JAVASCRIPT_FONT_ICON: &str = "";
// pub const LANGUAGE_HTML5_FONT_ICON: &str = "";
// pub const LANGUAGE_PYTHON_ICON: &str = "";
// pub const PAYPAL_FONT_ICON: &str = "";
// pub const POCKET_FONT_ICON: &str = "";
// pub const RSS_FONT_ICON: &str = "";
// pub const SHARE_FONT_ICON: &str = "";
// pub const STEAM_FONT_ICON: &str = "";
// pub const TWITTER_BOX_FONT_ICON: &str = "";
// pub const TWITTER_FONT_ICON: &str = "";
// pub const WIKIPEDIA_FONT_ICON: &str = "";
// pub const LINKEDIN_FONT_ICON: &str = "";
// pub const REDDIT_FONT_ICON: &str = "";
// pub const VIMEO_FONT_ICON: &str = "";
// pub const WINDOWS_FONT_ICON: &str = "";

// // category: Person
// pub const ACCOUNT_FONT_ICON: &str = "";
// pub const ACCOUNT_ADD_FONT_ICON: &str = "";
// pub const ACCOUNT_BOX_FONT_ICON: &str = "";
// pub const ACCOUNT_CIRCLE_FONT_ICON: &str = "";
// pub const ACCOUNTS_ADD_FONT_ICON: &str = "";
// pub const ACCOUNTS_FONT_ICON: &str = "";
// pub const MALE_FONT_ICON: &str = "";
// pub const FEMALE_FONT_ICON: &str = "";
// pub const MALE_FEMALE_FONT_ICON: &str = "";
// pub const RUN_FONT_ICON: &str = "";
// pub const WALK_FONT_ICON: &str = "";

// // category: File
// pub const CLOUD_FONT_ICON: &str = "";
// pub const DOWNLOAD_FONT_ICON: &str = "";
// pub const UPLOAD_FONT_ICON: &str = "";
// pub const FILE_FONT_ICON: &str = "";
// pub const FOLDER_FONT_ICON: &str = "";
// pub const FOLDER_OUTLINE_FONT_ICON: &str = "";
// pub const CLOUD_DONE_FONT_ICON: &str = "";
// pub const CLOUD_OFF_FONT_ICON: &str = "";
// pub const CLOUD_DOWNLOAD_FONT_ICON: &str = "";
// pub const CLOUD_OUTLINE_FONT_ICON: &str = "";
// pub const CLOUD_UPLOAD_FONT_ICON: &str = "";

// // category: Comment
// pub const COMMENT_FONT_ICON: &str = "";
// pub const COMMENT_LIST_FONT_ICON: &str = "";
// pub const COMMENT_IMAGE_FONT_ICON: &str = "";
// pub const COMMENT_EDIT_FONT_ICON: &str = "";
// pub const COMMENT_ALERT_FONT_ICON: &str = "";
// pub const COMMENT_MORE_FONT_ICON: &str = "";
// pub const COMMENT_OUTLINE_FONT_ICON: &str = "";
// pub const COMMENTS_FONT_ICON: &str = "";
// pub const COMMENT_VIDEO_TEXT_FONT_ICON: &str = "";
// pub const COMMENT_TEXT_FONT_ICON: &str = "";

// // category: Form
// pub const CHECK_ALL_FONT_ICON: &str = "";
// pub const CHECK_CIRCLE_U_FONT_ICON: &str = "";
// pub const CHECK_CIRCLE_FONT_ICON: &str = "";
// pub const CHECK_SQUARE_FONT_ICON: &str = "";
// pub const CHECK_FONT_ICON: &str = "";
// //pub const CHECK_FONT_ICON: &str = "";
// pub const CIRCLE_O_FONT_ICON: &str = "";
// pub const CIRCLE_FONT_ICON: &str = "";
// pub const DOT_CIRCLE_ALT_FONT_ICON: &str = "";
// pub const DOT_CIRCLE_FONT_ICON: &str = "";
// pub const MINUS_CIRCLE_OUTLINE_FONT_ICON: &str = "";
// pub const MINUS_CIRCLE_FONT_ICON: &str = "";
// pub const MINUS_SQUARE_FONT_ICON: &str = "";
// pub const MINUS_FONT_ICON: &str = "";
// //pub const MINUS_FONT_ICON: &str = "";
// pub const PLUS_CIRCLE_O_DUPLICATE_FONT_ICON: &str = "";
// pub const PLUS_CIRCLE_O_FONT_ICON: &str = "";
// pub const PLUS_CIRCLE_FONT_ICON: &str = "";
// pub const PLUS_SQUARE_FONT_ICON: &str = "";
// pub const PLUS_FONT_ICON: &str = "";
// pub const SQUARE_O_FONT_ICON: &str = "";
// pub const STAR_CIRCLE_FONT_ICON: &str = "";
// pub const STAR_HALF_FONT_ICON: &str = "";
// pub const STAR_OUTLINE_FONT_ICON: &str = "";
// pub const STAR_STAR_FONT_ICON: &str = "";

/// List of material font icons. Use this to generate a font Icon.
pub const FLOPPY_FONT_ICON: &str = "";
pub const CHECK_FONT_ICON: &str = "";
pub const ADD_FONT_ICON: &str = "";
pub const MINUS_FONT_ICON: &str = "";
pub const LOAD_FONT_ICON: &str = "";
pub const SAVE_FONT_ICON: &str = "";
pub const KEYBOARD_ARROW_LEFT_FONT_ICON: &str = "";
pub const KEYBOARD_ARROW_RIGHT_FONT_ICON: &str = "";
pub const REMOVE_ICON: &str = "";
pub const ARROW_DOWN_ICON: &str = "";<|endoftext|>


<commit_before><commit_msg>Regression test for #3902<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.

mod base {
    pub trait HasNew<T> {
        fn new() -> T;
    }

    pub struct Foo {
        dummy: (),
    }

    impl HasNew<Foo> for Foo {
        fn new() -> Foo {
            Foo { dummy: () }
        }
    }

    pub struct Bar {
        dummy: (),
    }

    impl HasNew<Bar> for Bar {
        fn new() -> Bar {
            Bar { dummy: () }
        }
    }
}

pub fn main() {
    let _f: base::Foo = base::HasNew::new();
    let _b: base::Bar = base::HasNew::new();
}
<|endoftext|>


<commit_before><commit_msg>rs: to_jaden_case<commit_after><|endoftext|>


<commit_before><commit_msg>v8 rub work<commit_after><|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 error::{Error};
use fmt;
use sync::atomic::{AtomicBool, Ordering};
use thread;

pub struct Flag { failed: AtomicBool }

// Note that the Ordering uses to access the `failed` field of `Flag` below is
// always `Relaxed`, and that's because this isn't actually protecting any data,
// it's just a flag whether we've panicked or not.
//
// The actual location that this matters is when a mutex is **locked** which is
// where we have external synchronization ensuring that we see memory
// reads/writes to this flag.
//
// As a result, if it matters, we should see the correct value for `failed` in
// all cases.

impl Flag {
    pub const fn new() -> Flag {
        Flag { failed: AtomicBool::new(false) }
    }

    #[inline]
    pub fn borrow(&self) -> LockResult<Guard> {
        let ret = Guard { panicking: thread::panicking() };
        if self.get() {
            Err(PoisonError::new(ret))
        } else {
            Ok(ret)
        }
    }

    #[inline]
    pub fn done(&self, guard: &Guard) {
        if !guard.panicking && thread::panicking() {
            self.failed.store(true, Ordering::Relaxed);
        }
    }

    #[inline]
    pub fn get(&self) -> bool {
        self.failed.load(Ordering::Relaxed)
    }
}

pub struct Guard {
    panicking: bool,
}

/// A type of error which can be returned whenever a lock is acquired.
///
/// Both [`Mutex`]es and [`RwLock`]s are poisoned whenever a thread fails while the lock
/// is held. The precise semantics for when a lock is poisoned is documented on
/// each lock, but once a lock is poisoned then all future acquisitions will
/// return this error.
///
/// [`Mutex`]: ../../std/sync/struct.Mutex.html
/// [`RwLock`]: ../../std/sync/struct.RwLock.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct PoisonError<T> {
    guard: T,
}

/// An enumeration of possible errors which can occur while calling the
/// [`try_lock`] method.
///
/// [`try_lock`]: struct.Mutex.html#method.try_lock
#[stable(feature = "rust1", since = "1.0.0")]
pub enum TryLockError<T> {
    /// The lock could not be acquired because another thread failed while holding
    /// the lock.
    #[stable(feature = "rust1", since = "1.0.0")]
    Poisoned(#[stable(feature = "rust1", since = "1.0.0")] PoisonError<T>),
    /// The lock could not be acquired at this time because the operation would
    /// otherwise block.
    #[stable(feature = "rust1", since = "1.0.0")]
    WouldBlock,
}

/// A type alias for the result of a lock method which can be poisoned.
///
/// The [`Ok`] variant of this result indicates that the primitive was not
/// poisoned, and the `Guard` is contained within. The [`Err`] variant indicates
/// that the primitive was poisoned. Note that the [`Err`] variant *also* carries
/// the associated guard, and it can be acquired through the [`into_inner`]
/// method.
///
/// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
/// [`into_inner`]: ../../std/sync/struct.Mutex.html#method.into_inner
#[stable(feature = "rust1", since = "1.0.0")]
pub type LockResult<Guard> = Result<Guard, PoisonError<Guard>>;

/// A type alias for the result of a nonblocking locking method.
///
/// For more information, see [`LockResult`]. A `TryLockResult` doesn't
/// necessarily hold the associated guard in the [`Err`] type as the lock may not
/// have been acquired for other reasons.
///
/// [`LockResult`]: ../../std/sync/type.LockResult.html
/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
#[stable(feature = "rust1", since = "1.0.0")]
pub type TryLockResult<Guard> = Result<Guard, TryLockError<Guard>>;

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Debug for PoisonError<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        "PoisonError { inner: .. }".fmt(f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Display for PoisonError<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        "poisoned lock: another task failed inside".fmt(f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Error for PoisonError<T> {
    fn description(&self) -> &str {
        "poisoned lock: another task failed inside"
    }
}

impl<T> PoisonError<T> {
    /// Creates a `PoisonError`.
    ///
    /// This is generally created by methods like [`Mutex::lock`] or [`RwLock::read`].
    ///
    /// [`Mutex::lock`]: ../../std/sync/struct.Mutex.html#method.lock
    /// [`RwLock::read`]: ../../std/sync/struct.RwLock.html#method.read
    #[stable(feature = "sync_poison", since = "1.2.0")]
    pub fn new(guard: T) -> PoisonError<T> {
        PoisonError { guard: guard }
    }

    /// Consumes this error indicating that a lock is poisoned, returning the
    /// underlying guard to allow access regardless.
    #[stable(feature = "sync_poison", since = "1.2.0")]
    pub fn into_inner(self) -> T { self.guard }

    /// Reaches into this error indicating that a lock is poisoned, returning a
    /// reference to the underlying guard to allow access regardless.
    #[stable(feature = "sync_poison", since = "1.2.0")]
    pub fn get_ref(&self) -> &T { &self.guard }

    /// Reaches into this error indicating that a lock is poisoned, returning a
    /// mutable reference to the underlying guard to allow access regardless.
    #[stable(feature = "sync_poison", since = "1.2.0")]
    pub fn get_mut(&mut self) -> &mut T { &mut self.guard }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> From<PoisonError<T>> for TryLockError<T> {
    fn from(err: PoisonError<T>) -> TryLockError<T> {
        TryLockError::Poisoned(err)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Debug for TryLockError<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            TryLockError::Poisoned(..) => "Poisoned(..)".fmt(f),
            TryLockError::WouldBlock => "WouldBlock".fmt(f)
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Display for TryLockError<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            TryLockError::Poisoned(..) => "poisoned lock: another task failed inside",
            TryLockError::WouldBlock => "try_lock failed because the operation would block"
        }.fmt(f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Error for TryLockError<T> {
    fn description(&self) -> &str {
        match *self {
            TryLockError::Poisoned(ref p) => p.description(),
            TryLockError::WouldBlock => "try_lock failed because the operation would block"
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            TryLockError::Poisoned(ref p) => Some(p),
            _ => None
        }
    }
}

pub fn map_result<T, U, F>(result: LockResult<T>, f: F)
                           -> LockResult<U>
                           where F: FnOnce(T) -> U {
    match result {
        Ok(t) => Ok(f(t)),
        Err(PoisonError { guard }) => Err(PoisonError::new(f(guard)))
    }
}
<commit_msg>Fix incorrect `into_inner` link in docs.<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 error::{Error};
use fmt;
use sync::atomic::{AtomicBool, Ordering};
use thread;

pub struct Flag { failed: AtomicBool }

// Note that the Ordering uses to access the `failed` field of `Flag` below is
// always `Relaxed`, and that's because this isn't actually protecting any data,
// it's just a flag whether we've panicked or not.
//
// The actual location that this matters is when a mutex is **locked** which is
// where we have external synchronization ensuring that we see memory
// reads/writes to this flag.
//
// As a result, if it matters, we should see the correct value for `failed` in
// all cases.

impl Flag {
    pub const fn new() -> Flag {
        Flag { failed: AtomicBool::new(false) }
    }

    #[inline]
    pub fn borrow(&self) -> LockResult<Guard> {
        let ret = Guard { panicking: thread::panicking() };
        if self.get() {
            Err(PoisonError::new(ret))
        } else {
            Ok(ret)
        }
    }

    #[inline]
    pub fn done(&self, guard: &Guard) {
        if !guard.panicking && thread::panicking() {
            self.failed.store(true, Ordering::Relaxed);
        }
    }

    #[inline]
    pub fn get(&self) -> bool {
        self.failed.load(Ordering::Relaxed)
    }
}

pub struct Guard {
    panicking: bool,
}

/// A type of error which can be returned whenever a lock is acquired.
///
/// Both [`Mutex`]es and [`RwLock`]s are poisoned whenever a thread fails while the lock
/// is held. The precise semantics for when a lock is poisoned is documented on
/// each lock, but once a lock is poisoned then all future acquisitions will
/// return this error.
///
/// [`Mutex`]: ../../std/sync/struct.Mutex.html
/// [`RwLock`]: ../../std/sync/struct.RwLock.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct PoisonError<T> {
    guard: T,
}

/// An enumeration of possible errors which can occur while calling the
/// [`try_lock`] method.
///
/// [`try_lock`]: struct.Mutex.html#method.try_lock
#[stable(feature = "rust1", since = "1.0.0")]
pub enum TryLockError<T> {
    /// The lock could not be acquired because another thread failed while holding
    /// the lock.
    #[stable(feature = "rust1", since = "1.0.0")]
    Poisoned(#[stable(feature = "rust1", since = "1.0.0")] PoisonError<T>),
    /// The lock could not be acquired at this time because the operation would
    /// otherwise block.
    #[stable(feature = "rust1", since = "1.0.0")]
    WouldBlock,
}

/// A type alias for the result of a lock method which can be poisoned.
///
/// The [`Ok`] variant of this result indicates that the primitive was not
/// poisoned, and the `Guard` is contained within. The [`Err`] variant indicates
/// that the primitive was poisoned. Note that the [`Err`] variant *also* carries
/// the associated guard, and it can be acquired through the [`into_inner`]
/// method.
///
/// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
/// [`into_inner`]: ../../std/sync/struct.PoisonError.html#method.into_inner
#[stable(feature = "rust1", since = "1.0.0")]
pub type LockResult<Guard> = Result<Guard, PoisonError<Guard>>;

/// A type alias for the result of a nonblocking locking method.
///
/// For more information, see [`LockResult`]. A `TryLockResult` doesn't
/// necessarily hold the associated guard in the [`Err`] type as the lock may not
/// have been acquired for other reasons.
///
/// [`LockResult`]: ../../std/sync/type.LockResult.html
/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
#[stable(feature = "rust1", since = "1.0.0")]
pub type TryLockResult<Guard> = Result<Guard, TryLockError<Guard>>;

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Debug for PoisonError<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        "PoisonError { inner: .. }".fmt(f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Display for PoisonError<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        "poisoned lock: another task failed inside".fmt(f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Error for PoisonError<T> {
    fn description(&self) -> &str {
        "poisoned lock: another task failed inside"
    }
}

impl<T> PoisonError<T> {
    /// Creates a `PoisonError`.
    ///
    /// This is generally created by methods like [`Mutex::lock`] or [`RwLock::read`].
    ///
    /// [`Mutex::lock`]: ../../std/sync/struct.Mutex.html#method.lock
    /// [`RwLock::read`]: ../../std/sync/struct.RwLock.html#method.read
    #[stable(feature = "sync_poison", since = "1.2.0")]
    pub fn new(guard: T) -> PoisonError<T> {
        PoisonError { guard: guard }
    }

    /// Consumes this error indicating that a lock is poisoned, returning the
    /// underlying guard to allow access regardless.
    #[stable(feature = "sync_poison", since = "1.2.0")]
    pub fn into_inner(self) -> T { self.guard }

    /// Reaches into this error indicating that a lock is poisoned, returning a
    /// reference to the underlying guard to allow access regardless.
    #[stable(feature = "sync_poison", since = "1.2.0")]
    pub fn get_ref(&self) -> &T { &self.guard }

    /// Reaches into this error indicating that a lock is poisoned, returning a
    /// mutable reference to the underlying guard to allow access regardless.
    #[stable(feature = "sync_poison", since = "1.2.0")]
    pub fn get_mut(&mut self) -> &mut T { &mut self.guard }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> From<PoisonError<T>> for TryLockError<T> {
    fn from(err: PoisonError<T>) -> TryLockError<T> {
        TryLockError::Poisoned(err)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Debug for TryLockError<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            TryLockError::Poisoned(..) => "Poisoned(..)".fmt(f),
            TryLockError::WouldBlock => "WouldBlock".fmt(f)
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Display for TryLockError<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            TryLockError::Poisoned(..) => "poisoned lock: another task failed inside",
            TryLockError::WouldBlock => "try_lock failed because the operation would block"
        }.fmt(f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Error for TryLockError<T> {
    fn description(&self) -> &str {
        match *self {
            TryLockError::Poisoned(ref p) => p.description(),
            TryLockError::WouldBlock => "try_lock failed because the operation would block"
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            TryLockError::Poisoned(ref p) => Some(p),
            _ => None
        }
    }
}

pub fn map_result<T, U, F>(result: LockResult<T>, f: F)
                           -> LockResult<U>
                           where F: FnOnce(T) -> U {
    match result {
        Ok(t) => Ok(f(t)),
        Err(PoisonError { guard }) => Err(PoisonError::new(f(guard)))
    }
}
<|endoftext|>


<commit_before><commit_msg>We now check for assignment to constant variables, and output an error message if it happens.<commit_after><|endoftext|>


<commit_before>/*!

Sendable hash maps.  Very much a work in progress.

*/

/**
 * A function that returns a hash of a value
 *
 * The hash should concentrate entropy in the lower bits.
 */
type hashfn<K> = pure fn~(K) -> uint;
type eqfn<K> = pure fn~(K, K) -> bool;

/// Open addressing with linear probing.
mod linear {
    export linear_map, linear_map_with_capacity, public_methods;

    const initial_capacity: uint = 32u; // 2^5
    type bucket<K,V> = {hash: uint, key: K, value: V};
    enum linear_map<K,V> {
        linear_map_({
            hashfn: pure fn~(x: &K) -> uint,
            eqfn: pure fn~(x: &K, y: &K) -> bool,
            resize_at: uint,
            size: uint,
            buckets: ~[option<bucket<K,V>>]})
    }

    // FIXME(#2979) -- with #2979 we could rewrite found_entry
    // to have type option<&bucket<K,V>> which would be nifty
    enum search_result {
        found_entry(uint), found_hole(uint), table_full
    }

    fn resize_at(capacity: uint) -> uint {
        ((capacity as float) * 3. / 4.) as uint
    }

    fn linear_map<K,V>(
        +hashfn: pure fn~(x: &K) -> uint,
        +eqfn: pure fn~(x: &K, y: &K) -> bool) -> linear_map<K,V> {

        linear_map_with_capacity(hashfn, eqfn, 32)
    }

    fn linear_map_with_capacity<K,V>(
        +hashfn: pure fn~(x: &K) -> uint,
        +eqfn: pure fn~(x: &K, y: &K) -> bool,
        initial_capacity: uint) -> linear_map<K,V> {

        linear_map_({
            hashfn: hashfn,
            eqfn: eqfn,
            resize_at: resize_at(initial_capacity),
            size: 0,
            buckets: vec::from_fn(initial_capacity, |_i| none)})
    }

    // FIXME(#2979) would allow us to use region type for k
    unsafe fn borrow<K>(&&k: K) -> &K {
        let p: *K = ptr::addr_of(k);
        p as &K
    }

    impl private_methods<K,V> for &const linear_map<K,V> {
        #[inline(always)]
        pure fn to_bucket(h: uint) -> uint {
            // FIXME(#3041) borrow a more sophisticated technique here from
            // Gecko, for example borrowing from Knuth, as Eich so
            // colorfully argues for here:
            // https://bugzilla.mozilla.org/show_bug.cgi?id=743107#c22
            h % self.buckets.len()
        }

        #[inline(always)]
        pure fn next_bucket(idx: uint, len_buckets: uint) -> uint {
            let n = (idx + 1) % len_buckets;
            unsafe{ // argh. log not considered pure.
                debug!{"next_bucket(%?, %?) = %?", idx, len_buckets, n};
            }
            ret n;
        }

        #[inline(always)]
        pure fn bucket_sequence(hash: uint, op: fn(uint) -> bool) -> uint {
            let start_idx = self.to_bucket(hash);
            let len_buckets = self.buckets.len();
            let mut idx = start_idx;
            loop {
                if !op(idx) {
                    ret idx;
                }
                idx = self.next_bucket(idx, len_buckets);
                if idx == start_idx {
                    ret start_idx;
                }
            }
        }

        #[inline(always)]
        pure fn bucket_for_key(
            buckets: &[option<bucket<K,V>>],
            k: &K) -> search_result {

            let hash = self.hashfn(k);
            self.bucket_for_key_with_hash(buckets, hash, k)
        }

        #[inline(always)]
        pure fn bucket_for_key_with_hash(
            buckets: &[option<bucket<K,V>>],
            hash: uint,
            k: &K) -> search_result {

            let _ = for self.bucket_sequence(hash) |i| {
                alt buckets[i] {
                  some(bkt) {
                    if bkt.hash == hash && self.eqfn(k, &bkt.key) {
                        ret found_entry(i);
                    }
                  }
                  none => {
                    ret found_hole(i);
                  }
                }
            };
            ret table_full;
        }
    }

    impl private_methods<K,V> for &mut linear_map<K,V> {
        /// Expands the capacity of the array and re-inserts each
        /// of the existing buckets.
        fn expand() {
            let old_capacity = self.buckets.len();
            let new_capacity = old_capacity * 2;
            self.resize_at = ((new_capacity as float) * 3.0 / 4.0) as uint;

            let mut old_buckets = vec::from_fn(new_capacity, |_i| none);
            self.buckets <-> old_buckets;

            for uint::range(0, old_capacity) |i| {
                let mut bucket = none;
                bucket <-> old_buckets[i];
                if bucket.is_some() {
                    self.insert_bucket(bucket);
                }
            }
        }

        fn insert_bucket(+bucket: option<bucket<K,V>>) {
            let {hash, key, value} <- option::unwrap(bucket);
            let _ = self.insert_internal(hash, key, value);
        }

        /// Inserts the key value pair into the buckets.
        /// Assumes that there will be a bucket.
        /// True if there was no previous entry with that key
        fn insert_internal(hash: uint, +k: K, +v: V) -> bool {
            alt self.bucket_for_key_with_hash(self.buckets, hash,
                                              unsafe{borrow(k)}) {
              table_full => {fail ~"Internal logic error";}
              found_hole(idx) {
                debug!{"insert fresh (%?->%?) at idx %?, hash %?",
                       k, v, idx, hash};
                self.buckets[idx] = some({hash: hash, key: k, value: v});
                self.size += 1;
                ret true;
              }
              found_entry(idx) => {
                debug!{"insert overwrite (%?->%?) at idx %?, hash %?",
                       k, v, idx, hash};
                self.buckets[idx] = some({hash: hash, key: k, value: v});
                ret false;
              }
            }
        }
    }

    impl public_methods<K,V> for &mut linear_map<K,V> {
        fn insert(+k: K, +v: V) -> bool {
            if self.size >= self.resize_at {
                // n.b.: We could also do this after searching, so
                // that we do not resize if this call to insert is
                // simply going to update a key in place.  My sense
                // though is that it's worse to have to search through
                // buckets to find the right spot twice than to just
                // resize in this corner case.
                self.expand();
            }

            let hash = self.hashfn(unsafe{borrow(k)});
            self.insert_internal(hash, k, v)
        }

        fn remove(k: &K) -> bool {
            // Removing from an open-addressed hashtable
            // is, well, painful.  The problem is that
            // the entry may lie on the probe path for other
            // entries, so removing it would make you think that
            // those probe paths are empty.
            //
            // To address this we basically have to keep walking,
            // re-inserting entries we find until we reach an empty
            // bucket.  We know we will eventually reach one because
            // we insert one ourselves at the beginning (the removed
            // entry).
            //
            // I found this explanation elucidating:
            // http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf

            let mut idx = alt self.bucket_for_key(self.buckets, k) {
              table_full | found_hole(_) => {
                ret false;
              }
              found_entry(idx) => {
                idx
              }
            };

            let len_buckets = self.buckets.len();
            self.buckets[idx] = none;
            idx = self.next_bucket(idx, len_buckets);
            while self.buckets[idx].is_some() {
                let mut bucket = none;
                bucket <-> self.buckets[idx];
                self.insert_bucket(bucket);
                idx = self.next_bucket(idx, len_buckets);
            }
            ret true;
        }
    }

    impl private_methods<K,V> for &linear_map<K,V> {
        fn search(hash: uint, op: fn(x: &option<bucket<K,V>>) -> bool) {
            let _ = self.bucket_sequence(hash, |i| op(&self.buckets[i]));
        }
    }

    impl public_methods<K,V> for &const linear_map<K,V> {
        fn size() -> uint {
            self.size
        }

        fn contains_key(k: &K) -> bool {
            alt self.bucket_for_key(self.buckets, k) {
              found_entry(_) => {true}
              table_full | found_hole(_) => {false}
            }
        }
    }

    impl public_methods<K,V: copy> for &const linear_map<K,V> {
        fn find(k: &K) -> option<V> {
            alt self.bucket_for_key(self.buckets, k) {
              found_entry(idx) => {
                alt check self.buckets[idx] {
                  some(bkt) => {some(copy bkt.value)}
                }
              }
              table_full | found_hole(_) => {
                none
              }
            }
        }

        fn get(k: &K) -> V {
            let value = self.find(k);
            if value.is_none() {
                fail fmt!{"No entry found for key: %?", k};
            }
            option::unwrap(value)
        }

        fn [](k: &K) -> V {
            self.get(k)
        }
    }

    impl imm_methods<K,V> for &linear_map<K,V> {
        /*
        FIXME --- #2979 must be fixed to typecheck this
        fn find_ptr(k: K) -> option<&V> {
            //XXX this should not type check as written, but it should
            //be *possible* to typecheck it...
            self.with_ptr(k, |v| v)
        }
        */

        fn each_ref(blk: fn(k: &K, v: &V) -> bool) {
            for vec::each(self.buckets) |slot| {
                let mut broke = false;
                do slot.iter |bucket| {
                    if !blk(&bucket.key, &bucket.value) {
                        broke = true; // FIXME(#3064) just write "break;"
                    }
                }
                if broke { break; }
            }
        }
        fn each_key_ref(blk: fn(k: &K) -> bool) {
            self.each_ref(|k, _v| blk(k))
        }
        fn each_value_ref(blk: fn(v: &V) -> bool) {
            self.each_ref(|_k, v| blk(v))
        }
    }

    impl public_methods<K: copy, V: copy> for &linear_map<K,V> {
        fn each(blk: fn(+K,+V) -> bool) {
            self.each_ref(|k,v| blk(copy *k, copy *v));
        }
    }
    impl public_methods<K: copy, V> for &linear_map<K,V> {
        fn each_key(blk: fn(+K) -> bool) {
            self.each_key_ref(|k| blk(copy *k));
        }
    }
    impl public_methods<K, V: copy> for &linear_map<K,V> {
        fn each_value(blk: fn(+V) -> bool) {
            self.each_value_ref(|v| blk(copy *v));
        }
    }
}

#[test]
mod test {

    import linear::linear_map;

    pure fn uint_hash(x: &uint) -> uint { *x }
    pure fn uint_eq(x: &uint, y: &uint) -> bool { *x == *y }

    fn int_linear_map<V>() -> linear_map<uint,V> {
        ret linear_map(uint_hash, uint_eq);
    }

    #[test]
    fn inserts() {
        let mut m = ~int_linear_map();
        assert m.insert(1, 2);
        assert m.insert(2, 4);
        assert m.get(&1) == 2;
        assert m.get(&2) == 4;
    }

    #[test]
    fn overwrite() {
        let mut m = ~int_linear_map();
        assert m.insert(1, 2);
        assert m.get(&1) == 2;
        assert !m.insert(1, 3);
        assert m.get(&1) == 3;
    }

    #[test]
    fn conflicts() {
        let mut m = ~linear::linear_map_with_capacity(uint_hash, uint_eq, 4);
        assert m.insert(1, 2);
        assert m.insert(5, 3);
        assert m.insert(9, 4);
        assert m.get(&9) == 4;
        assert m.get(&5) == 3;
        assert m.get(&1) == 2;
    }

    #[test]
    fn conflict_remove() {
        let mut m = ~linear::linear_map_with_capacity(uint_hash, uint_eq, 4);
        assert m.insert(1, 2);
        assert m.insert(5, 3);
        assert m.insert(9, 4);
        assert m.remove(&1);
        assert m.get(&9) == 4;
        assert m.get(&5) == 3;
    }

    #[test]
    fn iterate() {
        let mut m = linear::linear_map_with_capacity(uint_hash, uint_eq, 4);
        for uint::range(0, 32) |i| {
            assert (&mut m).insert(i, i*2);
        }
        let mut observed = 0;
        for (&m).each |k, v| {
            assert v == k*2;
            observed |= (1 << k);
        }
        assert observed == 0xFFFF_FFFF;
    }
}
<commit_msg>send_map - fix size bug; add is_empty and test case for same<commit_after>/*!

Sendable hash maps.  Very much a work in progress.

*/

/**
 * A function that returns a hash of a value
 *
 * The hash should concentrate entropy in the lower bits.
 */
type hashfn<K> = pure fn~(K) -> uint;
type eqfn<K> = pure fn~(K, K) -> bool;

/// Open addressing with linear probing.
mod linear {
    export linear_map, linear_map_with_capacity, public_methods;

    const initial_capacity: uint = 32u; // 2^5
    type bucket<K,V> = {hash: uint, key: K, value: V};
    enum linear_map<K,V> {
        linear_map_({
            hashfn: pure fn~(x: &K) -> uint,
            eqfn: pure fn~(x: &K, y: &K) -> bool,
            resize_at: uint,
            size: uint,
            buckets: ~[option<bucket<K,V>>]})
    }

    // FIXME(#2979) -- with #2979 we could rewrite found_entry
    // to have type option<&bucket<K,V>> which would be nifty
    enum search_result {
        found_entry(uint), found_hole(uint), table_full
    }

    fn resize_at(capacity: uint) -> uint {
        ((capacity as float) * 3. / 4.) as uint
    }

    fn linear_map<K,V>(
        +hashfn: pure fn~(x: &K) -> uint,
        +eqfn: pure fn~(x: &K, y: &K) -> bool) -> linear_map<K,V> {

        linear_map_with_capacity(hashfn, eqfn, 32)
    }

    fn linear_map_with_capacity<K,V>(
        +hashfn: pure fn~(x: &K) -> uint,
        +eqfn: pure fn~(x: &K, y: &K) -> bool,
        initial_capacity: uint) -> linear_map<K,V> {

        linear_map_({
            hashfn: hashfn,
            eqfn: eqfn,
            resize_at: resize_at(initial_capacity),
            size: 0,
            buckets: vec::from_fn(initial_capacity, |_i| none)})
    }

    // FIXME(#2979) would allow us to use region type for k
    unsafe fn borrow<K>(&&k: K) -> &K {
        let p: *K = ptr::addr_of(k);
        p as &K
    }

    impl private_methods<K,V> for &const linear_map<K,V> {
        #[inline(always)]
        pure fn to_bucket(h: uint) -> uint {
            // FIXME(#3041) borrow a more sophisticated technique here from
            // Gecko, for example borrowing from Knuth, as Eich so
            // colorfully argues for here:
            // https://bugzilla.mozilla.org/show_bug.cgi?id=743107#c22
            h % self.buckets.len()
        }

        #[inline(always)]
        pure fn next_bucket(idx: uint, len_buckets: uint) -> uint {
            let n = (idx + 1) % len_buckets;
            unsafe{ // argh. log not considered pure.
                debug!{"next_bucket(%?, %?) = %?", idx, len_buckets, n};
            }
            ret n;
        }

        #[inline(always)]
        pure fn bucket_sequence(hash: uint, op: fn(uint) -> bool) -> uint {
            let start_idx = self.to_bucket(hash);
            let len_buckets = self.buckets.len();
            let mut idx = start_idx;
            loop {
                if !op(idx) {
                    ret idx;
                }
                idx = self.next_bucket(idx, len_buckets);
                if idx == start_idx {
                    ret start_idx;
                }
            }
        }

        #[inline(always)]
        pure fn bucket_for_key(
            buckets: &[option<bucket<K,V>>],
            k: &K) -> search_result {

            let hash = self.hashfn(k);
            self.bucket_for_key_with_hash(buckets, hash, k)
        }

        #[inline(always)]
        pure fn bucket_for_key_with_hash(
            buckets: &[option<bucket<K,V>>],
            hash: uint,
            k: &K) -> search_result {

            let _ = for self.bucket_sequence(hash) |i| {
                alt buckets[i] {
                  some(bkt) {
                    if bkt.hash == hash && self.eqfn(k, &bkt.key) {
                        ret found_entry(i);
                    }
                  }
                  none => {
                    ret found_hole(i);
                  }
                }
            };
            ret table_full;
        }
    }

    impl private_methods<K,V> for &mut linear_map<K,V> {
        /// Expands the capacity of the array and re-inserts each
        /// of the existing buckets.
        fn expand() {
            let old_capacity = self.buckets.len();
            let new_capacity = old_capacity * 2;
            self.resize_at = ((new_capacity as float) * 3.0 / 4.0) as uint;

            let mut old_buckets = vec::from_fn(new_capacity, |_i| none);
            self.buckets <-> old_buckets;

            for uint::range(0, old_capacity) |i| {
                let mut bucket = none;
                bucket <-> old_buckets[i];
                if bucket.is_some() {
                    self.insert_bucket(bucket);
                }
            }
        }

        fn insert_bucket(+bucket: option<bucket<K,V>>) {
            let {hash, key, value} <- option::unwrap(bucket);
            let _ = self.insert_internal(hash, key, value);
        }

        /// Inserts the key value pair into the buckets.
        /// Assumes that there will be a bucket.
        /// True if there was no previous entry with that key
        fn insert_internal(hash: uint, +k: K, +v: V) -> bool {
            alt self.bucket_for_key_with_hash(self.buckets, hash,
                                              unsafe{borrow(k)}) {
              table_full => {fail ~"Internal logic error";}
              found_hole(idx) {
                debug!{"insert fresh (%?->%?) at idx %?, hash %?",
                       k, v, idx, hash};
                self.buckets[idx] = some({hash: hash, key: k, value: v});
                self.size += 1;
                ret true;
              }
              found_entry(idx) => {
                debug!{"insert overwrite (%?->%?) at idx %?, hash %?",
                       k, v, idx, hash};
                self.buckets[idx] = some({hash: hash, key: k, value: v});
                ret false;
              }
            }
        }
    }

    impl public_methods<K,V> for &mut linear_map<K,V> {
        fn insert(+k: K, +v: V) -> bool {
            if self.size >= self.resize_at {
                // n.b.: We could also do this after searching, so
                // that we do not resize if this call to insert is
                // simply going to update a key in place.  My sense
                // though is that it's worse to have to search through
                // buckets to find the right spot twice than to just
                // resize in this corner case.
                self.expand();
            }

            let hash = self.hashfn(unsafe{borrow(k)});
            self.insert_internal(hash, k, v)
        }

        fn remove(k: &K) -> bool {
            // Removing from an open-addressed hashtable
            // is, well, painful.  The problem is that
            // the entry may lie on the probe path for other
            // entries, so removing it would make you think that
            // those probe paths are empty.
            //
            // To address this we basically have to keep walking,
            // re-inserting entries we find until we reach an empty
            // bucket.  We know we will eventually reach one because
            // we insert one ourselves at the beginning (the removed
            // entry).
            //
            // I found this explanation elucidating:
            // http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf

            let mut idx = alt self.bucket_for_key(self.buckets, k) {
              table_full | found_hole(_) => {
                ret false;
              }
              found_entry(idx) => {
                idx
              }
            };

            let len_buckets = self.buckets.len();
            self.buckets[idx] = none;
            idx = self.next_bucket(idx, len_buckets);
            while self.buckets[idx].is_some() {
                let mut bucket = none;
                bucket <-> self.buckets[idx];
                self.insert_bucket(bucket);
                idx = self.next_bucket(idx, len_buckets);
            }
            self.size -= 1;
            ret true;
        }
    }

    impl private_methods<K,V> for &linear_map<K,V> {
        fn search(hash: uint, op: fn(x: &option<bucket<K,V>>) -> bool) {
            let _ = self.bucket_sequence(hash, |i| op(&self.buckets[i]));
        }
    }

    impl public_methods<K,V> for &const linear_map<K,V> {
        fn len() -> uint {
            self.size
        }

        fn is_empty() -> bool {
            self.len() == 0
        }

        fn contains_key(k: &K) -> bool {
            alt self.bucket_for_key(self.buckets, k) {
              found_entry(_) => {true}
              table_full | found_hole(_) => {false}
            }
        }
    }

    impl public_methods<K,V: copy> for &const linear_map<K,V> {
        fn find(k: &K) -> option<V> {
            alt self.bucket_for_key(self.buckets, k) {
              found_entry(idx) => {
                alt check self.buckets[idx] {
                  some(bkt) => {some(copy bkt.value)}
                }
              }
              table_full | found_hole(_) => {
                none
              }
            }
        }

        fn get(k: &K) -> V {
            let value = self.find(k);
            if value.is_none() {
                fail fmt!{"No entry found for key: %?", k};
            }
            option::unwrap(value)
        }

        fn [](k: &K) -> V {
            self.get(k)
        }
    }

    impl imm_methods<K,V> for &linear_map<K,V> {
        /*
        FIXME --- #2979 must be fixed to typecheck this
        fn find_ptr(k: K) -> option<&V> {
            //XXX this should not type check as written, but it should
            //be *possible* to typecheck it...
            self.with_ptr(k, |v| v)
        }
        */

        fn each_ref(blk: fn(k: &K, v: &V) -> bool) {
            for vec::each(self.buckets) |slot| {
                let mut broke = false;
                do slot.iter |bucket| {
                    if !blk(&bucket.key, &bucket.value) {
                        broke = true; // FIXME(#3064) just write "break;"
                    }
                }
                if broke { break; }
            }
        }
        fn each_key_ref(blk: fn(k: &K) -> bool) {
            self.each_ref(|k, _v| blk(k))
        }
        fn each_value_ref(blk: fn(v: &V) -> bool) {
            self.each_ref(|_k, v| blk(v))
        }
    }

    impl public_methods<K: copy, V: copy> for &linear_map<K,V> {
        fn each(blk: fn(+K,+V) -> bool) {
            self.each_ref(|k,v| blk(copy *k, copy *v));
        }
    }
    impl public_methods<K: copy, V> for &linear_map<K,V> {
        fn each_key(blk: fn(+K) -> bool) {
            self.each_key_ref(|k| blk(copy *k));
        }
    }
    impl public_methods<K, V: copy> for &linear_map<K,V> {
        fn each_value(blk: fn(+V) -> bool) {
            self.each_value_ref(|v| blk(copy *v));
        }
    }
}

#[test]
mod test {

    import linear::linear_map;

    pure fn uint_hash(x: &uint) -> uint { *x }
    pure fn uint_eq(x: &uint, y: &uint) -> bool { *x == *y }

    fn int_linear_map<V>() -> linear_map<uint,V> {
        ret linear_map(uint_hash, uint_eq);
    }

    #[test]
    fn inserts() {
        let mut m = ~int_linear_map();
        assert m.insert(1, 2);
        assert m.insert(2, 4);
        assert m.get(&1) == 2;
        assert m.get(&2) == 4;
    }

    #[test]
    fn overwrite() {
        let mut m = ~int_linear_map();
        assert m.insert(1, 2);
        assert m.get(&1) == 2;
        assert !m.insert(1, 3);
        assert m.get(&1) == 3;
    }

    #[test]
    fn conflicts() {
        let mut m = ~linear::linear_map_with_capacity(uint_hash, uint_eq, 4);
        assert m.insert(1, 2);
        assert m.insert(5, 3);
        assert m.insert(9, 4);
        assert m.get(&9) == 4;
        assert m.get(&5) == 3;
        assert m.get(&1) == 2;
    }

    #[test]
    fn conflict_remove() {
        let mut m = ~linear::linear_map_with_capacity(uint_hash, uint_eq, 4);
        assert m.insert(1, 2);
        assert m.insert(5, 3);
        assert m.insert(9, 4);
        assert m.remove(&1);
        assert m.get(&9) == 4;
        assert m.get(&5) == 3;
    }

    #[test]
    fn empty() {
        let mut m = ~linear::linear_map_with_capacity(uint_hash, uint_eq, 4);
        assert m.insert(1, 2);
        assert !m.is_empty();
        assert m.remove(&1);
        assert m.is_empty();
    }

    #[test]
    fn iterate() {
        let mut m = linear::linear_map_with_capacity(uint_hash, uint_eq, 4);
        for uint::range(0, 32) |i| {
            assert (&mut m).insert(i, i*2);
        }
        let mut observed = 0;
        for (&m).each |k, v| {
            assert v == k*2;
            observed |= (1 << k);
        }
        assert observed == 0xFFFF_FFFF;
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove a doc typo<commit_after><|endoftext|>


<commit_before><commit_msg>Cap vsu voice wave reg at 4<commit_after><|endoftext|>


<commit_before><commit_msg>i hope this works. plz.<commit_after><|endoftext|>