<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

use super::builder::*;
use super::list::List;

/// Builder for List<T>
pub struct ListBuilder<T> {
    data: Builder<T>,
    offsets: Builder<i32>,
}

impl<T> ListBuilder<T> {
    /// Create a ListBuilder with a default capacity
    pub fn new() -> Self {
        ListBuilder::with_capacity(64)
    }

    /// Create a ListBuilder with the specified capacity
    pub fn with_capacity(n: usize) -> Self {
        let data = Builder::with_capacity(n);
        let mut offsets = Builder::with_capacity(n);
        offsets.push(0_i32);
        ListBuilder { data, offsets }
    }

    /// Push one array slot to the builder
    pub fn push(&mut self, slice: &[T]) {
        self.data.push_slice(slice);
        self.offsets.push(self.data.len() as i32);
    }

    /// Create an immutable List<T> from the builder
    pub fn finish(&mut self) -> List<T> {
        List::from_raw_parts(self.data.finish(), self.offsets.finish())
    }
}

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

    #[test]
    fn test_list_u8_default_capacity() {
        let mut b: ListBuilder<u8> = ListBuilder::new();
        b.push("Hello, ".as_bytes());
        b.push("World!".as_bytes());
        let buffer = b.finish();

        assert_eq!(2, buffer.len());
        assert_eq!("Hello, ".as_bytes(), buffer.slice(0));
        assert_eq!("World!".as_bytes(), buffer.slice(1));
    }

    #[test]
    fn test_list_u8_zero_capacity() {
        let mut b: ListBuilder<u8> = ListBuilder::with_capacity(0);
        b.push("Hello, ".as_bytes());
        b.push("World!".as_bytes());
        let buffer = b.finish();
        assert_eq!(2, buffer.len());
        assert_eq!("Hello, ".as_bytes(), buffer.slice(0));
        assert_eq!("World!".as_bytes(), buffer.slice(1));
    }

    #[test]
    fn test_empty_lists() {
        let mut b: ListBuilder<u8> = ListBuilder::new();
        b.push("Hello, ".as_bytes());
        b.push("".as_bytes());
        b.push("World!".as_bytes());
        let buffer = b.finish();

        assert_eq!(3, buffer.len());
        assert_eq!("Hello, ".as_bytes(), buffer.slice(0));
        assert_eq!("".as_bytes(), buffer.slice(1));
        assert_eq!("World!".as_bytes(), buffer.slice(2));
    }
}
<commit_msg>ARROW-2536: [Rust] optimize capacity allocation for ListBuilder<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

use super::builder::*;
use super::list::List;

/// Builder for List<T>
pub struct ListBuilder<T> {
    data: Builder<T>,
    offsets: Builder<i32>,
}

impl<T> ListBuilder<T> {
    /// Create a ListBuilder with a default capacity
    pub fn new() -> Self {
        ListBuilder::with_capacity(64)
    }

    /// Create a ListBuilder with the specified capacity
    pub fn with_capacity(n: usize) -> Self {
        let data = Builder::with_capacity(n);
        // take into account additional element (0), that we are pushing immediately
        let mut offsets = Builder::with_capacity(n + 1);
        offsets.push(0_i32);
        ListBuilder { data, offsets }
    }

    /// Push one array slot to the builder
    pub fn push(&mut self, slice: &[T]) {
        self.data.push_slice(slice);
        self.offsets.push(self.data.len() as i32);
    }

    /// Create an immutable List<T> from the builder
    pub fn finish(&mut self) -> List<T> {
        List::from_raw_parts(self.data.finish(), self.offsets.finish())
    }
}

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

    #[test]
    fn test_list_u8_default_capacity() {
        let mut b: ListBuilder<u8> = ListBuilder::new();
        b.push("Hello, ".as_bytes());
        b.push("World!".as_bytes());
        let buffer = b.finish();

        assert_eq!(2, buffer.len());
        assert_eq!("Hello, ".as_bytes(), buffer.slice(0));
        assert_eq!("World!".as_bytes(), buffer.slice(1));
    }

    #[test]
    fn test_list_u8_zero_capacity() {
        let mut b: ListBuilder<u8> = ListBuilder::with_capacity(0);
        b.push("Hello, ".as_bytes());
        b.push("World!".as_bytes());
        let buffer = b.finish();
        assert_eq!(2, buffer.len());
        assert_eq!("Hello, ".as_bytes(), buffer.slice(0));
        assert_eq!("World!".as_bytes(), buffer.slice(1));
    }

    #[test]
    fn test_empty_lists() {
        let mut b: ListBuilder<u8> = ListBuilder::new();
        b.push("Hello, ".as_bytes());
        b.push("".as_bytes());
        b.push("World!".as_bytes());
        let buffer = b.finish();

        assert_eq!(3, buffer.len());
        assert_eq!("Hello, ".as_bytes(), buffer.slice(0));
        assert_eq!("".as_bytes(), buffer.slice(1));
        assert_eq!("World!".as_bytes(), buffer.slice(2));
    }
}
<|endoftext|>


<commit_before>use ::cairo;
use ::glib::translate::*;
use ::libc;

use error::*;
use parsers::Parse;

pub enum RsvgPropertyBag {}

extern "C" {
    fn rsvg_property_bag_lookup (pbag: *const RsvgPropertyBag, key: *const libc::c_char) -> *const libc::c_char;
    fn rsvg_property_bag_dup (pbag: *const RsvgPropertyBag) -> *mut RsvgPropertyBag;
    fn rsvg_property_bag_free (pbag: *mut RsvgPropertyBag);
}

pub fn lookup (pbag: *const RsvgPropertyBag, key: &str) -> Option<String> {
    unsafe {
        let c_value = rsvg_property_bag_lookup (pbag, key.to_glib_none ().0);
        from_glib_none (c_value)
    }
}

pub fn dup (pbag: *const RsvgPropertyBag) -> *mut RsvgPropertyBag {
    unsafe {
        rsvg_property_bag_dup (pbag)
    }
}

pub fn free (pbag: *mut RsvgPropertyBag) {
    unsafe {
        rsvg_property_bag_free (pbag);
    }
}

pub fn parse_or_none<T> (pbag: *const RsvgPropertyBag,
                         key: &'static str,
                         data: <T as Parse>::Data,
                         validate: Option<fn(T) -> Result<T, AttributeError>>) -> Result <Option<T>, NodeError>
    where T: Parse<Err = AttributeError> + Copy
{
    let value = lookup (pbag, key);

    match value {
        Some (v) => {
            T::parse (&v, data)
                .and_then (|v|
                           if let Some(validate) = validate {
                               validate(v)
                                   .map(|v| Some(v))
                           } else {
                               Ok(Some(v))
                           })
                .map_err (|e| NodeError::attribute_error (key, e))
        },

        None => Ok(None)
    }
}

pub fn parse_or_default<T> (pbag: *const RsvgPropertyBag,
                            key: &'static str,
                            data: <T as Parse>::Data,
                            validate: Option<fn(T) -> Result<T, AttributeError>>) -> Result <T, NodeError>
    where T: Default + Parse<Err = AttributeError> + Copy
{
    parse_or_value (pbag, key, data, T::default (), validate)
}

pub fn parse_or_value<T> (pbag: *const RsvgPropertyBag,
                          key: &'static str,
                          data: <T as Parse>::Data,
                          value: T,
                          validate: Option<fn(T) -> Result<T, AttributeError>>) -> Result <T, NodeError>
    where T: Parse<Err = AttributeError> + Copy
{
    let r = parse_or_none (pbag, key, data, validate);

    match r {
        Ok (Some (v)) => Ok (v),
        Ok (None)     => Ok (value),
        Err (e)       => Err (e)
    }
}
<commit_msg>parse_or_value(): implement in terms of Option::unwrap_or()<commit_after>use ::cairo;
use ::glib::translate::*;
use ::libc;

use error::*;
use parsers::Parse;

pub enum RsvgPropertyBag {}

extern "C" {
    fn rsvg_property_bag_lookup (pbag: *const RsvgPropertyBag, key: *const libc::c_char) -> *const libc::c_char;
    fn rsvg_property_bag_dup (pbag: *const RsvgPropertyBag) -> *mut RsvgPropertyBag;
    fn rsvg_property_bag_free (pbag: *mut RsvgPropertyBag);
}

pub fn lookup (pbag: *const RsvgPropertyBag, key: &str) -> Option<String> {
    unsafe {
        let c_value = rsvg_property_bag_lookup (pbag, key.to_glib_none ().0);
        from_glib_none (c_value)
    }
}

pub fn dup (pbag: *const RsvgPropertyBag) -> *mut RsvgPropertyBag {
    unsafe {
        rsvg_property_bag_dup (pbag)
    }
}

pub fn free (pbag: *mut RsvgPropertyBag) {
    unsafe {
        rsvg_property_bag_free (pbag);
    }
}

pub fn parse_or_none<T> (pbag: *const RsvgPropertyBag,
                         key: &'static str,
                         data: <T as Parse>::Data,
                         validate: Option<fn(T) -> Result<T, AttributeError>>) -> Result <Option<T>, NodeError>
    where T: Parse<Err = AttributeError> + Copy
{
    let value = lookup (pbag, key);

    match value {
        Some (v) => {
            T::parse (&v, data)
                .and_then (|v|
                           if let Some(validate) = validate {
                               validate(v)
                                   .map(|v| Some(v))
                           } else {
                               Ok(Some(v))
                           })
                .map_err (|e| NodeError::attribute_error (key, e))
        },

        None => Ok(None)
    }
}

pub fn parse_or_default<T> (pbag: *const RsvgPropertyBag,
                            key: &'static str,
                            data: <T as Parse>::Data,
                            validate: Option<fn(T) -> Result<T, AttributeError>>) -> Result <T, NodeError>
    where T: Default + Parse<Err = AttributeError> + Copy
{
    parse_or_value (pbag, key, data, T::default (), validate)
}

pub fn parse_or_value<T> (pbag: *const RsvgPropertyBag,
                          key: &'static str,
                          data: <T as Parse>::Data,
                          value: T,
                          validate: Option<fn(T) -> Result<T, AttributeError>>) -> Result <T, NodeError>
    where T: Parse<Err = AttributeError> + Copy
{
    Ok (parse_or_none (pbag, key, data, validate)?.unwrap_or (value))
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A work queue for scheduling units of work across threads in a fork-join fashion.
//!
//! Data associated with queues is simply a pair of unsigned integers. It is expected that a
//! higher-level API on top of this could allow safe fork-join parallelism.

use native;
use rand;
use rand::{Rng, XorShiftRng};
use std::cast;
use std::mem;
use std::sync::atomics::{AtomicUint, SeqCst};
use std::sync::deque::{Abort, BufferPool, Data, Empty, Stealer, Worker};
use std::task::TaskOpts;

/// A unit of work.
///
/// The type parameter `QUD` stands for "queue user data" and represents global custom data for the
/// entire work queue, and the type parameter `WUD` stands for "work user data" and represents
/// custom data specific to each unit of work.
pub struct WorkUnit<QUD,WUD> {
    /// The function to execute.
    pub fun: extern "Rust" fn(WUD, &mut WorkerProxy<QUD,WUD>),
    /// Arbitrary data.
    pub data: WUD,
}

/// Messages from the supervisor to the worker.
enum WorkerMsg<QUD,WUD> {
    /// Tells the worker to start work.
    StartMsg(Worker<WorkUnit<QUD,WUD>>, *mut AtomicUint, *QUD),

    /// Tells the worker to stop. It can be restarted again with a `StartMsg`.
    StopMsg,

    /// Tells the worker thread to terminate.
    ExitMsg,
}

/// Messages to the supervisor.
enum SupervisorMsg<QUD,WUD> {
    FinishedMsg,
    ReturnDequeMsg(uint, Worker<WorkUnit<QUD,WUD>>),
}

/// Information that the supervisor thread keeps about the worker threads.
struct WorkerInfo<QUD,WUD> {
    /// The communication channel to the workers.
    chan: Sender<WorkerMsg<QUD,WUD>>,
    /// The buffer pool for this deque.
    pool: BufferPool<WorkUnit<QUD,WUD>>,
    /// The worker end of the deque, if we have it.
    deque: Option<Worker<WorkUnit<QUD,WUD>>>,
    /// The thief end of the work-stealing deque.
    thief: Stealer<WorkUnit<QUD,WUD>>,
}

/// Information specific to each worker thread that the thread keeps.
struct WorkerThread<QUD,WUD> {
    /// The index of this worker.
    index: uint,
    /// The communication port from the supervisor.
    port: Receiver<WorkerMsg<QUD,WUD>>,
    /// The communication channel on which messages are sent to the supervisor.
    chan: Sender<SupervisorMsg<QUD,WUD>>,
    /// The thief end of the work-stealing deque for all other workers.
    other_deques: Vec<Stealer<WorkUnit<QUD,WUD>>>,
    /// The random number generator for this worker.
    rng: XorShiftRng,
}

static SPIN_COUNT: uint = 1000;

impl<QUD:Send,WUD:Send> WorkerThread<QUD,WUD> {
    /// The main logic. This function starts up the worker and listens for
    /// messages.
    fn start(&mut self) {
        loop {
            // Wait for a start message.
            let (mut deque, ref_count, queue_data) = match self.port.recv() {
                StartMsg(deque, ref_count, queue_data) => (deque, ref_count, queue_data),
                StopMsg => fail!("unexpected stop message"),
                ExitMsg => return,
            };

            // We're off!
            //
            // FIXME(pcwalton): Can't use labeled break or continue cross-crate due to a Rust bug.
            loop {
                // FIXME(pcwalton): Nasty workaround for the lack of labeled break/continue
                // cross-crate.
                let mut work_unit = unsafe {
                    mem::uninit()
                };
                match deque.pop() {
                    Some(work) => work_unit = work,
                    None => {
                        // Become a thief.
                        let mut i = 0;
                        let mut should_continue = true;
                        loop {
                            let victim = (self.rng.next_u32() as uint) % self.other_deques.len();
                            match self.other_deques.get_mut(victim).steal() {
                                Empty | Abort => {
                                    // Continue.
                                }
                                Data(work) => {
                                    work_unit = work;
                                    break
                                }
                            }

                            if i == SPIN_COUNT {
                                match self.port.try_recv() {
                                    Ok(StopMsg) => {
                                        should_continue = false;
                                        break
                                    }
                                    Ok(ExitMsg) => return,
                                    Ok(_) => fail!("unexpected message"),
                                    _ => {}
                                }

                                i = 0
                            } else {
                                i += 1
                            }
                        }

                        if !should_continue {
                            break
                        }
                    }
                }

                // At this point, we have some work. Perform it.
                let mut proxy = WorkerProxy {
                    worker: &mut deque,
                    ref_count: ref_count,
                    queue_data: queue_data,
                };
                (work_unit.fun)(work_unit.data, &mut proxy);

                // The work is done. Now decrement the count of outstanding work items. If this was
                // the last work unit in the queue, then send a message on the channel.
                unsafe {
                    if (*ref_count).fetch_sub(1, SeqCst) == 1 {
                        self.chan.send(FinishedMsg)
                    }
                }
            }

            // Give the deque back to the supervisor.
            self.chan.send(ReturnDequeMsg(self.index, deque))
        }
    }
}

/// A handle to the work queue that individual work units have.
pub struct WorkerProxy<'a,QUD,WUD> {
    worker: &'a mut Worker<WorkUnit<QUD,WUD>>,
    ref_count: *mut AtomicUint,
    queue_data: *QUD,
}

impl<'a,QUD,WUD:Send> WorkerProxy<'a,QUD,WUD> {
    /// Enqueues a block into the work queue.
    #[inline]
    pub fn push(&mut self, work_unit: WorkUnit<QUD,WUD>) {
        unsafe {
            drop((*self.ref_count).fetch_add(1, SeqCst));
        }
        self.worker.push(work_unit);
    }

    /// Retrieves the queue user data.
    #[inline]
    pub fn user_data<'a>(&'a self) -> &'a QUD {
        unsafe {
            cast::transmute(self.queue_data)
        }
    }
}

/// A work queue on which units of work can be submitted.
pub struct WorkQueue<QUD,WUD> {
    /// Information about each of the workers.
    workers: Vec<WorkerInfo<QUD,WUD>>,
    /// A port on which deques can be received from the workers.
    port: Receiver<SupervisorMsg<QUD,WUD>>,
    /// The amount of work that has been enqueued.
    work_count: uint,
    /// Arbitrary user data.
    pub data: QUD,
}

impl<QUD:Send,WUD:Send> WorkQueue<QUD,WUD> {
    /// Creates a new work queue and spawns all the threads associated with
    /// it.
    pub fn new(task_name: &'static str, thread_count: uint, user_data: QUD) -> WorkQueue<QUD,WUD> {
        // Set up data structures.
        let (supervisor_chan, supervisor_port) = channel();
        let (mut infos, mut threads) = (vec!(), vec!());
        for i in range(0, thread_count) {
            let (worker_chan, worker_port) = channel();
            let mut pool = BufferPool::new();
            let (worker, thief) = pool.deque();
            infos.push(WorkerInfo {
                chan: worker_chan,
                pool: pool,
                deque: Some(worker),
                thief: thief,
            });
            threads.push(WorkerThread {
                index: i,
                port: worker_port,
                chan: supervisor_chan.clone(),
                other_deques: vec!(),
                rng: rand::weak_rng(),
            });
        }

        // Connect workers to one another.
        for i in range(0, thread_count) {
            for j in range(0, thread_count) {
                if i != j {
                    threads.get_mut(i).other_deques.push(infos.get(j).thief.clone())
                }
            }
            assert!(threads.get(i).other_deques.len() == thread_count - 1)
        }

        // Spawn threads.
        for thread in threads.move_iter() {
            let mut opts = TaskOpts::new();
            opts.name = Some(task_name.into_maybe_owned());
            native::task::spawn_opts(opts, proc() {
                let mut thread = thread;
                thread.start()
            })
        }

        WorkQueue {
            workers: infos,
            port: supervisor_port,
            work_count: 0,
            data: user_data,
        }
    }

    /// Enqueues a block into the work queue.
    #[inline]
    pub fn push(&mut self, work_unit: WorkUnit<QUD,WUD>) {
        match self.workers.get_mut(0).deque {
            None => {
                fail!("tried to push a block but we don't have the deque?!")
            }
            Some(ref mut deque) => deque.push(work_unit),
        }
        self.work_count += 1
    }

    /// Synchronously runs all the enqueued tasks and waits for them to complete.
    pub fn run(&mut self) {
        // Tell the workers to start.
        let mut work_count = AtomicUint::new(self.work_count);
        for worker in self.workers.mut_iter() {
            worker.chan.send(StartMsg(worker.deque.take_unwrap(), &mut work_count, &self.data))
        }

        // Wait for the work to finish.
        drop(self.port.recv());
        self.work_count = 0;

        // Tell everyone to stop.
        for worker in self.workers.iter() {
            worker.chan.send(StopMsg)
        }

        // Get our deques back.
        for _ in range(0, self.workers.len()) {
            match self.port.recv() {
                ReturnDequeMsg(index, deque) => self.workers.get_mut(index).deque = Some(deque),
                FinishedMsg => fail!("unexpected finished message!"),
            }
        }
    }

    pub fn shutdown(&mut self) {
        for worker in self.workers.iter() {
            worker.chan.send(ExitMsg)
        }
    }
}

<commit_msg>Make the workqueue's type parameter names less terrible<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A work queue for scheduling units of work across threads in a fork-join fashion.
//!
//! Data associated with queues is simply a pair of unsigned integers. It is expected that a
//! higher-level API on top of this could allow safe fork-join parallelism.

use native;
use rand;
use rand::{Rng, XorShiftRng};
use std::cast;
use std::mem;
use std::sync::atomics::{AtomicUint, SeqCst};
use std::sync::deque::{Abort, BufferPool, Data, Empty, Stealer, Worker};
use std::task::TaskOpts;

/// A unit of work.
///
/// # Type parameters
///
/// - `QueueData`: global custom data for the entire work queue.
/// - `WorkData`: custom data specific to each unit of work.
pub struct WorkUnit<QueueData, WorkData> {
    /// The function to execute.
    pub fun: extern "Rust" fn(WorkData, &mut WorkerProxy<QueueData, WorkData>),
    /// Arbitrary data.
    pub data: WorkData,
}

/// Messages from the supervisor to the worker.
enum WorkerMsg<QueueData, WorkData> {
    /// Tells the worker to start work.
    StartMsg(Worker<WorkUnit<QueueData, WorkData>>, *mut AtomicUint, *QueueData),
    /// Tells the worker to stop. It can be restarted again with a `StartMsg`.
    StopMsg,
    /// Tells the worker thread to terminate.
    ExitMsg,
}

/// Messages to the supervisor.
enum SupervisorMsg<QueueData, WorkData> {
    FinishedMsg,
    ReturnDequeMsg(uint, Worker<WorkUnit<QueueData, WorkData>>),
}

/// Information that the supervisor thread keeps about the worker threads.
struct WorkerInfo<QueueData, WorkData> {
    /// The communication channel to the workers.
    chan: Sender<WorkerMsg<QueueData, WorkData>>,
    /// The buffer pool for this deque.
    pool: BufferPool<WorkUnit<QueueData, WorkData>>,
    /// The worker end of the deque, if we have it.
    deque: Option<Worker<WorkUnit<QueueData, WorkData>>>,
    /// The thief end of the work-stealing deque.
    thief: Stealer<WorkUnit<QueueData, WorkData>>,
}

/// Information specific to each worker thread that the thread keeps.
struct WorkerThread<QueueData, WorkData> {
    /// The index of this worker.
    index: uint,
    /// The communication port from the supervisor.
    port: Receiver<WorkerMsg<QueueData, WorkData>>,
    /// The communication channel on which messages are sent to the supervisor.
    chan: Sender<SupervisorMsg<QueueData, WorkData>>,
    /// The thief end of the work-stealing deque for all other workers.
    other_deques: Vec<Stealer<WorkUnit<QueueData, WorkData>>>,
    /// The random number generator for this worker.
    rng: XorShiftRng,
}

static SPIN_COUNT: uint = 1000;

impl<QueueData: Send, WorkData: Send> WorkerThread<QueueData, WorkData> {
    /// The main logic. This function starts up the worker and listens for
    /// messages.
    fn start(&mut self) {
        loop {
            // Wait for a start message.
            let (mut deque, ref_count, queue_data) = match self.port.recv() {
                StartMsg(deque, ref_count, queue_data) => (deque, ref_count, queue_data),
                StopMsg => fail!("unexpected stop message"),
                ExitMsg => return,
            };

            // We're off!
            //
            // FIXME(pcwalton): Can't use labeled break or continue cross-crate due to a Rust bug.
            loop {
                // FIXME(pcwalton): Nasty workaround for the lack of labeled break/continue
                // cross-crate.
                let mut work_unit = unsafe {
                    mem::uninit()
                };
                match deque.pop() {
                    Some(work) => work_unit = work,
                    None => {
                        // Become a thief.
                        let mut i = 0;
                        let mut should_continue = true;
                        loop {
                            let victim = (self.rng.next_u32() as uint) % self.other_deques.len();
                            match self.other_deques.get_mut(victim).steal() {
                                Empty | Abort => {
                                    // Continue.
                                }
                                Data(work) => {
                                    work_unit = work;
                                    break
                                }
                            }

                            if i == SPIN_COUNT {
                                match self.port.try_recv() {
                                    Ok(StopMsg) => {
                                        should_continue = false;
                                        break
                                    }
                                    Ok(ExitMsg) => return,
                                    Ok(_) => fail!("unexpected message"),
                                    _ => {}
                                }

                                i = 0
                            } else {
                                i += 1
                            }
                        }

                        if !should_continue {
                            break
                        }
                    }
                }

                // At this point, we have some work. Perform it.
                let mut proxy = WorkerProxy {
                    worker: &mut deque,
                    ref_count: ref_count,
                    queue_data: queue_data,
                };
                (work_unit.fun)(work_unit.data, &mut proxy);

                // The work is done. Now decrement the count of outstanding work items. If this was
                // the last work unit in the queue, then send a message on the channel.
                unsafe {
                    if (*ref_count).fetch_sub(1, SeqCst) == 1 {
                        self.chan.send(FinishedMsg)
                    }
                }
            }

            // Give the deque back to the supervisor.
            self.chan.send(ReturnDequeMsg(self.index, deque))
        }
    }
}

/// A handle to the work queue that individual work units have.
pub struct WorkerProxy<'a, QueueData, WorkData> {
    worker: &'a mut Worker<WorkUnit<QueueData, WorkData>>,
    ref_count: *mut AtomicUint,
    queue_data: *QueueData,
}

impl<'a, QueueData, WorkData: Send> WorkerProxy<'a, QueueData, WorkData> {
    /// Enqueues a block into the work queue.
    #[inline]
    pub fn push(&mut self, work_unit: WorkUnit<QueueData, WorkData>) {
        unsafe {
            drop((*self.ref_count).fetch_add(1, SeqCst));
        }
        self.worker.push(work_unit);
    }

    /// Retrieves the queue user data.
    #[inline]
    pub fn user_data<'a>(&'a self) -> &'a QueueData {
        unsafe {
            cast::transmute(self.queue_data)
        }
    }
}

/// A work queue on which units of work can be submitted.
pub struct WorkQueue<QueueData, WorkData> {
    /// Information about each of the workers.
    workers: Vec<WorkerInfo<QueueData, WorkData>>,
    /// A port on which deques can be received from the workers.
    port: Receiver<SupervisorMsg<QueueData, WorkData>>,
    /// The amount of work that has been enqueued.
    work_count: uint,
    /// Arbitrary user data.
    pub data: QueueData,
}

impl<QueueData: Send, WorkData: Send> WorkQueue<QueueData, WorkData> {
    /// Creates a new work queue and spawns all the threads associated with
    /// it.
    pub fn new(task_name: &'static str, thread_count: uint, user_data: QueueData) -> WorkQueue<QueueData, WorkData> {
        // Set up data structures.
        let (supervisor_chan, supervisor_port) = channel();
        let (mut infos, mut threads) = (vec!(), vec!());
        for i in range(0, thread_count) {
            let (worker_chan, worker_port) = channel();
            let mut pool = BufferPool::new();
            let (worker, thief) = pool.deque();
            infos.push(WorkerInfo {
                chan: worker_chan,
                pool: pool,
                deque: Some(worker),
                thief: thief,
            });
            threads.push(WorkerThread {
                index: i,
                port: worker_port,
                chan: supervisor_chan.clone(),
                other_deques: vec!(),
                rng: rand::weak_rng(),
            });
        }

        // Connect workers to one another.
        for i in range(0, thread_count) {
            for j in range(0, thread_count) {
                if i != j {
                    threads.get_mut(i).other_deques.push(infos.get(j).thief.clone())
                }
            }
            assert!(threads.get(i).other_deques.len() == thread_count - 1)
        }

        // Spawn threads.
        for thread in threads.move_iter() {
            let mut opts = TaskOpts::new();
            opts.name = Some(task_name.into_maybe_owned());
            native::task::spawn_opts(opts, proc() {
                let mut thread = thread;
                thread.start()
            })
        }

        WorkQueue {
            workers: infos,
            port: supervisor_port,
            work_count: 0,
            data: user_data,
        }
    }

    /// Enqueues a block into the work queue.
    #[inline]
    pub fn push(&mut self, work_unit: WorkUnit<QueueData, WorkData>) {
        match self.workers.get_mut(0).deque {
            None => {
                fail!("tried to push a block but we don't have the deque?!")
            }
            Some(ref mut deque) => deque.push(work_unit),
        }
        self.work_count += 1
    }

    /// Synchronously runs all the enqueued tasks and waits for them to complete.
    pub fn run(&mut self) {
        // Tell the workers to start.
        let mut work_count = AtomicUint::new(self.work_count);
        for worker in self.workers.mut_iter() {
            worker.chan.send(StartMsg(worker.deque.take_unwrap(), &mut work_count, &self.data))
        }

        // Wait for the work to finish.
        drop(self.port.recv());
        self.work_count = 0;

        // Tell everyone to stop.
        for worker in self.workers.iter() {
            worker.chan.send(StopMsg)
        }

        // Get our deques back.
        for _ in range(0, self.workers.len()) {
            match self.port.recv() {
                ReturnDequeMsg(index, deque) => self.workers.get_mut(index).deque = Some(deque),
                FinishedMsg => fail!("unexpected finished message!"),
            }
        }
    }

    pub fn shutdown(&mut self) {
        for worker in self.workers.iter() {
            worker.chan.send(ExitMsg)
        }
    }
}

<|endoftext|>


<commit_before>use polynomial::Polynomial;
use nalgebra::{Vector2, Dot};
use std::cmp::max;
use roots::find_roots_quartic;
use ::rounding_error_tolerant_math::*;

use std::io::Write;
macro_rules! printlnerr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

// TODO: polymorphic in number of dimensions, and numeric type
// TODO: optimize away the pointless inefficiencies I introduced
// note: the third time is not acceleration, but the coefficient of X squared, which is 2 times acceleration
pub type Coordinate = i64;
#[derive (Clone, Debug)]
pub struct QuadraticTrajectory {
  data: [[Coordinate; 3]; 2],
  time_scale_shift: u32,
}

fn distance_squared_would_be(first: (Coordinate, &QuadraticTrajectory),
                             second: (Coordinate, &QuadraticTrajectory),
                             when: Coordinate)
                             -> Coordinate {
  let displacement = first.1.updated_by(when - first.0).evaluate() -
                     second.1.updated_by(when - second.0).evaluate();
  displacement.dot(&displacement)
}

impl QuadraticTrajectory {
  pub fn new(time_scale_shift: u32, coordinates: [Coordinate; 6]) -> QuadraticTrajectory {
    QuadraticTrajectory {
      time_scale_shift: time_scale_shift,
      data: [[coordinates[0], coordinates[2], coordinates[4]],
             [coordinates[1], coordinates[3], coordinates[5]]],
    }
  }

  pub fn updated_by(&self, time: Coordinate) -> QuadraticTrajectory {
    let mut result = self.clone();
    result.update_by(time);
    result
  }

  pub fn update_by(&mut self, time: Coordinate) {
    for quadratic in self.data.iter_mut() {
      quadratic_move_origin_rounding_change_towards_0(quadratic.as_mut(),
                                                      time,
                                                      self.time_scale_shift);
    }
  }

  pub fn add_acceleration(&mut self, acceleration: Vector2<Coordinate>) {
    self.data[0][2] += acceleration[0] * 2;
    self.data[1][2] += acceleration[1] * 2;
  }
  pub fn evaluate(&self) -> Vector2<Coordinate> {
    Vector2::new(self.data[0][0], self.data[1][0])

  }

  // direction == -1->"when the distance between the trajectories drops below the distance argument"
  // direction == 1->"when the distance between the trajectories exceeds the distance argument"
  pub fn approximately_when_distance_passes(distance: Coordinate,
                                            direction: Coordinate,
                                            first: (Coordinate, &QuadraticTrajectory),
                                            second: (Coordinate, &QuadraticTrajectory))
                                            -> Option<Coordinate> {
    assert!(first.1.time_scale_shift == second.1.time_scale_shift,
            "we don't actually support interactions between trajectories with different scales");

    let base = max(first.0, second.0);
    if (distance_squared_would_be(first, second, base) - distance * distance) * direction > 0 {
		printlnerr!("rejefoo");
      return Some(base);
    }

    let intervals =
      quadratic_trajectories_possible_distance_crossing_intervals(distance,
                                                                  (first.0,
                                                                   &[first.1.data[0],
                                                                     first.1.data[1]]),
                                                                  (second.0,
                                                                   &[second.1.data[0],
                                                                     second.1.data[1]]),
                                                                  first.1.time_scale_shift);
    for interval in intervals.iter() {
      if interval.max() + 1 > base {

        if (distance_squared_would_be(first, second, interval.max() + 1) -
            distance * distance) * direction > 0 {
          return Some(interval.max() + 1);
        } //else {printlnerr!("rejected interval for not ending in the correct position")}
      } //else {printlnerr!("rejected interval for being in the past")}
    }
    None
  }
}
<commit_msg>Workaround<commit_after>use polynomial::Polynomial;
use nalgebra::{Vector2, Dot};
use std::cmp::max;
use roots::find_roots_quartic;
use ::rounding_error_tolerant_math::*;

use std::io::Write;
macro_rules! printlnerr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

// TODO: polymorphic in number of dimensions, and numeric type
// TODO: optimize away the pointless inefficiencies I introduced
// note: the third time is not acceleration, but the coefficient of X squared, which is 2 times acceleration
pub type Coordinate = i64;
#[derive (Clone, Debug)]
pub struct QuadraticTrajectory {
  data: [[Coordinate; 3]; 2],
  time_scale_shift: u32,
}

fn distance_squared_would_be(first: (Coordinate, &QuadraticTrajectory),
                             second: (Coordinate, &QuadraticTrajectory),
                             when: Coordinate)
                             -> Coordinate {
  let displacement = first.1.updated_by(when - first.0).evaluate() -
                     second.1.updated_by(when - second.0).evaluate();
  displacement.dot(&displacement)
}

impl QuadraticTrajectory {
  pub fn new(time_scale_shift: u32, coordinates: [Coordinate; 6]) -> QuadraticTrajectory {
    QuadraticTrajectory {
      time_scale_shift: time_scale_shift,
      data: [[coordinates[0], coordinates[2], coordinates[4]],
             [coordinates[1], coordinates[3], coordinates[5]]],
    }
  }

  pub fn updated_by(&self, time: Coordinate) -> QuadraticTrajectory {
    let mut result = self.clone();
    result.update_by(time);
    result
  }

  pub fn update_by(&mut self, time: Coordinate) {
    for quadratic in self.data.iter_mut() {
      quadratic_move_origin_rounding_change_towards_0(quadratic.as_mut(),
                                                      time,
                                                      self.time_scale_shift);
    }
  }

  pub fn add_acceleration(&mut self, acceleration: Vector2<Coordinate>) {
    self.data[0][2] += acceleration[0] * 2;
    self.data[1][2] += acceleration[1] * 2;
  }
  pub fn evaluate(&self) -> Vector2<Coordinate> {
    Vector2::new(self.data[0][0], self.data[1][0])

  }

  // direction == -1->"when the distance between the trajectories drops below the distance argument"
  // direction == 1->"when the distance between the trajectories exceeds the distance argument"
  pub fn approximately_when_distance_passes(distance: Coordinate,
                                            direction: Coordinate,
                                            first: (Coordinate, &QuadraticTrajectory),
                                            second: (Coordinate, &QuadraticTrajectory))
                                            -> Option<Coordinate> {
    assert!(first.1.time_scale_shift == second.1.time_scale_shift,
            "we don't actually support interactions between trajectories with different scales");

    let base = max(first.0, second.0);
    if (distance_squared_would_be(first, second, base) - distance * distance) * direction > 0 {
		printlnerr!("rejefoo");
      return Some(base);
    }

    let intervals =
      quadratic_trajectories_possible_distance_crossing_intervals(distance,
                                                                  (first.0,
                                                                   &[first.1.data[0],
                                                                     first.1.data[1]]),
                                                                  (second.0,
                                                                   &[second.1.data[0],
                                                                     second.1.data[1]]),
                                                                  first.1.time_scale_shift);
    for interval in intervals.iter() {
      if interval.max() != i64::max_value() && interval.max() + 1 > base {

        if (distance_squared_would_be(first, second, interval.max() + 1) -
            distance * distance) * direction > 0 {
          return Some(interval.max() + 1);
        } //else {printlnerr!("rejected interval for not ending in the correct position")}
      } //else {printlnerr!("rejected interval for being in the past")}
    }
    None
  }
}
<|endoftext|>


<commit_before>
#[derive(Show,PartialEq)]
struct Node<T> {
    payload: T,
    next: Option<Box<Node<T>>>,
    prev: Option<Box<Node<T>>>,
}

impl<T> Node<T> {
    pub fn new(payload: T) -> Node<T> {
        Node::<T> {
            payload: payload,
            next: None,
            prev: None,
        }
    }

    pub fn payload(&self) -> Option<&T> {
        Some(&self.payload)
    }
}

struct LinkedList<T> {
    root: Option<Node<T>>,
}

impl<T> LinkedList<T> {
    pub fn new() -> LinkedList<T> {
        LinkedList::<T> {
            root: None,
        }
    }

    fn add(node: Node<T>) {

        let last_node = &node;

        //loop {
        //    if last_node.payload == None {
        //        last_node = node;
        //        break;
        //    }
        //}
    }
}

#[test]
fn test_node_new() {
    let expected = Node {
        payload: "test",
        next: None,
        prev: None,
    };

    let node: Node<&str> = Node::new("test");

    assert_eq!(expected.payload,  node.payload);
    assert_eq!(expected.next,     node.next);
    assert_eq!(expected.prev,     node.prev);
}

#[test]
fn test_node_payload() {
    let node: Node<&str> = Node::new("test");
    assert_eq!(&"test", node.payload().unwrap());
}
<commit_msg>Broken version of `add`<commit_after>
#[derive(Show,PartialEq)]
struct Node<T> {
    payload: T,
    next: Option<Box<Node<T>>>,
    prev: Option<Box<Node<T>>>,
}

impl<T> Node<T> {
    pub fn new(payload: T) -> Node<T> {
        Node::<T> {
            payload: payload,
            next: None,
            prev: None,
        }
    }

    pub fn payload(&self) -> Option<&T> {
        Some(&self.payload)
    }
}

pub struct LinkedList<T> {
    head: Option<Box<Node<T>>>,
    tail: Option<Box<Node<T>>>,
}

impl<T> LinkedList<T> {
    pub fn new() -> LinkedList<T> {
        LinkedList::<T> {
            head: None,
            tail: None,
        }
    }

    pub fn add(&mut self, payload: T) {

        match self.head {
            None            => self.head = Some(Box::new(Node::new(payload))),
            Some(ref ptr)   => {
                let mut node_ptr = ptr;
                loop {

                    match node_ptr.next {
                        None => {
                            println!("this is the last");
                            /*node_ptr.next = Some(Box::new(Node {
                                payload: payload,
                                next: None,
                                prev: None, //Some(Box::new(&node_ptr)),
                            }));*/
                            break;
                        },
                        Some(ref ptr)   => {
                            node_ptr = ptr;
                        },
                    }

                }
            },
        }
    }
}

#[test]
fn node_new() {
    let expected = Node {
        payload: "test",
        next: None,
        prev: None,
    };

    let node: Node<&str> = Node::new("test");

    assert_eq!(expected.payload,  node.payload);
    assert_eq!(expected.next,     node.next);
    assert_eq!(expected.prev,     node.prev);
}

#[test]
fn node_payload() {
    let node: Node<&str> = Node::new("test");
    assert_eq!(&"test", node.payload().unwrap());
}

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

    #[test]
    fn new_linked_list() {
        let mut list: super::LinkedList<String> = super::LinkedList::new();
        list.add("first".to_string());
        println!("Value added: {}", list.head.unwrap().payload);
        //assert_eq!(list.head.unwrap().payload, "first".to_string());
    }

    #[test]
    fn multiple_nodes() {
        let mut list: super::LinkedList<String> = super::LinkedList::new();
        list.add("first".to_string());
        list.add("second".to_string());
        //println!("Value added: {}", list.head.unwrap().payload);
        //assert_eq!(list.head.unwrap().payload, "first".to_string());
    }

}
<|endoftext|>


<commit_before>extern crate oauthcli;
extern crate url;
extern crate hyper;

use std::io::Read;
use self::url::form_urlencoded::serialize;
use self::hyper::{Client, Error};
use self::hyper::client::Response;
use self::hyper::method::Method;
use self::hyper::status::StatusCode;
use self::hyper::header::{Headers, Authorization, ContentType};

pub struct TwitterClient {
	consumer_key: String,
	consumer_secret: String,
	access_key: String,
	access_secret: String,
	client: Client
}

#[derive(Debug)]
pub enum StatusUpdateError {
	Duplicated,
	RateLimitExceeded,
	Invalid,
	Network,
	Unauthorized,
	Unknown
}

impl TwitterClient {

	pub fn new(consumer_key: String, consumer_secret: String, access_key: String, access_secret: String) -> TwitterClient
	{
		TwitterClient {
			consumer_key: consumer_key,
			consumer_secret: consumer_secret,
			access_key: access_key,
			access_secret: access_secret,
			client: Client::new()
		}
	}

	pub fn is_valid(&self) -> bool
	{
		// TODO: implement token validation
		return true;
	}

	pub fn update_status(&self, message: String)
	 -> Result<(), StatusUpdateError>
	{
		let api_url = "https://api.twitter.com/1.1/statuses/update.json";
		let args = vec![("status".to_string(), message)];
		let res = self.request(Method::Post, api_url, args);

		match res {
			Ok(mut res) => {
				match res.status {

					StatusCode::Forbidden => {

						let mut body = String::new();

						if let Err(_) = res.read_to_string(&mut body) {
							return Err(StatusUpdateError::Unknown);
						}

						if body.contains("140") {
							return Err(StatusUpdateError::Invalid);
						} else if body.contains("duplicate") {
							return Err(StatusUpdateError::Duplicated);
						}

						return Err(StatusUpdateError::Unknown);

					},

					StatusCode::Ok => return Ok(()),
					StatusCode::TooManyRequests =>
						return Err(StatusUpdateError::RateLimitExceeded),
					StatusCode::Unauthorized =>
						return Err(StatusUpdateError::Unauthorized),
					_ => return Err(StatusUpdateError::Unknown)
				}
			},
			Err(_) => return Err(StatusUpdateError::Network)
		}
	}

	fn request(&self, method: Method, api_url: &str, args: Vec<(String, String)>)
	 -> Result<Response, Error>
	{
		match method {

			Method::Get => {

				let mut headers = Headers::new();
				let oauth_header = self.construct_oauth_header("GET", api_url, args);
				headers.set(Authorization(oauth_header));

				let result = self.client.get(api_url).headers(headers).send();

				return result;

			},

			Method::Post => {

				let content_type = ContentType("application/x-www-form-urlencoded".parse().unwrap());

				let args_serialized = &serialize(&args);

				/* let mut args_serializer = Serializer::new(String::new());
				for &(ref k, ref v) in &args {
					args_serializer.append_pair(k, v);
				}
				let args_serialized = args_serializer.finish();*/

				let mut headers = Headers::new();
				let oauth_header = self.construct_oauth_header("POST", api_url, args);
				headers.set(Authorization(oauth_header));
				headers.set(content_type);

				let result = self.client.post(api_url).body(args_serialized).headers(headers).send();

				return result;

			},

			_ => {
				panic!();
			}
		}
	}

	fn construct_oauth_header(&self, method: &str, api_url: &str, args: Vec<(String, String)>)
	 -> String
	{
		let oauth_header = oauthcli::authorization_header(
			method,
			url::Url::parse(api_url).unwrap(),
			None,
			&self.consumer_key,
			&self.consumer_secret,
			Some(&self.access_key),
			Some(&self.access_secret),
			oauthcli::SignatureMethod::HmacSha1,
			&oauthcli::timestamp(),
			&oauthcli::nonce(),
			None,
			None,
			args.into_iter()
		);

		return oauth_header;
	}
}
<commit_msg>Format twitter_client.rs<commit_after>extern crate oauthcli;
extern crate url;
extern crate hyper;

use std::io::Read;
use self::url::form_urlencoded::serialize;
use self::hyper::{Client, Error};
use self::hyper::client::Response;
use self::hyper::method::Method;
use self::hyper::status::StatusCode;
use self::hyper::header::{Headers, Authorization, ContentType};

pub struct TwitterClient {
	consumer_key: String,
	consumer_secret: String,
	access_key: String,
	access_secret: String,
	client: Client
}

#[derive(Debug)]
pub enum StatusUpdateError {
	Duplicated,
	RateLimitExceeded,
	Invalid,
	Network,
	Unauthorized,
	Unknown
}

impl TwitterClient {

	pub fn new(consumer_key: String, consumer_secret: String, access_key: String, access_secret: String) -> TwitterClient
	{
		TwitterClient {
			consumer_key: consumer_key,
			consumer_secret: consumer_secret,
			access_key: access_key,
			access_secret: access_secret,
			client: Client::new()
		}
	}

	pub fn is_valid(&self) -> bool
	{
		// TODO: implement token validation
		return true;
	}

	pub fn update_status(&self, message: String)
	 -> Result<(), StatusUpdateError>
	{
		let api_url = "https://api.twitter.com/1.1/statuses/update.json";
		let args = vec![("status".to_string(), message)];
		let res = self.request(Method::Post, api_url, args);

		match res {
			Ok(mut res) => {
				match res.status {

					StatusCode::Forbidden => {

						let mut body = String::new();

						if let Err(_) = res.read_to_string(&mut body) {
							return Err(StatusUpdateError::Unknown);
						}

						if body.contains("140") {
							return Err(StatusUpdateError::Invalid);
						} else if body.contains("duplicate") {
							return Err(StatusUpdateError::Duplicated);
						}

						return Err(StatusUpdateError::Unknown);

					},

					StatusCode::Ok => return Ok(()),
					StatusCode::TooManyRequests =>
						return Err(StatusUpdateError::RateLimitExceeded),
					StatusCode::Unauthorized =>
						return Err(StatusUpdateError::Unauthorized),
					_ => return Err(StatusUpdateError::Unknown)
				}
			},
			Err(_) => return Err(StatusUpdateError::Network)
		}
	}

	fn request(&self, method: Method, api_url: &str, args: Vec<(String, String)>)
	 -> Result<Response, Error>
	{
		match method {

			Method::Get => {

				let mut headers = Headers::new();
				let oauth_header = self.construct_oauth_header("GET", api_url, args);
				headers.set(Authorization(oauth_header));

				let result = self.client.get(api_url).headers(headers).send();

				return result;

			},

			Method::Post => {

				let content_type = ContentType("application/x-www-form-urlencoded".parse().unwrap());

				let args_serialized = &serialize(&args);

				/* let mut args_serializer = Serializer::new(String::new());
				for &(ref k, ref v) in &args {
					args_serializer.append_pair(k, v);
				}
				let args_serialized = args_serializer.finish();*/

				let mut headers = Headers::new();
				let oauth_header = self.construct_oauth_header("POST", api_url, args);
				headers.set(Authorization(oauth_header));
				headers.set(content_type);

				let result = self.client.post(api_url).body(args_serialized).headers(headers).send();

				return result;

			},

			_ => {
				panic!();
			}
		}
	}

	fn construct_oauth_header(&self, method: &str, api_url: &str, args: Vec<(String, String)>)
	 -> String
	{
		let oauth_header = oauthcli::authorization_header(
			method,
			url::Url::parse(api_url).unwrap(),
			None,
			&self.consumer_key,
			&self.consumer_secret,
			Some(&self.access_key),
			Some(&self.access_secret),
			oauthcli::SignatureMethod::HmacSha1,
			&oauthcli::timestamp(),
			&oauthcli::nonce(),
			None,
			None,
			args.into_iter()
		);

		return oauth_header;
	}
}
<|endoftext|>


<commit_before>/*
 * Cymbalum, Molecular Simulation in Rust
 * Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
*/
use std::f64::consts::PI;

use ::types::Vector3D;
use ::types::Matrix3;

/// The type of a cell determine how we will be able to compute the periodic
/// boundaries condition.
#[derive(Clone, Copy)]
pub enum CellType {
    /// Infinite unit cell, with no boundaries
    INFINITE,
    /// Orthorombic unit cell, with cuboide shape
    ORTHOROMBIC,
    /// Triclinic unit cell, with arbitrary parallelepipedic shape
    TRICLINIC,
}

/// The Universe type hold all the data about a system.
#[derive(Clone, Copy)]
pub struct UnitCell {
    data: Matrix3,
    celltype: CellType,
}

impl UnitCell {
    /// Create an infinite unit cell
    pub fn new() -> UnitCell {
        UnitCell{data: Matrix3::zero(), celltype: CellType::INFINITE}
    }
    /// Create an orthorombic unit cell
    pub fn ortho(a: f64, b: f64, c: f64) -> UnitCell {
        UnitCell{data: Matrix3::new(a, 0.0, 0.0,
                                    0.0, b, 0.0,
                                    0.0, 0.0, c),
                 celltype: CellType::ORTHOROMBIC}
    }
    /// Create a cubic unit cell
    pub fn cubic(L: f64) -> UnitCell {
        UnitCell{data: Matrix3::new(L, 0.0, 0.0,
                                    0.0, L, 0.0,
                                    0.0, 0.0, L),
                 celltype: CellType::ORTHOROMBIC}
    }
    /// Create a triclinic unit cell
    pub fn triclinic(a: f64, b: f64, c: f64, alpha: f64, beta: f64, gamma: f64) -> UnitCell {
        let cos_alpha = deg2rad(alpha).cos();
        let cos_beta = deg2rad(beta).cos();
        let (sin_gamma, cos_gamma) = deg2rad(gamma).sin_cos();

        let b_x = b * cos_gamma;
        let b_y = b * sin_gamma;

        let c_x = c * cos_beta;
        let c_y = c * (cos_alpha - cos_beta*cos_gamma)/sin_gamma;
        let c_z = f64::sqrt(c*c - c_y*c_y - c_x*c_x);

        UnitCell{data: Matrix3::new(a,   b_x, c_x,
                                    0.0, b_y, c_y,
                                    0.0, 0.0, c_z),
                 celltype: CellType::TRICLINIC}
    }

    /// Get the cell type
    pub fn celltype(&self) -> CellType {
        self.celltype
    }
    /// Set the cell type
    pub fn set_celltype(&mut self, ctype: CellType) {
        self.celltype = ctype;
    }

    /// Get the first vector of the cell
    pub fn vect_a(&self) -> Vector3D {
        let x = self.data[(0, 0)];
        let y = self.data[(1, 0)];
        let z = self.data[(2, 0)];
        Vector3D::new(x, y, z)
    }
    /// Get the first length of the cell
    pub fn a(&self) -> f64 {
        match self.celltype {
            CellType::TRICLINIC => self.vect_a().norm(),
            _ => self.data[(0, 0)],
        }
    }

    /// Get the second length of the cell
    pub fn vect_b(&self) -> Vector3D {
        let x = self.data[(0, 1)];
        let y = self.data[(1, 1)];
        let z = self.data[(2, 1)];
        Vector3D::new(x, y, z)
    }
    /// Get the second length of the cell
    pub fn b(&self) -> f64 {
        match self.celltype {
            CellType::TRICLINIC => self.vect_b().norm(),
            _ => self.data[(1, 1)],
        }
    }

    /// Get the third length of the cell
    pub fn vect_c(&self) -> Vector3D {
        let x = self.data[(0, 2)];
        let y = self.data[(1, 2)];
        let z = self.data[(2, 2)];
        Vector3D::new(x, y, z)
    }
    /// Get the second length of the cell
    pub fn c(&self) -> f64 {
        match self.celltype {
            CellType::TRICLINIC => self.vect_c().norm(),
            _ => self.data[(2, 2)],
        }
    }

    /// Get the first angle of the cell
    pub fn alpha(&self) -> f64 {
        match self.celltype {
            CellType::TRICLINIC => {
                let b = self.vect_b();
                let c = self.vect_c();
                rad2deg(angle(b, c))
            },
            _ => 90.0,
        }
    }

    /// Get the second angle of the cell
    pub fn beta(&self) -> f64 {
        match self.celltype {
            CellType::TRICLINIC => {
                let a = self.vect_a();
                let c = self.vect_c();
                rad2deg(angle(a, c))
            },
            _ => 90.0,
        }
    }

    /// Get the third angle of the cell
    pub fn gamma(&self) -> f64 {
        match self.celltype {
            CellType::TRICLINIC => {
                let a = self.vect_a();
                let b = self.vect_b();
                rad2deg(angle(a, b))
            },
            _ => 90.0,
        }
    }

    /// Get the volume angle of the cell
    pub fn volume(&self) -> f64 {
        match self.celltype {
            CellType::INFINITE => 0.0,
            CellType::ORTHOROMBIC => self.a()*self.b()*self.c(),
            CellType::TRICLINIC => {
                // The volume is the mixed product of the three cell vectors
                let a = self.vect_a();
                let b = self.vect_b();
                let c = self.vect_c();
                a * (b ^ c)
            },
        }
    }

    /// Scale this unit cell in-place by multiplying the H matrix by `s`.
    pub fn scale_mut(&mut self, s: Matrix3) {
        self.data = s * self.data;
    }

    /// Scale this unit cell by multiplying the H matrix by `s`, and return a new unit cell
    pub fn scale(&self, s: Matrix3) -> UnitCell {
        UnitCell{data: s * self.data, celltype: self.celltype}
    }

    /// Wrap a vector in the unit cell, obeying the periodic boundary conditions
    pub fn wrap_vector(&self, vect: &mut Vector3D) {
        match self.celltype {
            CellType::INFINITE => (),
            CellType::ORTHOROMBIC => {
                vect.x = vect.x - f64::round(vect.x/self.a())*self.a();
                vect.y = vect.y - f64::round(vect.y/self.b())*self.b();
                vect.z = vect.z - f64::round(vect.z/self.c())*self.c();
            },
            CellType::TRICLINIC => {
                let inv = self.data.inverse();
                let mut fractional = inv * (*vect);
                fractional.x = fractional.x - f64::round(fractional.x);
                fractional.y = fractional.y - f64::round(fractional.y);
                fractional.z = fractional.z - f64::round(fractional.z);
                let res = self.data * fractional;
                vect.x = res.x;
                vect.y = res.y;
                vect.z = res.z;
            },
        }
    }

    /// Periodic boundary conditions distance between the point `u` and the point `v`
    pub fn distance(&self, u: &Vector3D, v: &Vector3D) -> f64 {
        let mut d = *v - *u;
        self.wrap_vector(&mut d);
        return d.norm();
    }
}

/// Convert `x` from degrees to radians
fn deg2rad(x: f64) -> f64 {
    x * PI / 180.0
}
/// Convert `x` from radians to degrees
fn rad2deg(x: f64) -> f64 {
    x * 180.0 / PI
}

/// Get the angles between the vectors `u` and `v`.
fn angle(u: Vector3D, v: Vector3D) -> f64 {
    let un = u.normalized();
    let vn = v.normalized();
    f64::acos(un*vn)
}

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

    #[test]
    fn infinite() {
        let cell = UnitCell::new();
        assert_eq!(cell.a(), 0.0);
        assert_eq!(cell.b(), 0.0);
        assert_eq!(cell.c(), 0.0);

        assert_eq!(cell.alpha(), 90.0);
        assert_eq!(cell.beta(), 90.0);
        assert_eq!(cell.gamma(), 90.0);

        assert_eq!(cell.volume(), 0.0);
    }

    #[test]
    fn cubic() {
        let cell = UnitCell::cubic(3.0);
        assert_eq!(cell.a(), 3.0);
        assert_eq!(cell.b(), 3.0);
        assert_eq!(cell.c(), 3.0);

        assert_eq!(cell.alpha(), 90.0);
        assert_eq!(cell.beta(), 90.0);
        assert_eq!(cell.gamma(), 90.0);

        assert_eq!(cell.volume(), 3.0*3.0*3.0);
    }

    #[test]
    fn orthorombic() {
        let cell = UnitCell::ortho(3.0, 4.0, 5.0);
        assert_eq!(cell.a(), 3.0);
        assert_eq!(cell.b(), 4.0);
        assert_eq!(cell.c(), 5.0);

        assert_eq!(cell.alpha(), 90.0);
        assert_eq!(cell.beta(), 90.0);
        assert_eq!(cell.gamma(), 90.0);

        assert_eq!(cell.volume(), 3.0*4.0*5.0);
    }

    #[test]
    fn triclinic() {
        let cell = UnitCell::triclinic(3.0, 4.0, 5.0, 80.0, 90.0, 110.0);
        assert_eq!(cell.a(), 3.0);
        assert_eq!(cell.b(), 4.0);
        assert_eq!(cell.c(), 5.0);

        assert_eq!(cell.alpha(), 80.0);
        assert_eq!(cell.beta(), 90.0);
        assert_eq!(cell.gamma(), 110.0);

        assert_approx_eq!(cell.volume(), 55.410529, 1e-6);
    }

    #[test]
    fn scale() {
        let cell = UnitCell::ortho(3.0, 4.0, 5.0);
        let A = 2.0 * Matrix3::one();
        let cell = cell.scale(A);

        assert_eq!(cell.a(), 6.0);
        assert_eq!(cell.b(), 8.0);
        assert_eq!(cell.c(), 10.0);
    }

    #[test]
    fn scale_mut() {
        let mut cell = UnitCell::ortho(3.0, 4.0, 5.0);
        let A = 2.0 * Matrix3::one();
        cell.scale_mut(A);

        assert_eq!(cell.a(), 6.0);
        assert_eq!(cell.b(), 8.0);
        assert_eq!(cell.c(), 10.0);
    }

    #[test]
    fn distances() {
        // Orthorombic unit cell
        let cell = UnitCell::ortho(3.0, 4.0, 5.0);
        let u = &Vector3D::new(0.0, 0.0, 0.0);
        let v = &Vector3D::new(1.0, 2.0, 6.0);
        assert_eq!(cell.distance(u, v), f64::sqrt(6.0));

        // Infinite unit cell
        let cell = UnitCell::new();
        assert_eq!(cell.distance(u, v), v.norm());

        // Triclinic unit cell
        let cell = UnitCell::triclinic(3.0, 4.0, 5.0, 90.0, 90.0, 90.0);
        assert_eq!(cell.distance(u, v), f64::sqrt(6.0));
    }
}
<commit_msg>Add unit test for wrap_vector<commit_after>/*
 * Cymbalum, Molecular Simulation in Rust
 * Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
*/
use std::f64::consts::PI;

use ::types::Vector3D;
use ::types::Matrix3;

/// The type of a cell determine how we will be able to compute the periodic
/// boundaries condition.
#[derive(Clone, Copy)]
pub enum CellType {
    /// Infinite unit cell, with no boundaries
    INFINITE,
    /// Orthorombic unit cell, with cuboide shape
    ORTHOROMBIC,
    /// Triclinic unit cell, with arbitrary parallelepipedic shape
    TRICLINIC,
}

/// The Universe type hold all the data about a system.
#[derive(Clone, Copy)]
pub struct UnitCell {
    data: Matrix3,
    celltype: CellType,
}

impl UnitCell {
    /// Create an infinite unit cell
    pub fn new() -> UnitCell {
        UnitCell{data: Matrix3::zero(), celltype: CellType::INFINITE}
    }
    /// Create an orthorombic unit cell
    pub fn ortho(a: f64, b: f64, c: f64) -> UnitCell {
        UnitCell{data: Matrix3::new(a, 0.0, 0.0,
                                    0.0, b, 0.0,
                                    0.0, 0.0, c),
                 celltype: CellType::ORTHOROMBIC}
    }
    /// Create a cubic unit cell
    pub fn cubic(L: f64) -> UnitCell {
        UnitCell{data: Matrix3::new(L, 0.0, 0.0,
                                    0.0, L, 0.0,
                                    0.0, 0.0, L),
                 celltype: CellType::ORTHOROMBIC}
    }
    /// Create a triclinic unit cell
    pub fn triclinic(a: f64, b: f64, c: f64, alpha: f64, beta: f64, gamma: f64) -> UnitCell {
        let cos_alpha = deg2rad(alpha).cos();
        let cos_beta = deg2rad(beta).cos();
        let (sin_gamma, cos_gamma) = deg2rad(gamma).sin_cos();

        let b_x = b * cos_gamma;
        let b_y = b * sin_gamma;

        let c_x = c * cos_beta;
        let c_y = c * (cos_alpha - cos_beta*cos_gamma)/sin_gamma;
        let c_z = f64::sqrt(c*c - c_y*c_y - c_x*c_x);

        UnitCell{data: Matrix3::new(a,   b_x, c_x,
                                    0.0, b_y, c_y,
                                    0.0, 0.0, c_z),
                 celltype: CellType::TRICLINIC}
    }

    /// Get the cell type
    pub fn celltype(&self) -> CellType {
        self.celltype
    }
    /// Set the cell type
    pub fn set_celltype(&mut self, ctype: CellType) {
        self.celltype = ctype;
    }

    /// Get the first vector of the cell
    pub fn vect_a(&self) -> Vector3D {
        let x = self.data[(0, 0)];
        let y = self.data[(1, 0)];
        let z = self.data[(2, 0)];
        Vector3D::new(x, y, z)
    }
    /// Get the first length of the cell
    pub fn a(&self) -> f64 {
        match self.celltype {
            CellType::TRICLINIC => self.vect_a().norm(),
            _ => self.data[(0, 0)],
        }
    }

    /// Get the second length of the cell
    pub fn vect_b(&self) -> Vector3D {
        let x = self.data[(0, 1)];
        let y = self.data[(1, 1)];
        let z = self.data[(2, 1)];
        Vector3D::new(x, y, z)
    }
    /// Get the second length of the cell
    pub fn b(&self) -> f64 {
        match self.celltype {
            CellType::TRICLINIC => self.vect_b().norm(),
            _ => self.data[(1, 1)],
        }
    }

    /// Get the third length of the cell
    pub fn vect_c(&self) -> Vector3D {
        let x = self.data[(0, 2)];
        let y = self.data[(1, 2)];
        let z = self.data[(2, 2)];
        Vector3D::new(x, y, z)
    }
    /// Get the second length of the cell
    pub fn c(&self) -> f64 {
        match self.celltype {
            CellType::TRICLINIC => self.vect_c().norm(),
            _ => self.data[(2, 2)],
        }
    }

    /// Get the first angle of the cell
    pub fn alpha(&self) -> f64 {
        match self.celltype {
            CellType::TRICLINIC => {
                let b = self.vect_b();
                let c = self.vect_c();
                rad2deg(angle(b, c))
            },
            _ => 90.0,
        }
    }

    /// Get the second angle of the cell
    pub fn beta(&self) -> f64 {
        match self.celltype {
            CellType::TRICLINIC => {
                let a = self.vect_a();
                let c = self.vect_c();
                rad2deg(angle(a, c))
            },
            _ => 90.0,
        }
    }

    /// Get the third angle of the cell
    pub fn gamma(&self) -> f64 {
        match self.celltype {
            CellType::TRICLINIC => {
                let a = self.vect_a();
                let b = self.vect_b();
                rad2deg(angle(a, b))
            },
            _ => 90.0,
        }
    }

    /// Get the volume angle of the cell
    pub fn volume(&self) -> f64 {
        match self.celltype {
            CellType::INFINITE => 0.0,
            CellType::ORTHOROMBIC => self.a()*self.b()*self.c(),
            CellType::TRICLINIC => {
                // The volume is the mixed product of the three cell vectors
                let a = self.vect_a();
                let b = self.vect_b();
                let c = self.vect_c();
                a * (b ^ c)
            },
        }
    }

    /// Scale this unit cell in-place by multiplying the H matrix by `s`.
    pub fn scale_mut(&mut self, s: Matrix3) {
        self.data = s * self.data;
    }

    /// Scale this unit cell by multiplying the H matrix by `s`, and return a new unit cell
    pub fn scale(&self, s: Matrix3) -> UnitCell {
        UnitCell{data: s * self.data, celltype: self.celltype}
    }

    /// Wrap a vector in the unit cell, obeying the periodic boundary conditions
    pub fn wrap_vector(&self, vect: &mut Vector3D) {
        match self.celltype {
            CellType::INFINITE => (),
            CellType::ORTHOROMBIC => {
                vect.x = vect.x - f64::round(vect.x/self.a())*self.a();
                vect.y = vect.y - f64::round(vect.y/self.b())*self.b();
                vect.z = vect.z - f64::round(vect.z/self.c())*self.c();
            },
            CellType::TRICLINIC => {
                let inv = self.data.inverse();
                let mut fractional = inv * (*vect);
                fractional.x = fractional.x - f64::round(fractional.x);
                fractional.y = fractional.y - f64::round(fractional.y);
                fractional.z = fractional.z - f64::round(fractional.z);
                let res = self.data * fractional;
                vect.x = res.x;
                vect.y = res.y;
                vect.z = res.z;
            },
        }
    }

    /// Periodic boundary conditions distance between the point `u` and the point `v`
    pub fn distance(&self, u: &Vector3D, v: &Vector3D) -> f64 {
        let mut d = *v - *u;
        self.wrap_vector(&mut d);
        return d.norm();
    }
}

/// Convert `x` from degrees to radians
fn deg2rad(x: f64) -> f64 {
    x * PI / 180.0
}
/// Convert `x` from radians to degrees
fn rad2deg(x: f64) -> f64 {
    x * 180.0 / PI
}

/// Get the angles between the vectors `u` and `v`.
fn angle(u: Vector3D, v: Vector3D) -> f64 {
    let un = u.normalized();
    let vn = v.normalized();
    f64::acos(un*vn)
}

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

    #[test]
    fn infinite() {
        let cell = UnitCell::new();
        assert_eq!(cell.a(), 0.0);
        assert_eq!(cell.b(), 0.0);
        assert_eq!(cell.c(), 0.0);

        assert_eq!(cell.alpha(), 90.0);
        assert_eq!(cell.beta(), 90.0);
        assert_eq!(cell.gamma(), 90.0);

        assert_eq!(cell.volume(), 0.0);
    }

    #[test]
    fn cubic() {
        let cell = UnitCell::cubic(3.0);
        assert_eq!(cell.a(), 3.0);
        assert_eq!(cell.b(), 3.0);
        assert_eq!(cell.c(), 3.0);

        assert_eq!(cell.alpha(), 90.0);
        assert_eq!(cell.beta(), 90.0);
        assert_eq!(cell.gamma(), 90.0);

        assert_eq!(cell.volume(), 3.0*3.0*3.0);
    }

    #[test]
    fn orthorombic() {
        let cell = UnitCell::ortho(3.0, 4.0, 5.0);
        assert_eq!(cell.a(), 3.0);
        assert_eq!(cell.b(), 4.0);
        assert_eq!(cell.c(), 5.0);

        assert_eq!(cell.alpha(), 90.0);
        assert_eq!(cell.beta(), 90.0);
        assert_eq!(cell.gamma(), 90.0);

        assert_eq!(cell.volume(), 3.0*4.0*5.0);
    }

    #[test]
    fn triclinic() {
        let cell = UnitCell::triclinic(3.0, 4.0, 5.0, 80.0, 90.0, 110.0);
        assert_eq!(cell.a(), 3.0);
        assert_eq!(cell.b(), 4.0);
        assert_eq!(cell.c(), 5.0);

        assert_eq!(cell.alpha(), 80.0);
        assert_eq!(cell.beta(), 90.0);
        assert_eq!(cell.gamma(), 110.0);

        assert_approx_eq!(cell.volume(), 55.410529, 1e-6);
    }

    #[test]
    fn scale() {
        let cell = UnitCell::ortho(3.0, 4.0, 5.0);
        let A = 2.0 * Matrix3::one();
        let cell = cell.scale(A);

        assert_eq!(cell.a(), 6.0);
        assert_eq!(cell.b(), 8.0);
        assert_eq!(cell.c(), 10.0);
    }

    #[test]
    fn scale_mut() {
        let mut cell = UnitCell::ortho(3.0, 4.0, 5.0);
        let A = 2.0 * Matrix3::one();
        cell.scale_mut(A);

        assert_eq!(cell.a(), 6.0);
        assert_eq!(cell.b(), 8.0);
        assert_eq!(cell.c(), 10.0);
    }

    #[test]
    fn distances() {
        // Orthorombic unit cell
        let cell = UnitCell::ortho(3.0, 4.0, 5.0);
        let u = &Vector3D::new(0.0, 0.0, 0.0);
        let v = &Vector3D::new(1.0, 2.0, 6.0);
        assert_eq!(cell.distance(u, v), f64::sqrt(6.0));

        // Infinite unit cell
        let cell = UnitCell::new();
        assert_eq!(cell.distance(u, v), v.norm());

        // Triclinic unit cell
        let cell = UnitCell::triclinic(3.0, 4.0, 5.0, 90.0, 90.0, 90.0);
        assert_eq!(cell.distance(u, v), f64::sqrt(6.0));
    }

    #[test]
    fn wrap_vector() {
        // Orthorombic unit cell
        let cell = UnitCell::ortho(3.0, 4.0, 5.0);
        let mut v = Vector3D::new(1.0, 1.5, 6.0);
        cell.wrap_vector(&mut v);
        assert_eq!(v, Vector3D::new(1.0, 1.5, 1.0));

        // Infinite unit cell
        let cell = UnitCell::new();
        let mut v = Vector3D::new(1.0, 1.5, 6.0);
        cell.wrap_vector(&mut v);
        assert_eq!(v, Vector3D::new(1.0, 1.5, 6.0));

        // Triclinic unit cell
        let cell = UnitCell::triclinic(3.0, 4.0, 5.0, 90.0, 90.0, 90.0);
        let mut v = Vector3D::new(1.0, 1.5, 6.0);
        cell.wrap_vector(&mut v);
        let res = Vector3D::new(1.0, 1.5, 1.0);
        assert_approx_eq!(v.x, res.x, 1e-15);
        assert_approx_eq!(v.y, res.y, 1e-15);
        assert_approx_eq!(v.z, res.z, 1e-15);
    }
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;

use c_ares;
use mio;
use mio_extras;

use error::Error;
use eventloop::EventLoopHandle;

// The EventLoop will set up a mio::Poll and use it to wait for the following:
//
// -  messages telling it which file descriptors it should be interested in.
//    These file descriptors are then registered (or deregistered) with the
//    mio::Poll as required.
//
// -  events telling it that something has happened on one of these file
//    descriptors.  When this happens, it tells the c_ares::Channel about it.
pub struct EventLoop {
    poll: mio::Poll,
    rx_msg_channel: mio_extras::channel::Receiver<Message>,
    tracked_fds: HashSet<c_ares::Socket>,
    pub ares_channel: Arc<Mutex<c_ares::Channel>>,
    quit: Arc<AtomicBool>,
}

// Messages for the event loop.
#[derive(Debug)]
pub enum Message {
    // 'Notify me when this file descriptor becomes readable, or writable'.
    // The first bool is for 'readable' and the second is for 'writable'.  It's
    // allowed to set both of these - or neither, meaning 'I am no longer
    // interested in this file descriptor'.
    RegisterInterest(c_ares::Socket, bool, bool),
}

// A token identifying that the message channel has become available for
// reading.
//
// We use Token(fd) for file descriptors, so this relies on zero not being a
// valid file descriptor for c-ares to use.  Zero is stdin, so that's true.
const CHANNEL: mio::Token = mio::Token(0);

impl EventLoop {
    // Create a new event loop.
    pub fn new(mut options: c_ares::Options) -> Result<EventLoop, Error> {
        // Create a mio::Poll on which to wait for events, and register a
        // channel with it.
        let poll = mio::Poll::new()?;
        let (tx, rx) = mio_extras::channel::channel();
        poll.register(&rx, CHANNEL, mio::Ready::readable(), mio::PollOpt::edge())?;

        // Whenever c-ares tells us what to do with a file descriptor, we'll
        // send that request along, through the channel we just created.
        let sock_callback = move |fd: c_ares::Socket, readable: bool, writable: bool| {
            let _ = tx.send(Message::RegisterInterest(fd, readable, writable));
        };
        options.set_socket_state_callback(sock_callback);

        // Create the c-ares channel.
        let ares_channel = c_ares::Channel::with_options(options)?;
        let locked_channel = Arc::new(Mutex::new(ares_channel));

        // Create and return the event loop.
        let event_loop = EventLoop {
            poll: poll,
            rx_msg_channel: rx,
            tracked_fds: HashSet::<c_ares::Socket>::new(),
            ares_channel: locked_channel,
            quit: Arc::new(AtomicBool::new(false)),
        };
        Ok(event_loop)
    }

    // Run the event loop.
    pub fn run(self) -> EventLoopHandle {
        let quit = Arc::clone(&self.quit);
        let join_handle = thread::spawn(|| self.event_loop_thread());
        EventLoopHandle::new(join_handle, quit)
    }

    // Event loop thread - waits for events, and handles them.
    fn event_loop_thread(mut self) {
        let mut events = mio::Events::with_capacity(16);
        loop {
            // Wait for something to happen.
            let timeout = Duration::from_millis(100);
            let results = self.poll
                .poll(&mut events, Some(timeout))
                .expect("poll failed");

            // Process whatever happened.
            match results {
                0 => {
                    // No events - must be a timeout.  Tell c-ares about it.
                    self.ares_channel
                        .lock()
                        .unwrap()
                        .process_fd(c_ares::SOCKET_BAD, c_ares::SOCKET_BAD);
                }
                _ => {
                    // Process events.
                    for event in &events {
                        self.handle_event(&event);
                    }
                }
            }
            if self.quit.load(Ordering::Relaxed) {
                break;
            }
        }
    }

    // Handle a single event.
    fn handle_event(&mut self, event: &mio::Event) {
        match event.token() {
            CHANNEL => {
                // The channel is readable.
                self.handle_messages()
            }

            mio::Token(fd) => {
                // Sockets became readable or writable - tell c-ares.
                let ready = mio::unix::UnixReady::from(event.readiness());
                let error = ready.is_error() || ready.is_hup();
                let rfd = if error || ready.is_readable() {
                    fd as c_ares::Socket
                } else {
                    c_ares::SOCKET_BAD
                };
                let wfd = if error || ready.is_writable() {
                    fd as c_ares::Socket
                } else {
                    c_ares::SOCKET_BAD
                };
                self.ares_channel.lock().unwrap().process_fd(rfd, wfd);
            }
        }
    }

    // Process messages incoming on the channel.
    fn handle_messages(&mut self) {
        while let Ok(Message::RegisterInterest(fd, readable, writable)) =
            self.rx_msg_channel.try_recv()
        {
            let efd = mio::unix::EventedFd(&fd);
            if !readable && !writable {
                self.tracked_fds.remove(&fd);
                let _ = self.poll.deregister(&efd);
            } else {
                let token = mio::Token(fd as usize);
                assert_ne!(token, CHANNEL);
                let mut interest =
                    mio::Ready::from(mio::unix::UnixReady::error() | mio::unix::UnixReady::hup());
                if readable {
                    interest.insert(mio::Ready::readable())
                }
                if writable {
                    interest.insert(mio::Ready::writable())
                }
                let register_result = if !self.tracked_fds.insert(fd) {
                    self.poll
                        .reregister(&efd, token, interest, mio::PollOpt::level())
                } else {
                    self.poll
                        .register(&efd, token, interest, mio::PollOpt::level())
                };
                register_result.expect("failed to register interest");
            }
        }
    }
}
<commit_msg>unnecessary type annotation<commit_after>use std::collections::HashSet;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;

use c_ares;
use mio;
use mio_extras;

use error::Error;
use eventloop::EventLoopHandle;

// The EventLoop will set up a mio::Poll and use it to wait for the following:
//
// -  messages telling it which file descriptors it should be interested in.
//    These file descriptors are then registered (or deregistered) with the
//    mio::Poll as required.
//
// -  events telling it that something has happened on one of these file
//    descriptors.  When this happens, it tells the c_ares::Channel about it.
pub struct EventLoop {
    poll: mio::Poll,
    rx_msg_channel: mio_extras::channel::Receiver<Message>,
    tracked_fds: HashSet<c_ares::Socket>,
    pub ares_channel: Arc<Mutex<c_ares::Channel>>,
    quit: Arc<AtomicBool>,
}

// Messages for the event loop.
#[derive(Debug)]
pub enum Message {
    // 'Notify me when this file descriptor becomes readable, or writable'.
    // The first bool is for 'readable' and the second is for 'writable'.  It's
    // allowed to set both of these - or neither, meaning 'I am no longer
    // interested in this file descriptor'.
    RegisterInterest(c_ares::Socket, bool, bool),
}

// A token identifying that the message channel has become available for
// reading.
//
// We use Token(fd) for file descriptors, so this relies on zero not being a
// valid file descriptor for c-ares to use.  Zero is stdin, so that's true.
const CHANNEL: mio::Token = mio::Token(0);

impl EventLoop {
    // Create a new event loop.
    pub fn new(mut options: c_ares::Options) -> Result<EventLoop, Error> {
        // Create a mio::Poll on which to wait for events, and register a
        // channel with it.
        let poll = mio::Poll::new()?;
        let (tx, rx) = mio_extras::channel::channel();
        poll.register(&rx, CHANNEL, mio::Ready::readable(), mio::PollOpt::edge())?;

        // Whenever c-ares tells us what to do with a file descriptor, we'll
        // send that request along, through the channel we just created.
        let sock_callback = move |fd: c_ares::Socket, readable: bool, writable: bool| {
            let _ = tx.send(Message::RegisterInterest(fd, readable, writable));
        };
        options.set_socket_state_callback(sock_callback);

        // Create the c-ares channel.
        let ares_channel = c_ares::Channel::with_options(options)?;
        let locked_channel = Arc::new(Mutex::new(ares_channel));

        // Create and return the event loop.
        let event_loop = EventLoop {
            poll: poll,
            rx_msg_channel: rx,
            tracked_fds: HashSet::new(),
            ares_channel: locked_channel,
            quit: Arc::new(AtomicBool::new(false)),
        };
        Ok(event_loop)
    }

    // Run the event loop.
    pub fn run(self) -> EventLoopHandle {
        let quit = Arc::clone(&self.quit);
        let join_handle = thread::spawn(|| self.event_loop_thread());
        EventLoopHandle::new(join_handle, quit)
    }

    // Event loop thread - waits for events, and handles them.
    fn event_loop_thread(mut self) {
        let mut events = mio::Events::with_capacity(16);
        loop {
            // Wait for something to happen.
            let timeout = Duration::from_millis(100);
            let results = self.poll
                .poll(&mut events, Some(timeout))
                .expect("poll failed");

            // Process whatever happened.
            match results {
                0 => {
                    // No events - must be a timeout.  Tell c-ares about it.
                    self.ares_channel
                        .lock()
                        .unwrap()
                        .process_fd(c_ares::SOCKET_BAD, c_ares::SOCKET_BAD);
                }
                _ => {
                    // Process events.
                    for event in &events {
                        self.handle_event(&event);
                    }
                }
            }
            if self.quit.load(Ordering::Relaxed) {
                break;
            }
        }
    }

    // Handle a single event.
    fn handle_event(&mut self, event: &mio::Event) {
        match event.token() {
            CHANNEL => {
                // The channel is readable.
                self.handle_messages()
            }

            mio::Token(fd) => {
                // Sockets became readable or writable - tell c-ares.
                let ready = mio::unix::UnixReady::from(event.readiness());
                let error = ready.is_error() || ready.is_hup();
                let rfd = if error || ready.is_readable() {
                    fd as c_ares::Socket
                } else {
                    c_ares::SOCKET_BAD
                };
                let wfd = if error || ready.is_writable() {
                    fd as c_ares::Socket
                } else {
                    c_ares::SOCKET_BAD
                };
                self.ares_channel.lock().unwrap().process_fd(rfd, wfd);
            }
        }
    }

    // Process messages incoming on the channel.
    fn handle_messages(&mut self) {
        while let Ok(Message::RegisterInterest(fd, readable, writable)) =
            self.rx_msg_channel.try_recv()
        {
            let efd = mio::unix::EventedFd(&fd);
            if !readable && !writable {
                self.tracked_fds.remove(&fd);
                let _ = self.poll.deregister(&efd);
            } else {
                let token = mio::Token(fd as usize);
                assert_ne!(token, CHANNEL);
                let mut interest =
                    mio::Ready::from(mio::unix::UnixReady::error() | mio::unix::UnixReady::hup());
                if readable {
                    interest.insert(mio::Ready::readable())
                }
                if writable {
                    interest.insert(mio::Ready::writable())
                }
                let register_result = if !self.tracked_fds.insert(fd) {
                    self.poll
                        .reregister(&efd, token, interest, mio::PollOpt::level())
                } else {
                    self.poll
                        .register(&efd, token, interest, mio::PollOpt::level())
                };
                register_result.expect("failed to register interest");
            }
        }
    }
}
<|endoftext|>


<commit_before>#![allow(unused, missing_docs)]

use std::fmt;
use std::iter::repeat;
use elements::{BlockType, External, FunctionType, GlobalEntry, GlobalType, MemoryType, Module,
               Opcode, ResizableLimits, TableType, Type, ValueType};
use common::stack;
use self::context::ModuleContext;
use self::func::{FunctionValidationContext, Validator};

pub use self::module::ValidatedModule;

mod context;
mod module;
mod func;

#[cfg(test)]
mod tests;

pub struct Error(String);

impl fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "{}", self.0)
	}
}

impl From<stack::Error> for Error {
	fn from(e: stack::Error) -> Error {
		Error(format!("Stack: {}", e))
	}
}

pub fn validate_module(module: &Module) -> Result<ValidatedModule, Error> {
	let context = prepare_context(module)?;

	let function_section_len = module
		.function_section()
		.map(|s| s.entries().len())
		.unwrap_or(0);
	let code_section_len = module.code_section().map(|s| s.bodies().len()).unwrap_or(0);
	if function_section_len != code_section_len {
		return Err(Error(format!(
			"length of function section is {}, while len of code section is {}",
			function_section_len,
			code_section_len
		)));
	}

	// validate every function body in user modules
	if function_section_len != 0 {
		// tests use invalid code
		let function_section = module
			.function_section()
			.expect("function_section_len != 0; qed");
		let code_section = module
			.code_section()
			.expect("function_section_len != 0; function_section_len == code_section_len; qed");
		// check every function body
		for (index, function) in function_section.entries().iter().enumerate() {
			let function_labels = {
				let function_body = code_section
					.bodies()
					.get(index as usize)
					.ok_or(Error(format!("Missing body for function {}", index)))?;
				Validator::validate_function(&context, function, function_body).map_err(|e| {
					let Error(ref msg) = e;
					Error(format!("Function #{} validation error: {}", index, msg))
				})?;

				// TODO: pepyakin
				// context.function_labels()
			};

			// TODO: pepyakin
			// self.functions_labels.insert(index as u32, function_labels);
		}
	}

	// validate start section
	if let Some(start_function) = module.start_section() {
		let (params, return_ty) = context.require_function(start_function)?;
		if return_ty != BlockType::NoResult || params.len() != 0 {
			return Err(Error("start function expected to have type [] -> []".into()));
		}
	}

	let ModuleContext {
		types,
		tables,
		memories,
		globals,
		func_type_indexes,
	} = context;

	Ok(ValidatedModule {
		types,
		tables,
		memories,
		globals,
		func_type_indexes,
	})
}

fn prepare_context(module: &Module) -> Result<ModuleContext, Error> {
	// TODO: Validate imports
	// TODO: Validate exports

	// Copy types from module as is.
	let types = module
		.type_section()
		.map(|ts| ts.types().into_iter().cloned().collect())
		.unwrap_or_default();

	// Fill elements with imported values.

	// TODO: Use Func::type_ref?
	let mut func_type_indexes = Vec::new();
	let mut tables = Vec::new();
	let mut memories = Vec::new();
	let mut globals = Vec::new();

	for import_entry in module
		.import_section()
		.map(|i| i.entries())
		.unwrap_or_default()
	{
		match import_entry.external() {
			&External::Function(idx) => func_type_indexes.push(idx),
			&External::Table(ref table) => tables.push(table.clone()),
			&External::Memory(ref memory) => memories.push(memory.clone()),
			&External::Global(ref global) => globals.push(global.clone()),
		}
	}

	// Concatenate elements with defined in the module.
	if let Some(function_section) = module.function_section() {
		for func_entry in function_section.entries() {
			func_type_indexes.push(func_entry.type_ref());
		}
	}
	if let Some(table_section) = module.table_section() {
		for table_entry in table_section.entries() {
			table_entry.validate()?;
			tables.push(table_entry.clone());
		}
	}
	if let Some(mem_section) = module.memory_section() {
		for mem_entry in mem_section.entries() {
			mem_entry.validate()?;
			memories.push(mem_entry.clone());
		}
	}
	if let Some(global_section) = module.global_section() {
		// Validation of globals is defined over modified context C', which
		// contains only imported globals. So we do globals validation
		// in two passes, in first we validate globals and after all globals are validated
		// add them in globals list.
		for global_entry in global_section.entries() {
			global_entry.validate(&globals)?;
		}

		for global_entry in global_section.entries() {
			globals.push(global_entry.global_type().clone());
		}
	}

	Ok(ModuleContext {
		types,
		tables,
		memories,
		globals,
		func_type_indexes,
	})
}

impl ResizableLimits {
	fn validate(&self) -> Result<(), Error> {
		if let Some(maximum) = self.maximum() {
			if self.initial() > maximum {
				return Err(Error(format!(
					"maximum limit {} is lesser than minimum {}",
					maximum,
					self.initial()
				)));
			}
		}
		Ok(())
	}
}

impl MemoryType {
	fn validate(&self) -> Result<(), Error> {
		self.limits().validate()
	}
}

impl TableType {
	fn validate(&self) -> Result<(), Error> {
		self.limits().validate()
	}
}

impl GlobalEntry {
	fn validate(&self, globals_sofar: &[GlobalType]) -> Result<(), Error> {
		let init = self.init_expr().code();
		if init.len() != 2 {
			return Err(Error(
				format!("Init expression should always be with length 2"),
			));
		}
		let init_expr_ty: ValueType = match init[0] {
			Opcode::I32Const(_) => ValueType::I32,
			Opcode::I64Const(_) => ValueType::I64,
			Opcode::F32Const(_) => ValueType::F32,
			Opcode::F64Const(_) => ValueType::F64,
			Opcode::GetGlobal(idx) => match globals_sofar.get(idx as usize) {
				Some(target_global) => {
					if target_global.is_mutable() {
						return Err(Error(format!("Global {} is mutable", idx)));
					}
					target_global.content_type()
				}
				None => {
					return Err(Error(
						format!("Global {} doesn't exists or not yet defined", idx),
					))
				}
			},
			_ => return Err(Error(format!("Non constant opcode in init expr"))),
		};
		if init_expr_ty != self.global_type().content_type() {
			return Err(Error(format!(
				"Trying to initialize variable of type {:?} with value of type {:?}",
				self.global_type().content_type(),
				init_expr_ty
			)));
		}
		if init[1] != Opcode::End {
			return Err(Error(format!("Expression doesn't ends with `end` opcode")));
		}
		Ok(())
	}
}
<commit_msg>Clean<commit_after>#![allow(unused, missing_docs)]

use std::fmt;
use std::iter::repeat;
use elements::{BlockType, External, FunctionType, GlobalEntry, GlobalType, MemoryType, Module,
               Opcode, ResizableLimits, TableType, Type, ValueType};
use common::stack;
use self::context::ModuleContext;
use self::func::{FunctionValidationContext, Validator};

pub use self::module::ValidatedModule;

mod context;
mod module;
mod func;

#[cfg(test)]
mod tests;

pub struct Error(String);

impl fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "{}", self.0)
	}
}

impl From<stack::Error> for Error {
	fn from(e: stack::Error) -> Error {
		Error(format!("Stack: {}", e))
	}
}

pub fn validate_module(module: &Module) -> Result<ValidatedModule, Error> {
	let context = prepare_context(module)?;

	let function_section_len = module
		.function_section()
		.map(|s| s.entries().len())
		.unwrap_or(0);
	let code_section_len = module.code_section().map(|s| s.bodies().len()).unwrap_or(0);
	if function_section_len != code_section_len {
		return Err(Error(format!(
			"length of function section is {}, while len of code section is {}",
			function_section_len,
			code_section_len
		)));
	}

	// validate every function body in user modules
	if function_section_len != 0 {
		// tests use invalid code
		let function_section = module
			.function_section()
			.expect("function_section_len != 0; qed");
		let code_section = module
			.code_section()
			.expect("function_section_len != 0; function_section_len == code_section_len; qed");
		// check every function body
		for (index, function) in function_section.entries().iter().enumerate() {
			let function_body = code_section
				.bodies()
				.get(index as usize)
				.ok_or(Error(format!("Missing body for function {}", index)))?;
			Validator::validate_function(&context, function, function_body).map_err(|e| {
				let Error(ref msg) = e;
				Error(format!("Function #{} validation error: {}", index, msg))
			})?;
		}
	}

	// validate start section
	if let Some(start_function) = module.start_section() {
		let (params, return_ty) = context.require_function(start_function)?;
		if return_ty != BlockType::NoResult || params.len() != 0 {
			return Err(Error("start function expected to have type [] -> []".into()));
		}
	}

	let ModuleContext {
		types,
		tables,
		memories,
		globals,
		func_type_indexes,
	} = context;

	Ok(ValidatedModule {
		types,
		tables,
		memories,
		globals,
		func_type_indexes,
	})
}

fn prepare_context(module: &Module) -> Result<ModuleContext, Error> {
	// TODO: Validate imports
	// TODO: Validate exports

	// Copy types from module as is.
	let types = module
		.type_section()
		.map(|ts| ts.types().into_iter().cloned().collect())
		.unwrap_or_default();

	// Fill elements with imported values.

	// TODO: Use Func::type_ref?
	let mut func_type_indexes = Vec::new();
	let mut tables = Vec::new();
	let mut memories = Vec::new();
	let mut globals = Vec::new();

	for import_entry in module
		.import_section()
		.map(|i| i.entries())
		.unwrap_or_default()
	{
		match import_entry.external() {
			&External::Function(idx) => func_type_indexes.push(idx),
			&External::Table(ref table) => tables.push(table.clone()),
			&External::Memory(ref memory) => memories.push(memory.clone()),
			&External::Global(ref global) => globals.push(global.clone()),
		}
	}

	// Concatenate elements with defined in the module.
	if let Some(function_section) = module.function_section() {
		for func_entry in function_section.entries() {
			func_type_indexes.push(func_entry.type_ref());
		}
	}
	if let Some(table_section) = module.table_section() {
		for table_entry in table_section.entries() {
			table_entry.validate()?;
			tables.push(table_entry.clone());
		}
	}
	if let Some(mem_section) = module.memory_section() {
		for mem_entry in mem_section.entries() {
			mem_entry.validate()?;
			memories.push(mem_entry.clone());
		}
	}
	if let Some(global_section) = module.global_section() {
		// Validation of globals is defined over modified context C', which
		// contains only imported globals. So we do globals validation
		// in two passes, in first we validate globals and after all globals are validated
		// add them in globals list.
		for global_entry in global_section.entries() {
			global_entry.validate(&globals)?;
		}

		for global_entry in global_section.entries() {
			globals.push(global_entry.global_type().clone());
		}
	}

	Ok(ModuleContext {
		types,
		tables,
		memories,
		globals,
		func_type_indexes,
	})
}

impl ResizableLimits {
	fn validate(&self) -> Result<(), Error> {
		if let Some(maximum) = self.maximum() {
			if self.initial() > maximum {
				return Err(Error(format!(
					"maximum limit {} is lesser than minimum {}",
					maximum,
					self.initial()
				)));
			}
		}
		Ok(())
	}
}

impl MemoryType {
	fn validate(&self) -> Result<(), Error> {
		self.limits().validate()
	}
}

impl TableType {
	fn validate(&self) -> Result<(), Error> {
		self.limits().validate()
	}
}

impl GlobalEntry {
	fn validate(&self, globals_sofar: &[GlobalType]) -> Result<(), Error> {
		let init = self.init_expr().code();
		if init.len() != 2 {
			return Err(Error(
				format!("Init expression should always be with length 2"),
			));
		}
		let init_expr_ty: ValueType = match init[0] {
			Opcode::I32Const(_) => ValueType::I32,
			Opcode::I64Const(_) => ValueType::I64,
			Opcode::F32Const(_) => ValueType::F32,
			Opcode::F64Const(_) => ValueType::F64,
			Opcode::GetGlobal(idx) => match globals_sofar.get(idx as usize) {
				Some(target_global) => {
					if target_global.is_mutable() {
						return Err(Error(format!("Global {} is mutable", idx)));
					}
					target_global.content_type()
				}
				None => {
					return Err(Error(
						format!("Global {} doesn't exists or not yet defined", idx),
					))
				}
			},
			_ => return Err(Error(format!("Non constant opcode in init expr"))),
		};
		if init_expr_ty != self.global_type().content_type() {
			return Err(Error(format!(
				"Trying to initialize variable of type {:?} with value of type {:?}",
				self.global_type().content_type(),
				init_expr_ty
			)));
		}
		if init[1] != Opcode::End {
			return Err(Error(format!("Expression doesn't ends with `end` opcode")));
		}
		Ok(())
	}
}
<|endoftext|>