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

// Many of my decisions were based off the following document
// https://web.archive.org/web/20140727185616/http://algs4.cs.princeton.edu/33balanced/

#![feature(box_syntax)]

use Direction::{Left, Middle, Right, Leaf};
use InsertResult::{Fit, Split};

/// SplitNode
enum SplitNode<V: Ord> {
    Four(V, V, V, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>),
    LeafFour(V, V, V),
}

impl <V: Ord> SplitNode<V> {
    fn to_two(self) -> Two<V> {
        match self {
            SplitNode::LeafFour(v1, v2, v3) =>
                Two(v2,
                    box Node::LeafTwo(LeafTwo(v1)),
                    box Node::LeafTwo(LeafTwo(v3))),
            SplitNode::Four(v1, v2, v3, n1, n2, n3, n4) =>
                Two(v2,
                    box Node::Two(Two(v1, n1, n2)),
                    box Node::Two(Two(v3, n3, n4))),
        }
    }
}

/// InsertResult
enum InsertResult<V: Ord> {
    Fit(Node<V>),
    Split(SplitNode<V>),
}

/// Direction
enum Direction {
    Left,
    Middle,
    Right,
    Leaf,
}

/// Two
pub struct Two<V: Ord>(pub V, pub Box<Node<V>>, pub Box<Node<V>>);

impl <V: Ord> Two<V> {
    fn as_node(self) -> Node<V> { Node::Two(self) }

    fn to_three(self, other_value: V, other_node: Box<Node<V>>) -> Three<V> {
        let Two(self_value, self_left, self_middle) = self;
        if self_value > other_value {
            Three(other_value, self_value, other_node, self_left, self_middle)
        } else {
            Three(self_value, other_value, self_left, self_middle, other_node)
        }
    }

    fn has_value(&self, value: &V) -> bool {
        let &Two(ref self_value, _, _) = self;
        *self_value == *value
    }
}

/// Three
pub struct Three<V: Ord>(pub V, pub V, pub Box<Node<V>>, pub Box<Node<V>>, pub Box<Node<V>>);

impl <V: Ord> Three<V> {
    fn as_node(self) -> Node<V> { Node::Three(self) }

    fn to_split_node(self, other_value: V, other_node: Box<Node<V>>) -> SplitNode<V> {
        let Three(self_value1, self_value2, self_left, self_middle, self_right) = self;
        if other_value < self_value1 {
            SplitNode::Four(other_value, self_value1, self_value2, other_node, self_left, self_middle, self_right)
        } else {
            SplitNode::Four(self_value1, self_value2, other_value, self_left, self_middle, self_right, other_node)
        }
    }

    fn has_value(&self, value: &V) -> bool {
        let Three(ref self_value1, ref self_value2, _, _, _) = *self;
        *self_value1 == *value || *self_value2 == *value
    }
}

/// LeafTwo
pub struct LeafTwo<V: Ord>(pub V);

impl <V: Ord> LeafTwo<V> {
    fn to_three(self, other_value: V) -> LeafThree<V> {
        let LeafTwo(self_value) = self;
        if self_value > other_value {
            LeafThree(other_value, self_value)
        } else {
            LeafThree(self_value, other_value)
        }
    }

    fn has_value(&self, value: &V) -> bool {
        let &LeafTwo(ref self_value) = self;
        *self_value == *value
    }
}

/// LeafThree
pub struct LeafThree<V: Ord>(pub V, pub V);

impl <V: Ord> LeafThree<V> {
    fn as_node(self) -> Node<V> { Node::LeafThree(self) }

    fn to_split_node(self, value: V) -> SplitNode<V> {
        let LeafThree(value1, value2) = self;
        if value > value2      { SplitNode::LeafFour(value1, value2, value) }
        else if value < value1 { SplitNode::LeafFour(value, value1, value2) }
        else                   { SplitNode::LeafFour(value1, value, value2) }
    }

    fn has_value(&self, value: &V) -> bool {
        let &LeafThree(ref self_value1, ref self_value2) = self;
        *self_value1 == *value || *self_value2 == *value
    }
}

/// Node
pub enum Node<V: Ord> {
    LeafTwo(LeafTwo<V>),
    LeafThree(LeafThree<V>),
    Two(Two<V>),
    Three(Three<V>),
}

impl <V: Ord> Node<V> {
    fn next_direction(&self, to_insert: &V) -> Direction {
        match *self {
            Node::Two(Two(ref value, _, _)) =>
                if to_insert < value { Left }
                else                 { Middle },
            Node::Three(Three(ref value1, ref value2, _, _, _)) =>
                if      to_insert < value1 { Left }
                else if to_insert > value2 { Right }
                else                       { Middle },
            _ => Leaf,
        }
    }

    fn has_value(&self, value: &V) -> bool {
        match *self {
            Node::LeafTwo(ref n)   => n.has_value(value),
            Node::LeafThree(ref n) => n.has_value(value),
            Node::Two(ref n)       => n.has_value(value),
            Node::Three(ref n)     => n.has_value(value),
        }
    }

    fn insert(self, to_insert: V) -> InsertResult<V> {
        // If value is already in this node, we're done (prevent duplicates)
        if self.has_value(&to_insert) { return Fit(self); }

        let next_direction = self.next_direction(&to_insert);

        match self {
            // Insert if leaf TwoNode
            Node::LeafTwo(leaf_two) => {
                let three_node = leaf_two.to_three(to_insert);
                Fit(three_node.as_node())
            },

            // Split if leaf ThreeNode
            Node::LeafThree(leaf_three) => {
                let split_node = leaf_three.to_split_node(to_insert);
                Split(split_node)
            },

            // Recurse down if internal Node and handle results
            Node::Two(Two(value, box left, box middle)) => {

                // Determine which node we'll recurse next
                let (next_node, other_node) = match next_direction {
                    Left => (left, middle),
                    Middle => (middle, left),
                    _ => unreachable!(),
                };

                // Recurse, save the result of the insert
                let insert_result = next_node.insert(to_insert);

                // Handle the result of the insert
                let new_node = match insert_result {
                    Fit(returned_node) =>
                        match next_direction {
                            Left =>   Two(value, box returned_node, box other_node),
                            Middle => Two(value, box other_node, box returned_node),
                            _ => unreachable!(),
                        }.as_node(),
                    Split(split_node) => split_node.to_two().to_three(value, box other_node).as_node(),
                };

                Fit(new_node)
            },

            // Recurse down if internal Node and handle results
            Node::Three(Three(value1, value2, left, middle, right)) => {

                // Determine which node we'll recurse next
                let (next_node, other_node1, other_node2) = match next_direction {
                    Left => (left, middle, right),
                    Middle => (middle, left, right),
                    Right => (right, left, middle),
                    _ => unreachable!(),
                };

                let insert_result = next_node.insert(to_insert);

                match insert_result {
                    Fit(returned_node) => {
                        let three = match next_direction {
                            Left =>   Three(value1, value2, box returned_node, other_node1, other_node2),
                            Middle => Three(value1, value2, other_node1, box returned_node, other_node2),
                            Right =>  Three(value1, value2, other_node1, other_node2, box returned_node),
                            _ => unreachable!(),
                        };
                        Fit(three.as_node())
                    },
                    Split(split_node) => {
                        let two = split_node.to_two();
                        let new_node = match next_direction {
                            Left =>   two.to_three(value1, other_node1).to_split_node(value2, other_node2),
                            Middle => two.to_three(value1, other_node1).to_split_node(value2, other_node2),
                            Right =>  two.to_three(value2, other_node2).to_split_node(value1, other_node1),
                            _ => unreachable!(),
                        };
                        Split(new_node)
                    }
                }
            }
        }
    }
}

/// TTTree
pub struct TTTree<V: Ord> {
    pub root: Option<Node<V>>,
}

impl <V: Ord> TTTree<V> {
    pub fn new() -> TTTree<V> {
        TTTree { root: None }
    }

    pub fn insert(&mut self, value: V) -> () {
        let root: Option<Node<V>> = self.root.take();
        let new_root: Node<V> = match root {
            None => Node::LeafTwo(LeafTwo(value)),
            Some(root) => {
                let result = root.insert(value);
                match result {
                    Fit(node) => node,
                    Split(split_node) => split_node.to_two().as_node(),
                }
            }
        };
        self.root = Some(new_root);
    }
}
<commit_msg>Update source to not use box syntax<commit_after>//  Copyright 2014-2015 Corey Farwell
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//  	http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

// Many of my decisions were based off the following document
// https://web.archive.org/web/20140727185616/http://algs4.cs.princeton.edu/33balanced/

use Direction::{Left, Middle, Right, Leaf};
use InsertResult::{Fit, Split};

/// SplitNode
enum SplitNode<V: Ord> {
    Four(V, V, V, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>),
    LeafFour(V, V, V),
}

impl <V: Ord> SplitNode<V> {
    fn to_two(self) -> Two<V> {
        match self {
            SplitNode::LeafFour(v1, v2, v3) =>
                Two(v2,
                    Box::new(Node::LeafTwo(LeafTwo(v1))),
                    Box::new(Node::LeafTwo(LeafTwo(v3)))),
            SplitNode::Four(v1, v2, v3, n1, n2, n3, n4) =>
                Two(v2,
                    Box::new(Node::Two(Two(v1, n1, n2))),
                    Box::new(Node::Two(Two(v3, n3, n4)))),
        }
    }
}

/// InsertResult
enum InsertResult<V: Ord> {
    Fit(Node<V>),
    Split(SplitNode<V>),
}

/// Direction
enum Direction {
    Left,
    Middle,
    Right,
    Leaf,
}

/// Two
pub struct Two<V: Ord>(pub V, pub Box<Node<V>>, pub Box<Node<V>>);

impl <V: Ord> Two<V> {
    fn as_node(self) -> Node<V> { Node::Two(self) }

    fn to_three(self, other_value: V, other_node: Box<Node<V>>) -> Three<V> {
        let Two(self_value, self_left, self_middle) = self;
        if self_value > other_value {
            Three(other_value, self_value, other_node, self_left, self_middle)
        } else {
            Three(self_value, other_value, self_left, self_middle, other_node)
        }
    }

    fn has_value(&self, value: &V) -> bool {
        let &Two(ref self_value, _, _) = self;
        *self_value == *value
    }
}

/// Three
pub struct Three<V: Ord>(pub V, pub V, pub Box<Node<V>>, pub Box<Node<V>>, pub Box<Node<V>>);

impl <V: Ord> Three<V> {
    fn as_node(self) -> Node<V> { Node::Three(self) }

    fn to_split_node(self, other_value: V, other_node: Box<Node<V>>) -> SplitNode<V> {
        let Three(self_value1, self_value2, self_left, self_middle, self_right) = self;
        if other_value < self_value1 {
            SplitNode::Four(other_value, self_value1, self_value2, other_node, self_left, self_middle, self_right)
        } else {
            SplitNode::Four(self_value1, self_value2, other_value, self_left, self_middle, self_right, other_node)
        }
    }

    fn has_value(&self, value: &V) -> bool {
        let Three(ref self_value1, ref self_value2, _, _, _) = *self;
        *self_value1 == *value || *self_value2 == *value
    }
}

/// LeafTwo
pub struct LeafTwo<V: Ord>(pub V);

impl <V: Ord> LeafTwo<V> {
    fn to_three(self, other_value: V) -> LeafThree<V> {
        let LeafTwo(self_value) = self;
        if self_value > other_value {
            LeafThree(other_value, self_value)
        } else {
            LeafThree(self_value, other_value)
        }
    }

    fn has_value(&self, value: &V) -> bool {
        let &LeafTwo(ref self_value) = self;
        *self_value == *value
    }
}

/// LeafThree
pub struct LeafThree<V: Ord>(pub V, pub V);

impl <V: Ord> LeafThree<V> {
    fn as_node(self) -> Node<V> { Node::LeafThree(self) }

    fn to_split_node(self, value: V) -> SplitNode<V> {
        let LeafThree(value1, value2) = self;
        if value > value2      { SplitNode::LeafFour(value1, value2, value) }
        else if value < value1 { SplitNode::LeafFour(value, value1, value2) }
        else                   { SplitNode::LeafFour(value1, value, value2) }
    }

    fn has_value(&self, value: &V) -> bool {
        let &LeafThree(ref self_value1, ref self_value2) = self;
        *self_value1 == *value || *self_value2 == *value
    }
}

/// Node
pub enum Node<V: Ord> {
    LeafTwo(LeafTwo<V>),
    LeafThree(LeafThree<V>),
    Two(Two<V>),
    Three(Three<V>),
}

impl <V: Ord> Node<V> {
    fn next_direction(&self, to_insert: &V) -> Direction {
        match *self {
            Node::Two(Two(ref value, _, _)) =>
                if to_insert < value { Left }
                else                 { Middle },
            Node::Three(Three(ref value1, ref value2, _, _, _)) =>
                if      to_insert < value1 { Left }
                else if to_insert > value2 { Right }
                else                       { Middle },
            _ => Leaf,
        }
    }

    fn has_value(&self, value: &V) -> bool {
        match *self {
            Node::LeafTwo(ref n)   => n.has_value(value),
            Node::LeafThree(ref n) => n.has_value(value),
            Node::Two(ref n)       => n.has_value(value),
            Node::Three(ref n)     => n.has_value(value),
        }
    }

    fn insert(self, to_insert: V) -> InsertResult<V> {
        // If value is already in this node, we're done (prevent duplicates)
        if self.has_value(&to_insert) { return Fit(self); }

        let next_direction = self.next_direction(&to_insert);

        match self {
            // Insert if leaf TwoNode
            Node::LeafTwo(leaf_two) => {
                let three_node = leaf_two.to_three(to_insert);
                Fit(three_node.as_node())
            },

            // Split if leaf ThreeNode
            Node::LeafThree(leaf_three) => {
                let split_node = leaf_three.to_split_node(to_insert);
                Split(split_node)
            },

            // Recurse down if internal Node and handle results
            Node::Two(Two(value, left, middle)) => {

                // Determine which node we'll recurse next
                let (next_node, other_node) = match next_direction {
                    Left => (left, middle),
                    Middle => (middle, left),
                    _ => unreachable!(),
                };

                // Recurse, save the result of the insert
                let insert_result = next_node.insert(to_insert);

                // Handle the result of the insert
                let new_node = match insert_result {
                    Fit(returned_node) =>
                        match next_direction {
                            Left =>   Two(value, Box::new(returned_node), other_node),
                            Middle => Two(value, other_node, Box::new(returned_node)),
                            _ => unreachable!(),
                        }.as_node(),
                    Split(split_node) => split_node.to_two().to_three(value, other_node).as_node(),
                };

                Fit(new_node)
            },

            // Recurse down if internal Node and handle results
            Node::Three(Three(value1, value2, left, middle, right)) => {

                // Determine which node we'll recurse next
                let (next_node, other_node1, other_node2) = match next_direction {
                    Left => (left, middle, right),
                    Middle => (middle, left, right),
                    Right => (right, left, middle),
                    _ => unreachable!(),
                };

                let insert_result = next_node.insert(to_insert);

                match insert_result {
                    Fit(returned_node) => {
                        let three = match next_direction {
                            Left =>   Three(value1, value2, Box::new(returned_node), other_node1, other_node2),
                            Middle => Three(value1, value2, other_node1, Box::new(returned_node), other_node2),
                            Right =>  Three(value1, value2, other_node1, other_node2, Box::new(returned_node)),
                            _ => unreachable!(),
                        };
                        Fit(three.as_node())
                    },
                    Split(split_node) => {
                        let two = split_node.to_two();
                        let new_node = match next_direction {
                            Left =>   two.to_three(value1, other_node1).to_split_node(value2, other_node2),
                            Middle => two.to_three(value1, other_node1).to_split_node(value2, other_node2),
                            Right =>  two.to_three(value2, other_node2).to_split_node(value1, other_node1),
                            _ => unreachable!(),
                        };
                        Split(new_node)
                    }
                }
            }
        }
    }
}

/// TTTree
pub struct TTTree<V: Ord> {
    pub root: Option<Node<V>>,
}

impl <V: Ord> TTTree<V> {
    pub fn new() -> TTTree<V> {
        TTTree { root: None }
    }

    pub fn insert(&mut self, value: V) -> () {
        let root: Option<Node<V>> = self.root.take();
        let new_root: Node<V> = match root {
            None => Node::LeafTwo(LeafTwo(value)),
            Some(root) => {
                let result = root.insert(value);
                match result {
                    Fit(node) => node,
                    Split(split_node) => split_node.to_two().as_node(),
                }
            }
        };
        self.root = Some(new_root);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate helix;
extern crate csv;

use std::error::Error;
use std::io::Read;
use helix::sys;
use helix::sys::{VALUE};
use helix::{FromRuby, CheckResult, ToRuby};

fn generate_lines(rows: &[Vec<String>]) -> Result<String, Box<Error>> {
    let mut wtr = csv::WriterBuilder::new().from_writer(vec![]);
    for row in rows {
        wtr.write_record(row)?;
    }

    Ok(String::from_utf8(wtr.into_inner()?)?)
}

fn record_to_ruby(record: &csv::ByteRecord) -> VALUE {
    let inner_array = unsafe { sys::rb_ary_new_capa(record.len() as isize) };
    for column in record.iter() {
        unsafe {
            let column_value =
                sys::rb_utf8_str_new(column.as_ptr() as *const i8, column.len() as i64);
            sys::rb_ary_push(inner_array, column_value);
        }
    }
    inner_array
}

struct Enumerator {
    value: VALUE,
}

impl FromRuby for Enumerator {
    type Checked = Enumerator;

    fn from_ruby(value: VALUE) -> CheckResult<Enumerator> {
        // TODO: validate this?
        Ok(Enumerator { value })
    }

    fn from_checked(checked: Enumerator) -> Enumerator {
        checked
    }
}

struct EnumeratorRead {
    value: VALUE,
    next: Option<Vec<u8>>,
}

impl EnumeratorRead {
    fn new(value: VALUE) -> EnumeratorRead {
        EnumeratorRead {
            value,
            next: None,
        }
    }

    fn read_and_store_overflow(&mut self, buf: &mut [u8], value: &[u8]) -> std::io::Result<usize> {
        if value.len() > buf.len() {
            match value.split_at(buf.len()) {
                (current, next) => {
                    for (index, c) in current.iter().enumerate() {
                        buf[index] = *c;
                    }
                    self.next = Some(next.to_vec());
                    Ok(current.len())
                }
            }

        } else {
            for (index, value) in value.iter().enumerate() {
                buf[index] = *value;
            }
            self.next = None;
            Ok(value.len() as usize)
        }
    }

    fn read_from_external(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        let next = unsafe {
            sys::rb_funcall(
                self.value,
                sys::rb_intern("next\0".as_ptr() as *const i8),
                0,
            )
        };

        let string = String::from_ruby_unwrap(next);

        self.read_and_store_overflow(buf, string.as_bytes())
    }
}

impl Read for EnumeratorRead {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        match self.next.take() {
            Some(ref inner) => self.read_and_store_overflow(buf, inner),
            None => self.read_from_external(buf),
        }
    }
}

fn csv_reader<R: Read>(reader: R) -> csv::Reader<R> {
    csv::ReaderBuilder::new()
        .buffer_capacity(16 * 1024)
        .has_headers(false)
        .from_reader(reader)
}

fn yield_csv(data: &Enumerator) -> Result<(), csv::Error> {
    let mut reader = csv_reader(EnumeratorRead::new(data.value));
    let mut record = csv::ByteRecord::new();

    while reader.read_byte_record(&mut record)? {
        let inner_array = record_to_ruby(&record);
        unsafe {
            sys::rb_yield(inner_array);
        }
    }

    Ok(())
}

fn parse_csv(data: &str) -> Result<Vec<Vec<VALUE>>, csv::Error> {
    csv_reader(data.as_bytes())
        .records()
        .map(|r| r.map(|v| record_to_vec(&v)))
        .collect()
}

fn record_to_vec(record: &csv::StringRecord) -> Vec<VALUE> {
    record.iter().map(|s| s.to_ruby().unwrap()).collect()
}

ruby! {
    class RscsvReader {
        def each_internal(data: Enumerator) -> Result<(), &'static str> {
            yield_csv(&data).map_err(|_| "Error parsing CSV")
        }

        def parse(data: String) -> Result<Vec<Vec<VALUE>>, &'static str> {
            parse_csv(&data).map_err(|_| "Error parsing CSV")
        }
    }

    class RscsvWriter {
        def generate_line(row: Vec<String>) -> Result<String, &'static str> {
            let mut wtr = csv::WriterBuilder::new().from_writer(vec![]);

            wtr.write_record(&row)
                .map(|_| String::from_utf8(wtr.into_inner().unwrap()).unwrap())
                .map_err(|_| "Error generating csv")
        }

        def generate_lines(rows: Vec<Vec<String>>) -> Result<String, &'static str> {
            generate_lines(&rows).map_err(|_| "Error generating csv")
        }
    }
}
<commit_msg>Wrap calling Enumerator#next to rb_protect<commit_after>#[macro_use]
extern crate helix;
extern crate csv;

use std::error::Error;
use std::io::Read;
use helix::sys;
use helix::sys::{VALUE, RubyException};
use helix::{FromRuby, CheckResult, ToRuby};
use helix::libc::{c_void};

fn generate_lines(rows: &[Vec<String>]) -> Result<String, Box<Error>> {
    let mut wtr = csv::WriterBuilder::new().from_writer(vec![]);
    for row in rows {
        wtr.write_record(row)?;
    }

    Ok(String::from_utf8(wtr.into_inner()?)?)
}

fn record_to_ruby(record: &csv::ByteRecord) -> VALUE {
    let inner_array = unsafe { sys::rb_ary_new_capa(record.len() as isize) };
    for column in record.iter() {
        unsafe {
            let column_value =
                sys::rb_utf8_str_new(column.as_ptr() as *const i8, column.len() as i64);
            sys::rb_ary_push(inner_array, column_value);
        }
    }
    inner_array
}

extern fn protect_wrapper<F>(closure: *mut c_void) -> VALUE
      where F: FnOnce() -> VALUE {
    let closure_option = closure as *mut Option<F>;
    unsafe {
      (*closure_option).take().unwrap()()
    }
  }

pub fn protect<F>(func: F) -> Result<VALUE, RubyException>
where
    F: FnOnce() -> VALUE,
{
    let mut state = sys::EMPTY_EXCEPTION;
    let value = unsafe {
        sys::rb_protect(
            protect_wrapper::<F>,
            &func as *const _ as *mut c_void,
            &mut state,
        )
    };
    if state == sys::EMPTY_EXCEPTION {
        Ok(value)
    } else {
        Err(state)
    }
}

struct Enumerator {
    value: VALUE,
}

impl FromRuby for Enumerator {
    type Checked = Enumerator;

    fn from_ruby(value: VALUE) -> CheckResult<Enumerator> {
        // TODO: validate this?
        Ok(Enumerator { value })
    }

    fn from_checked(checked: Enumerator) -> Enumerator {
        checked
    }
}

struct EnumeratorRead {
    value: VALUE,
    next: Option<Vec<u8>>,
}

impl EnumeratorRead {
    fn new(value: VALUE) -> EnumeratorRead {
        EnumeratorRead {
            value,
            next: None,
        }
    }

    fn read_and_store_overflow(&mut self, buf: &mut [u8], value: &[u8]) -> std::io::Result<usize> {
        if value.len() > buf.len() {
            match value.split_at(buf.len()) {
                (current, next) => {
                    for (index, c) in current.iter().enumerate() {
                        buf[index] = *c;
                    }
                    self.next = Some(next.to_vec());
                    Ok(current.len())
                }
            }

        } else {
            for (index, value) in value.iter().enumerate() {
                buf[index] = *value;
            }
            self.next = None;
            Ok(value.len() as usize)
        }
    }

    fn read_from_external(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {

        let value = self.value;
        let result = protect(|| {
            unsafe { sys::rb_funcall(
                value,
                sys::rb_intern("next\0".as_ptr() as *const i8),
                0)
            }
        });
        match result {
            Ok(next) => {
                let string = String::from_ruby_unwrap(next);
                self.read_and_store_overflow(buf, string.as_bytes())
            },
            Err(state) => {
                unsafe { sys::rb_jump_tag(state) };
                //Err(std::io::Error::new(ErrorKind::Other, "Ruby Exception"))
            }
        }

    }
}

impl Read for EnumeratorRead {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        match self.next.take() {
            Some(ref inner) => self.read_and_store_overflow(buf, inner),
            None => self.read_from_external(buf),
        }
    }
}

fn csv_reader<R: Read>(reader: R) -> csv::Reader<R> {
    csv::ReaderBuilder::new()
        .buffer_capacity(16 * 1024)
        .has_headers(false)
        .from_reader(reader)
}

fn yield_csv(data: &Enumerator) -> Result<(), csv::Error> {
    let mut reader = csv_reader(EnumeratorRead::new(data.value));
    let mut record = csv::ByteRecord::new();

    while reader.read_byte_record(&mut record)? {
        let inner_array = record_to_ruby(&record);
        unsafe {
            sys::rb_yield(inner_array);
        }
    }

    Ok(())
}

fn parse_csv(data: &str) -> Result<Vec<Vec<VALUE>>, csv::Error> {
    csv_reader(data.as_bytes())
        .records()
        .map(|r| r.map(|v| record_to_vec(&v)))
        .collect()
}

fn record_to_vec(record: &csv::StringRecord) -> Vec<VALUE> {
    record.iter().map(|s| s.to_ruby().unwrap()).collect()
}

ruby! {
    class RscsvReader {
        def each_internal(data: Enumerator) -> Result<(), &'static str> {
            yield_csv(&data).map_err(|_| "Error parsing CSV")
        }

        def parse(data: String) -> Result<Vec<Vec<VALUE>>, &'static str> {
            parse_csv(&data).map_err(|_| "Error parsing CSV")
        }
    }

    class RscsvWriter {
        def generate_line(row: Vec<String>) -> Result<String, &'static str> {
            let mut wtr = csv::WriterBuilder::new().from_writer(vec![]);

            wtr.write_record(&row)
                .map(|_| String::from_utf8(wtr.into_inner().unwrap()).unwrap())
                .map_err(|_| "Error generating csv")
        }

        def generate_lines(rows: Vec<Vec<String>>) -> Result<String, &'static str> {
            generate_lines(&rows).map_err(|_| "Error generating csv")
        }
    }
}
<|endoftext|>


<commit_before>#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]

#[macro_use] extern crate hyper;
#[macro_use] extern crate lazy_static;
extern crate crypto;
extern crate pencil;
extern crate serde;
extern crate serde_json;

use crypto::hmac::Hmac;
use crypto::mac::{Mac, MacResult};
use crypto::sha1::Sha1;
use pencil::Request;
use std::env;
use std::io::Read;
use std::path::Path;
use std::process::{Stdio, Command};
use std::thread;

header! { (XGitHubEvent, "X-GitHub-Event") => [String] }
header! { (XGitHubDelivery, "X-GitHub-Delivery") => [String] }
header! { (XHubSignature, "X-Hub-Signature") => [String] }

lazy_static! {
  pub static ref PROD_REPO: String = env::var("TENJAVA_WEBSITE_PROD_REPO").expect("missing TENJAVA_WEBSITE_PROD_REPO");
  pub static ref DEV_REPO: String = env::var("TENJAVA_WEBSITE_DEV_REPO").expect("missing TENJAVA_WEBSITE_DEV_REPO");
}

pub type DeployResult<T> = Result<T, String>;

pub enum Branch {
  Master,
  Dev
}

pub fn get_request_bytes(request: &mut Request) -> DeployResult<Vec<u8>> {
  let mut bytes: Vec<u8> = Vec::new();
  match request.read_to_end(&mut bytes) {
    Ok(_) => Ok(bytes),
    Err(e) => Err(format!("could not read request: {}", e))
  }
}

#[derive(Deserialize)]
struct DeployRequest {
  #[serde(rename = "ref")]
  ref_key: String
}

#[derive(Deserialize)]
pub struct CommandFile {
  pub commands: Vec<Vec<String>>
}

impl CommandFile {
  pub fn execute(&self, branch: &Branch) {
    for command in &self.commands {
      self.execute_command(branch, command.clone());
    }
  }

  fn execute_command(&self, branch: &Branch, command: Vec<String>) {
    let repo_path = match *branch {
      Branch::Master => &*PROD_REPO,
      Branch::Dev => &*DEV_REPO
    };
    thread::spawn(move || {
      if command.is_empty() {
        println!("no command");
        return;
      }
      let command_name = &command[0];
      let args = if command.len() > 1 {
        &command[1..]
      } else {
        &[]
      };
      let status = Command::new(command_name.clone())
        .args(args)
        .stdout(Stdio::null())
        .current_dir(Path::new(repo_path))
        .status();
      let status = match status {
        Ok(r) => r,
        Err(e) => {
          println!("could not start {}: {}", command_name, e);
          return;
        }
      };
      if !status.success() {
        match status.code() {
          Some(code) => {
            println!("{} exited with code {}", command_name, code);
          },
          None => {
            println!("{} exited with an unknown status code", command_name);
          }
        }
      } else {
        println!("{} exited successfully", command_name);
      }
    });
  }
}

fn get_request_from_bytes(bytes: Vec<u8>) -> DeployResult<DeployRequest> {
  let json_string = match String::from_utf8(bytes) {
    Ok(x) => x,
    Err(e) => return Err(format!("could not convert request to string: {}", e))
  };
  serde_json::from_str(&json_string).map_err(|x| format!("could not process json from request: {}", x))
}

pub fn get_branch(bytes: Vec<u8>) -> DeployResult<Branch> {
  let request = try!(get_request_from_bytes(bytes));
  let branch = match request.ref_key.split('/').last() {
    Some(x) => x,
    None => return Err("invalid 'ref' key".into())
  };
  match branch {
    "master" => Ok(Branch::Master),
    "dev" => Ok(Branch::Dev),
    _ => Err("invalid branch".into())
  }
}

pub fn check_signature(bytes: &[u8], signature: &XHubSignature, secret: &str) -> DeployResult<bool> {
  let (method, hash) = {
    let mut split = signature.split('=');
    let method = match split.next() {
      Some(x) => x,
      None => return Err("invalid signature".into())
    };
    let hash = match split.next() {
      Some(x) => x,
      None => return Err("invalid signature".into())
    };
    (method, hash)
  };
  if method != "sha1" {
    return Err("invalid signature method (non-sha1)".into());
  }
  let hash = try!(hex_string_to_bytes(hash));
  let result = build_sha1_hmac(secret, bytes).result();
  let check_against = MacResult::new(&hash);
  Ok(result == check_against)
}

fn build_sha1_hmac(secret: &str, input: &[u8]) -> Hmac<Sha1> {
  let mut hmac = Hmac::new(Sha1::new(), secret.as_bytes());
  hmac.input(input);
  hmac
}

pub fn hex_string_to_bytes(hex_string: &str) -> DeployResult<Vec<u8>> {
  let char_vec = hex_string.chars().collect::<Vec<_>>();
  let chunks = char_vec.chunks(2);
  let parsed: Vec<_> = chunks
    .map(|x| u8::from_str_radix(
        x.into_iter().cloned().collect::<String>().as_str(),
        16
      )
    )
    .collect();
  if parsed.iter().any(|x| x.is_err()) {
    return Err("could not parse hex string".into());
  }
  Ok(parsed.into_iter().flat_map(|x| x).collect())
}
<commit_msg>fix: wait for commands<commit_after>#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]

#[macro_use] extern crate hyper;
#[macro_use] extern crate lazy_static;
extern crate crypto;
extern crate pencil;
extern crate serde;
extern crate serde_json;

use crypto::hmac::Hmac;
use crypto::mac::{Mac, MacResult};
use crypto::sha1::Sha1;
use pencil::Request;
use std::env;
use std::io::Read;
use std::path::Path;
use std::process::{Stdio, Command};
use std::thread;

header! { (XGitHubEvent, "X-GitHub-Event") => [String] }
header! { (XGitHubDelivery, "X-GitHub-Delivery") => [String] }
header! { (XHubSignature, "X-Hub-Signature") => [String] }

lazy_static! {
  pub static ref PROD_REPO: String = env::var("TENJAVA_WEBSITE_PROD_REPO").expect("missing TENJAVA_WEBSITE_PROD_REPO");
  pub static ref DEV_REPO: String = env::var("TENJAVA_WEBSITE_DEV_REPO").expect("missing TENJAVA_WEBSITE_DEV_REPO");
}

pub type DeployResult<T> = Result<T, String>;

pub enum Branch {
  Master,
  Dev
}

pub fn get_request_bytes(request: &mut Request) -> DeployResult<Vec<u8>> {
  let mut bytes: Vec<u8> = Vec::new();
  match request.read_to_end(&mut bytes) {
    Ok(_) => Ok(bytes),
    Err(e) => Err(format!("could not read request: {}", e))
  }
}

#[derive(Deserialize)]
struct DeployRequest {
  #[serde(rename = "ref")]
  ref_key: String
}

#[derive(Deserialize)]
pub struct CommandFile {
  pub commands: Vec<Vec<String>>
}

impl CommandFile {
  pub fn execute(&self, branch: &Branch) {
    for command in &self.commands {
      self.execute_command(branch, command.clone());
    }
  }

  fn execute_command(&self, branch: &Branch, command: Vec<String>) {
    let repo_path = match *branch {
      Branch::Master => &*PROD_REPO,
      Branch::Dev => &*DEV_REPO
    };
    let handle = thread::spawn(move || {
      if command.is_empty() {
        println!("no command");
        return;
      }
      let command_name = &command[0];
      let args = if command.len() > 1 {
        &command[1..]
      } else {
        &[]
      };
      let status = Command::new(command_name.clone())
        .args(args)
        .stdout(Stdio::null())
        .current_dir(Path::new(repo_path))
        .status();
      let status = match status {
        Ok(r) => r,
        Err(e) => {
          println!("could not start {}: {}", command_name, e);
          return;
        }
      };
      if !status.success() {
        match status.code() {
          Some(code) => {
            println!("{} exited with code {}", command_name, code);
          },
          None => {
            println!("{} exited with an unknown status code", command_name);
          }
        }
      } else {
        println!("{} exited successfully", command_name);
      }
    });
    handle.join().unwrap();
  }
}

fn get_request_from_bytes(bytes: Vec<u8>) -> DeployResult<DeployRequest> {
  let json_string = match String::from_utf8(bytes) {
    Ok(x) => x,
    Err(e) => return Err(format!("could not convert request to string: {}", e))
  };
  serde_json::from_str(&json_string).map_err(|x| format!("could not process json from request: {}", x))
}

pub fn get_branch(bytes: Vec<u8>) -> DeployResult<Branch> {
  let request = try!(get_request_from_bytes(bytes));
  let branch = match request.ref_key.split('/').last() {
    Some(x) => x,
    None => return Err("invalid 'ref' key".into())
  };
  match branch {
    "master" => Ok(Branch::Master),
    "dev" => Ok(Branch::Dev),
    _ => Err("invalid branch".into())
  }
}

pub fn check_signature(bytes: &[u8], signature: &XHubSignature, secret: &str) -> DeployResult<bool> {
  let (method, hash) = {
    let mut split = signature.split('=');
    let method = match split.next() {
      Some(x) => x,
      None => return Err("invalid signature".into())
    };
    let hash = match split.next() {
      Some(x) => x,
      None => return Err("invalid signature".into())
    };
    (method, hash)
  };
  if method != "sha1" {
    return Err("invalid signature method (non-sha1)".into());
  }
  let hash = try!(hex_string_to_bytes(hash));
  let result = build_sha1_hmac(secret, bytes).result();
  let check_against = MacResult::new(&hash);
  Ok(result == check_against)
}

fn build_sha1_hmac(secret: &str, input: &[u8]) -> Hmac<Sha1> {
  let mut hmac = Hmac::new(Sha1::new(), secret.as_bytes());
  hmac.input(input);
  hmac
}

pub fn hex_string_to_bytes(hex_string: &str) -> DeployResult<Vec<u8>> {
  let char_vec = hex_string.chars().collect::<Vec<_>>();
  let chunks = char_vec.chunks(2);
  let parsed: Vec<_> = chunks
    .map(|x| u8::from_str_radix(
        x.into_iter().cloned().collect::<String>().as_str(),
        16
      )
    )
    .collect();
  if parsed.iter().any(|x| x.is_err()) {
    return Err("could not parse hex string".into());
  }
  Ok(parsed.into_iter().flat_map(|x| x).collect())
}
<|endoftext|>


<commit_before>//! A library providing a generic connection pool.
#![feature(unsafe_destructor, phase)]
#![warn(missing_doc)]
#![doc(html_root_url="http://www.rust-ci.org/sfackler/r2d2/doc")]

#[phase(plugin, link)]
extern crate log;
extern crate serialize;

use std::comm;
use std::collections::{Deque, RingBuf};
use std::sync::{Arc, Mutex};
use std::fmt;

pub use config::Config;

mod config;

/// A trait which provides database-specific functionality.
pub trait PoolManager<C, E>: Send+Sync {
    /// Attempts to create a new connection.
    fn connect(&self) -> Result<C, E>;

    /// Determines if the connection is still connected to the database.
    ///
    /// A standard implementation would check if a simple query like `SELECT 1`
    /// succeeds.
    fn is_valid(&self, conn: &mut C) -> bool;

    /// *Quickly* determines if the connection is no longer usable.
    ///
    /// This will be called synchronously every time a connection is returned
    /// to the pool, so it should *not* block. If it returns `true`, the
    /// connection will be discarded.
    ///
    /// For example, an implementation might check if the underlying TCP socket
    /// has disconnected. Implementations that do not support this kind of
    /// fast health check may simply return `false`.
    fn has_broken(&self, conn: &mut C) -> bool;
}

/// A trait which handles errors reported by the `PoolManager`.
pub trait ErrorHandler<E>: Send+Sync {
    /// Handles a connection error.
    fn handle_error(&self, error: E);
}

/// An `ErrorHandler` which does nothing.
pub struct NoopErrorHandler;

impl<E> ErrorHandler<E> for NoopErrorHandler {
    fn handle_error(&self, _: E) {}
}

/// An `ErrorHandler` which logs at the error level.
pub struct LoggingErrorHandler;

impl<E> ErrorHandler<E> for LoggingErrorHandler where E: fmt::Show {
    fn handle_error(&self, error: E) {
        error!("Error opening connection: {}", error);
    }
}

/// An error type returned if pool creation fails.
#[deriving(PartialEq, Eq)]
pub enum NewPoolError<E> {
    /// The provided pool configuration was invalid.
    InvalidConfig(&'static str),
    /// The manager returned an error when creating a connection.
    ConnectionError(E),
}

impl<E> fmt::Show for NewPoolError<E> where E: fmt::Show {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InvalidConfig(ref error) => write!(f, "Invalid config: {}", error),
            ConnectionError(ref error) => write!(f, "Unable to create connections: {}", error),
        }
    }
}

enum Command<C> {
    AddConnection,
    TestConnection(C),
}

struct PoolInternals<C> {
    conns: RingBuf<C>,
    num_conns: uint,
}

struct InnerPool<C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    config: Config,
    manager: M,
    error_handler: H,
    internals: Mutex<PoolInternals<C>>,
}

/// A generic connection pool.
pub struct Pool<C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    helper_chan: Mutex<Sender<Command<C>>>,
    inner: Arc<InnerPool<C, E, M, H>>
}

impl<C, E, M, H> Pool<C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    /// Creates a new connection pool.
    pub fn new(config: Config, manager: M, error_handler: H)
               -> Result<Pool<C, E, M, H>, NewPoolError<E>> {
        try!(config.validate().map_err(InvalidConfig));

        let mut internals = PoolInternals {
            conns: RingBuf::new(),
            num_conns: config.pool_size,
        };

        for _ in range(0, config.pool_size) {
            match manager.connect() {
                Ok(conn) => internals.conns.push(conn),
                Err(err) => return Err(ConnectionError(err)),
            }
        }

        let inner = Arc::new(InnerPool {
            config: config,
            manager: manager,
            error_handler: error_handler,
            internals: Mutex::new(internals),
        });

        let (sender, receiver) = comm::channel();
        // FIXME :(
        let receiver = Arc::new(Mutex::new(receiver));

        for _ in range(0, config.helper_tasks) {
            let inner = inner.clone();
            let receiver = receiver.clone();
            spawn(proc() helper_task(receiver, inner));
        }

        Ok(Pool {
            helper_chan: Mutex::new(sender),
            inner: inner,
        })
    }

    /// Retrieves a connection from the pool.
    pub fn get<'a>(&'a self) -> Result<PooledConnection<'a, C, E, M, H>, ()> {
        let mut internals = self.inner.internals.lock();

        loop {
            match internals.conns.pop_front() {
                Some(mut conn) => {
                    if self.inner.config.test_on_check_out {
                        drop(internals);
                        let valid = self.inner.manager.is_valid(&mut conn);

                        if !valid {
                            internals = self.inner.internals.lock();
                            internals.num_conns -= 1;
                            continue;
                        }
                    }

                    return Ok(PooledConnection {
                        pool: self,
                        conn: Some(conn),
                    })
                }
                None => internals.cond.wait(),
            }
        }
    }

    fn put_back(&self, mut conn: C) {
        // This is specified to be fast, but call it before locking anyways
        let broken = self.inner.manager.has_broken(&mut conn);

        let mut internals = self.inner.internals.lock();
        if broken {
            internals.num_conns -= 1;
        } else {
            internals.conns.push(conn);
            internals.cond.signal();
        }
    }
}

fn helper_task<C, E, M, H>(receiver: Arc<Mutex<Receiver<Command<C>>>>,
                           inner: Arc<InnerPool<C, E, M, H>>)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    loop {
        let mut receiver = receiver.lock();
        let res = receiver.recv_opt();
        drop(receiver);

        match res {
            Ok(AddConnection) => add_connection(&*inner),
            Ok(TestConnection(conn)) => test_connection(&*inner, conn),
            Err(()) => break,
        }
    }
}

fn add_connection<C, E, M, H>(inner: &InnerPool<C, E, M, H>)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    match inner.manager.connect() {
        Ok(conn) => {
            let mut internals = inner.internals.lock();
            internals.conns.push(conn);
            internals.num_conns += 1;
            internals.cond.signal();
        }
        Err(err) => inner.error_handler.handle_error(err),
    }
}

fn test_connection<C, E, M, H>(inner: &InnerPool<C, E, M, H>, mut conn: C)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    let is_valid = inner.manager.is_valid(&mut conn);
    let mut internals = inner.internals.lock();
    if is_valid {
        internals.conns.push(conn);
    } else {
        internals.num_conns -= 1;
    }
}

/// A smart pointer wrapping an underlying connection.
pub struct PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    pool: &'a Pool<C, E, M, H>,
    conn: Option<C>,
}

#[unsafe_destructor]
impl<'a, C, E, M, H> Drop for PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    fn drop(&mut self) {
        self.pool.put_back(self.conn.take().unwrap());
    }
}

impl<'a, C, E, M, H> Deref<C> for PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    fn deref(&self) -> &C {
        self.conn.as_ref().unwrap()
    }
}
<commit_msg>Clean up checkout test logic a bit<commit_after>//! A library providing a generic connection pool.
#![feature(unsafe_destructor, phase)]
#![warn(missing_doc)]
#![doc(html_root_url="http://www.rust-ci.org/sfackler/r2d2/doc")]

#[phase(plugin, link)]
extern crate log;
extern crate serialize;

use std::comm;
use std::collections::{Deque, RingBuf};
use std::sync::{Arc, Mutex};
use std::fmt;

pub use config::Config;

mod config;

/// A trait which provides database-specific functionality.
pub trait PoolManager<C, E>: Send+Sync {
    /// Attempts to create a new connection.
    fn connect(&self) -> Result<C, E>;

    /// Determines if the connection is still connected to the database.
    ///
    /// A standard implementation would check if a simple query like `SELECT 1`
    /// succeeds.
    fn is_valid(&self, conn: &mut C) -> bool;

    /// *Quickly* determines if the connection is no longer usable.
    ///
    /// This will be called synchronously every time a connection is returned
    /// to the pool, so it should *not* block. If it returns `true`, the
    /// connection will be discarded.
    ///
    /// For example, an implementation might check if the underlying TCP socket
    /// has disconnected. Implementations that do not support this kind of
    /// fast health check may simply return `false`.
    fn has_broken(&self, conn: &mut C) -> bool;
}

/// A trait which handles errors reported by the `PoolManager`.
pub trait ErrorHandler<E>: Send+Sync {
    /// Handles a connection error.
    fn handle_error(&self, error: E);
}

/// An `ErrorHandler` which does nothing.
pub struct NoopErrorHandler;

impl<E> ErrorHandler<E> for NoopErrorHandler {
    fn handle_error(&self, _: E) {}
}

/// An `ErrorHandler` which logs at the error level.
pub struct LoggingErrorHandler;

impl<E> ErrorHandler<E> for LoggingErrorHandler where E: fmt::Show {
    fn handle_error(&self, error: E) {
        error!("Error opening connection: {}", error);
    }
}

/// An error type returned if pool creation fails.
#[deriving(PartialEq, Eq)]
pub enum NewPoolError<E> {
    /// The provided pool configuration was invalid.
    InvalidConfig(&'static str),
    /// The manager returned an error when creating a connection.
    ConnectionError(E),
}

impl<E> fmt::Show for NewPoolError<E> where E: fmt::Show {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InvalidConfig(ref error) => write!(f, "Invalid config: {}", error),
            ConnectionError(ref error) => write!(f, "Unable to create connections: {}", error),
        }
    }
}

enum Command<C> {
    AddConnection,
    TestConnection(C),
}

struct PoolInternals<C> {
    conns: RingBuf<C>,
    num_conns: uint,
}

struct InnerPool<C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    config: Config,
    manager: M,
    error_handler: H,
    internals: Mutex<PoolInternals<C>>,
}

/// A generic connection pool.
pub struct Pool<C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    helper_chan: Mutex<Sender<Command<C>>>,
    inner: Arc<InnerPool<C, E, M, H>>
}

impl<C, E, M, H> Pool<C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    /// Creates a new connection pool.
    pub fn new(config: Config, manager: M, error_handler: H)
               -> Result<Pool<C, E, M, H>, NewPoolError<E>> {
        try!(config.validate().map_err(InvalidConfig));

        let mut internals = PoolInternals {
            conns: RingBuf::new(),
            num_conns: config.pool_size,
        };

        for _ in range(0, config.pool_size) {
            match manager.connect() {
                Ok(conn) => internals.conns.push(conn),
                Err(err) => return Err(ConnectionError(err)),
            }
        }

        let inner = Arc::new(InnerPool {
            config: config,
            manager: manager,
            error_handler: error_handler,
            internals: Mutex::new(internals),
        });

        let (sender, receiver) = comm::channel();
        // FIXME :(
        let receiver = Arc::new(Mutex::new(receiver));

        for _ in range(0, config.helper_tasks) {
            let inner = inner.clone();
            let receiver = receiver.clone();
            spawn(proc() helper_task(receiver, inner));
        }

        Ok(Pool {
            helper_chan: Mutex::new(sender),
            inner: inner,
        })
    }

    /// Retrieves a connection from the pool.
    pub fn get<'a>(&'a self) -> Result<PooledConnection<'a, C, E, M, H>, ()> {
        let mut internals = self.inner.internals.lock();

        loop {
            match internals.conns.pop_front() {
                Some(mut conn) => {
                    drop(internals);

                    if self.inner.config.test_on_check_out &&
                            !self.inner.manager.is_valid(&mut conn) {
                        internals = self.inner.internals.lock();
                        internals.num_conns -= 1;
                        continue;
                    }

                    return Ok(PooledConnection {
                        pool: self,
                        conn: Some(conn),
                    })
                }
                None => internals.cond.wait(),
            }
        }
    }

    fn put_back(&self, mut conn: C) {
        // This is specified to be fast, but call it before locking anyways
        let broken = self.inner.manager.has_broken(&mut conn);

        let mut internals = self.inner.internals.lock();
        if broken {
            internals.num_conns -= 1;
        } else {
            internals.conns.push(conn);
            internals.cond.signal();
        }
    }
}

fn helper_task<C, E, M, H>(receiver: Arc<Mutex<Receiver<Command<C>>>>,
                           inner: Arc<InnerPool<C, E, M, H>>)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    loop {
        let mut receiver = receiver.lock();
        let res = receiver.recv_opt();
        drop(receiver);

        match res {
            Ok(AddConnection) => add_connection(&*inner),
            Ok(TestConnection(conn)) => test_connection(&*inner, conn),
            Err(()) => break,
        }
    }
}

fn add_connection<C, E, M, H>(inner: &InnerPool<C, E, M, H>)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    match inner.manager.connect() {
        Ok(conn) => {
            let mut internals = inner.internals.lock();
            internals.conns.push(conn);
            internals.num_conns += 1;
            internals.cond.signal();
        }
        Err(err) => inner.error_handler.handle_error(err),
    }
}

fn test_connection<C, E, M, H>(inner: &InnerPool<C, E, M, H>, mut conn: C)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    let is_valid = inner.manager.is_valid(&mut conn);
    let mut internals = inner.internals.lock();
    if is_valid {
        internals.conns.push(conn);
    } else {
        internals.num_conns -= 1;
    }
}

/// A smart pointer wrapping an underlying connection.
pub struct PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    pool: &'a Pool<C, E, M, H>,
    conn: Option<C>,
}

#[unsafe_destructor]
impl<'a, C, E, M, H> Drop for PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    fn drop(&mut self) {
        self.pool.put_back(self.conn.take().unwrap());
    }
}

impl<'a, C, E, M, H> Deref<C> for PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    fn deref(&self) -> &C {
        self.conn.as_ref().unwrap()
    }
}
<|endoftext|>


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

//! Net-utils library provides a configurable TCP/SSL client connection pool
#![crate_name = "net_utils"]
#![crate_type = "lib"]
#![warn(missing_docs)]
// #![allow(unstable)]
#![allow(unused_must_use)]

/// # Example
///
///Define the below dependency in Cargo.toml
///
///[dependencies.net-utils]
///git = "https://github.com/rohitjoshi/net-utils.git"
///
/// ```
/// extern crate "net-utils" as utils;
/// use std::default::Default;
/// use std::sync::{ Arc, Mutex };
/// use utils::net::config;
/// use utils::net::poolmgr;

/// fn main() {
///     let mut cfg : config::Config = Default::default();
///     //set port to 80
///     cfg.port= Some(80);
///     //set host to
///     cfg.server = Some("google.com".to_string());
///     let mut pool = poolmgr::ConnectionPool::new(2, 20, true, &cfg);
///     //get the connection
///     let mut conn = pool.aquire().unwrap();
///     conn.writer.write_str("GET google.com\r\n").unwrap();
///     conn.writer.flush().unwrap();
///     let r = conn.reader.read_line();
///     println!("Received {}", r);
///     pool.release(conn);
///}
/// ```
///
///Here is above example used in multi-threded environment
/// ```
/// extern crate "net-utils" as utils;
/// use std::default::Default;
/// use std::sync::{ Arc, Mutex };
/// use utils::net::config;
/// use utils::net::poolmgr;
///
/// fn main() {
///     let mut cfg : config::Config = Default::default();
///     //set port to 80
///     cfg.port= Some(80);
///     //set host to
///     cfg.server = Some("google.com".to_string());
///     let mut pool = poolmgr::ConnectionPool::new(2, 20, true, &cfg);
///     let pool = Arc::new(Mutex::new(pool));
///     for _ in range(0u, 2) {
///         let pool = pool.clone();
///         spawn(move || {
///             let mut conn = pool.lock().aquire().unwrap();
///             conn.writer.write_str("GET google.com\r\n").unwrap();
///             conn.writer.flush().unwrap();
///             let r = conn.reader.read_line();
///             println!("Received {}", r);
///             pool.lock().release(conn);
///        });
///     }
/// }
//# ```
#[cfg(feature = "ssl")]
extern crate openssl;
#[macro_use]
extern crate log;
extern crate time;
extern crate uuid;
/// module net provides the TCP/SSL connection and connection pool functionality
pub mod net;
<commit_msg>fixed test case failure<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Net-utils library provides a configurable TCP/SSL client connection pool
//! A simple, connection pool library.
#![crate_name = "net_utils"]
#![crate_type = "lib"]
#![warn(missing_docs)]
// #![allow(unstable)]
#![allow(unused_must_use)]
#[cfg(feature = "ssl")]
extern crate openssl;
#[macro_use]
extern crate log;
extern crate time;
extern crate uuid;
/// module net provides the TCP/SSL connection and connection pool functionality
pub mod net;
<|endoftext|>


<commit_before>#![cfg_attr(all(feature="nightly", test), feature(test))]
#![cfg_attr(feature="nightly", feature(const_fn))]

#[macro_use]
#[cfg(test)]
extern crate lazy_static;

use std::thread::{self, JoinHandle};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::sync::{Arc, Mutex, Barrier};
use std::cell::RefCell;
use std::marker::PhantomData;

enum Message {
    NewJob(Thunk<'static>),
    Join,
}

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Thunk<'a> = Box<FnBox + Send + 'a>;

impl Drop for PoolCache {
    fn drop(&mut self) {
        ::std::mem::replace(&mut self.job_sender, None);
    }
}

pub struct PoolCache {
    threads: Vec<JoinHandle<()>>,
    job_sender: Option<Sender<Message>>,
    join_barrier: Arc<(Mutex<Receiver<Message>>, Barrier)>,
}

impl PoolCache {
    pub fn new(n: u32) -> PoolCache {
        assert!(n >= 1);

        let (job_sender, job_receiver) = channel();
        let job_receiver = Arc::new((Mutex::new(job_receiver),
                                     Barrier::new(n as usize + 1)));

        let mut threads = Vec::with_capacity(n as usize);
        for _ in 0..n {
            let job_receiver = job_receiver.clone();
            threads.push(thread::spawn(move || {
                loop {
                    let message = {
                        // Only lock jobs for the time it takes
                        // to get a job, not run it.
                        let lock = job_receiver.0.lock().unwrap();
                        lock.recv()
                    };

                    match message {
                        Ok(Message::NewJob(job)) => {
                            job.call_box();
                        }
                        Ok(Message::Join) => {
                            job_receiver.1.wait();
                        }
                        // The pool was dropped.
                        Err(..) => break
                    }
                }
            }));
        }

        PoolCache {
            threads: threads,
            job_sender: Some(job_sender),
            join_barrier: job_receiver,
        }

        // spawn n threads, put them in waiting mode
    }

    pub fn scope<'pool, 'scope, F, R>(&'pool mut self, f: F) -> R
        where F: FnOnce(&Scope<'pool, 'scope>) -> R
    {
        let mut scope = Scope {
            pool: self,
            dtors: RefCell::new(None),
            _marker: PhantomData,
        };
        let ret = f(&scope);
        scope.drop_all();
        ret
    }

    pub fn thread_count(&self) -> u32 {
        self.threads.len() as u32
    }
}

/////////////////////////////////////////////////////////////////////////////

pub struct Scope<'pool, 'scope> {
    pool: &'pool mut PoolCache,
    dtors: RefCell<Option<DtorChain<'scope>>>,
    _marker: PhantomData<&'scope mut ()>,
}

struct DtorChain<'a> {
    dtor: Box<FnBox + 'a>,
    next: Option<Box<DtorChain<'a>>>
}

impl<'pool, 'scope> Scope<'pool, 'scope> {
    // This method is carefully written in a transactional style, so
    // that it can be called directly and, if any dtor panics, can be
    // resumed in the unwinding this causes. By initially running the
    // method outside of any destructor, we avoid any leakage problems
    // due to #14875.
    fn drop_all(&mut self) {
        loop {
            // use a separate scope to ensure that the RefCell borrow
            // is relinquished before running `dtor`
            let dtor = {
                let mut dtors = self.dtors.borrow_mut();
                if let Some(mut node) = dtors.take() {
                    *dtors = node.next.take().map(|b| *b);
                    node.dtor
                } else {
                    break
                }
            };
            dtor.call_box()
        }

        for _ in 0..self.pool.threads.len() {
            self.pool.job_sender.as_ref().unwrap().send(Message::Join).unwrap();
        }

        self.pool.join_barrier.1.wait();
    }

    fn defer<F>(&self, f: F) where F: FnOnce() + 'scope {
        let mut dtors = self.dtors.borrow_mut();
        *dtors = Some(DtorChain {
            dtor: Box::new(f),
            next: dtors.take().map(Box::new)
        });
    }

    pub fn execute<F>(&self, f: F)
        where F: FnOnce() + Send + 'scope
    {
        let b = unsafe {
            ::std::mem::transmute::<Thunk<'scope>, Thunk<'static>>(Box::new(f))
        };
        self.pool.job_sender.as_ref().unwrap().send(Message::NewJob(b)).unwrap();
        self.defer(move || {

        });
    }
}

impl<'pool, 'scope> Drop for Scope<'pool, 'scope> {
    fn drop(&mut self) {
        self.drop_all()
    }
}

/////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    extern crate test;
    use super::PoolCache;

    #[test]
    fn example() {
        // Create a threadpool holding 4 threads
        let mut pool = PoolCache::new(4);

        let mut vec = vec![0, 1, 2, 3, 4, 5, 6, 7];

        // Use the threads as scoped threads that can
        // reference anything outside this closure
        pool.scope(|scoped| {

            // Create references to each element in the vector ...
            for e in &mut vec {
                // ... and add 1 to it in a seperate thread
                scoped.execute(move || {
                    *e += 1;
                });
            }
        });

        assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7, 8]);
    }

    #[test]
    fn smoketest() {
        let mut pool = PoolCache::new(4);

        for i in 1..7 {
            let mut vec = vec![0, 1, 2, 3, 4];
            pool.scope(|s| {
                for e in vec.iter_mut() {
                    s.execute(move || {
                        *e += i;
                    });
                }
            });

            let mut vec2 = vec![0, 1, 2, 3, 4];
            for e in vec2.iter_mut() {
                *e += i;
            }

            assert_eq!(vec, vec2);
        }
    }
}

#[cfg(test)]
mod benches {
    extern crate test;

    use self::test::{Bencher, black_box};
    use super::PoolCache;
    use std::sync::Mutex;

    // const MS_SLEEP_PER_OP: u32 = 1;

    lazy_static! {
        static ref POOL_1: Mutex<PoolCache> = Mutex::new(PoolCache::new(1));
        static ref POOL_2: Mutex<PoolCache> = Mutex::new(PoolCache::new(2));
        static ref POOL_3: Mutex<PoolCache> = Mutex::new(PoolCache::new(3));
        static ref POOL_4: Mutex<PoolCache> = Mutex::new(PoolCache::new(4));
        static ref POOL_5: Mutex<PoolCache> = Mutex::new(PoolCache::new(5));
        static ref POOL_8: Mutex<PoolCache> = Mutex::new(PoolCache::new(8));
    }

    fn fib(n: u64) -> u64 {
        let mut prev_prev: u64 = 1;
        let mut prev = 1;
        let mut current = 1;
        for _ in 2..(n+1) {
            current = prev_prev.wrapping_add(prev);
            prev_prev = prev;
            prev = current;
        }
        current
    }

    fn threads_interleaved_n(pool: &mut PoolCache)  {
        let size = 1024; // 1kiB

        let mut data = vec![1u8; size];
        pool.scope(|s| {
            for e in data.iter_mut() {
                s.execute(move || {
                    *e += fib(black_box(1000 * (*e as u64))) as u8;
                    //thread::sleep_ms(MS_SLEEP_PER_OP);
                });
            }
        });
    }

    #[bench]
    fn threads_interleaved_1(b: &mut Bencher) {
        b.iter(|| threads_interleaved_n(&mut POOL_1.lock().unwrap()))
    }

    #[bench]
    fn threads_interleaved_2(b: &mut Bencher) {
        b.iter(|| threads_interleaved_n(&mut POOL_2.lock().unwrap()))
    }

    #[bench]
    fn threads_interleaved_4(b: &mut Bencher) {
        b.iter(|| threads_interleaved_n(&mut POOL_4.lock().unwrap()))
    }

    #[bench]
    fn threads_interleaved_8(b: &mut Bencher) {
        b.iter(|| threads_interleaved_n(&mut POOL_8.lock().unwrap()))
    }

    fn threads_chunked_n(pool: &mut PoolCache) {
        let size = 1024 * 1024 * 100 / 4; // 100MiB

        let n = pool.thread_count();
        let mut data = vec![0u32; size];
        pool.scope(|s| {
            let l = (data.len() - 1) / n as usize + 1;
            for es in data.chunks_mut(l) {
                s.execute(move || {
                    if es.len() > 1 {
                        es[0] = 1;
                        es[1] = 1;
                        for i in 2..es.len() {
                            // Fibonnaci gets big fast,
                            // so just wrap around all the time
                            es[i] = es[i-1].wrapping_add(es[i-2]);
                        }
                    }
                    //thread::sleep_ms(MS_SLEEP_PER_OP);
                });
            }
        });
    }

    #[bench]
    fn threads_chunked_1(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_1.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_2(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_2.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_3(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_3.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_4(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_4.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_5(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_5.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_8(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_8.lock().unwrap()))
    }
}
<commit_msg>Make benchmarks only run on nightly<commit_after>#![cfg_attr(all(feature="nightly", test), feature(test))]
#![cfg_attr(feature="nightly", feature(const_fn))]

#[macro_use]
#[cfg(test)]
extern crate lazy_static;

use std::thread::{self, JoinHandle};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::sync::{Arc, Mutex, Barrier};
use std::cell::RefCell;
use std::marker::PhantomData;

enum Message {
    NewJob(Thunk<'static>),
    Join,
}

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Thunk<'a> = Box<FnBox + Send + 'a>;

impl Drop for PoolCache {
    fn drop(&mut self) {
        ::std::mem::replace(&mut self.job_sender, None);
    }
}

pub struct PoolCache {
    threads: Vec<JoinHandle<()>>,
    job_sender: Option<Sender<Message>>,
    join_barrier: Arc<(Mutex<Receiver<Message>>, Barrier)>,
}

impl PoolCache {
    pub fn new(n: u32) -> PoolCache {
        assert!(n >= 1);

        let (job_sender, job_receiver) = channel();
        let job_receiver = Arc::new((Mutex::new(job_receiver),
                                     Barrier::new(n as usize + 1)));

        let mut threads = Vec::with_capacity(n as usize);
        for _ in 0..n {
            let job_receiver = job_receiver.clone();
            threads.push(thread::spawn(move || {
                loop {
                    let message = {
                        // Only lock jobs for the time it takes
                        // to get a job, not run it.
                        let lock = job_receiver.0.lock().unwrap();
                        lock.recv()
                    };

                    match message {
                        Ok(Message::NewJob(job)) => {
                            job.call_box();
                        }
                        Ok(Message::Join) => {
                            job_receiver.1.wait();
                        }
                        // The pool was dropped.
                        Err(..) => break
                    }
                }
            }));
        }

        PoolCache {
            threads: threads,
            job_sender: Some(job_sender),
            join_barrier: job_receiver,
        }

        // spawn n threads, put them in waiting mode
    }

    pub fn scope<'pool, 'scope, F, R>(&'pool mut self, f: F) -> R
        where F: FnOnce(&Scope<'pool, 'scope>) -> R
    {
        let mut scope = Scope {
            pool: self,
            dtors: RefCell::new(None),
            _marker: PhantomData,
        };
        let ret = f(&scope);
        scope.drop_all();
        ret
    }

    pub fn thread_count(&self) -> u32 {
        self.threads.len() as u32
    }
}

/////////////////////////////////////////////////////////////////////////////

pub struct Scope<'pool, 'scope> {
    pool: &'pool mut PoolCache,
    dtors: RefCell<Option<DtorChain<'scope>>>,
    _marker: PhantomData<&'scope mut ()>,
}

struct DtorChain<'a> {
    dtor: Box<FnBox + 'a>,
    next: Option<Box<DtorChain<'a>>>
}

impl<'pool, 'scope> Scope<'pool, 'scope> {
    // This method is carefully written in a transactional style, so
    // that it can be called directly and, if any dtor panics, can be
    // resumed in the unwinding this causes. By initially running the
    // method outside of any destructor, we avoid any leakage problems
    // due to #14875.
    fn drop_all(&mut self) {
        loop {
            // use a separate scope to ensure that the RefCell borrow
            // is relinquished before running `dtor`
            let dtor = {
                let mut dtors = self.dtors.borrow_mut();
                if let Some(mut node) = dtors.take() {
                    *dtors = node.next.take().map(|b| *b);
                    node.dtor
                } else {
                    break
                }
            };
            dtor.call_box()
        }

        for _ in 0..self.pool.threads.len() {
            self.pool.job_sender.as_ref().unwrap().send(Message::Join).unwrap();
        }

        self.pool.join_barrier.1.wait();
    }

    fn defer<F>(&self, f: F) where F: FnOnce() + 'scope {
        let mut dtors = self.dtors.borrow_mut();
        *dtors = Some(DtorChain {
            dtor: Box::new(f),
            next: dtors.take().map(Box::new)
        });
    }

    pub fn execute<F>(&self, f: F)
        where F: FnOnce() + Send + 'scope
    {
        let b = unsafe {
            ::std::mem::transmute::<Thunk<'scope>, Thunk<'static>>(Box::new(f))
        };
        self.pool.job_sender.as_ref().unwrap().send(Message::NewJob(b)).unwrap();
        self.defer(move || {

        });
    }
}

impl<'pool, 'scope> Drop for Scope<'pool, 'scope> {
    fn drop(&mut self) {
        self.drop_all()
    }
}

/////////////////////////////////////////////////////////////////////////////

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

    #[test]
    fn example() {
        // Create a threadpool holding 4 threads
        let mut pool = PoolCache::new(4);

        let mut vec = vec![0, 1, 2, 3, 4, 5, 6, 7];

        // Use the threads as scoped threads that can
        // reference anything outside this closure
        pool.scope(|scoped| {

            // Create references to each element in the vector ...
            for e in &mut vec {
                // ... and add 1 to it in a seperate thread
                scoped.execute(move || {
                    *e += 1;
                });
            }
        });

        assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7, 8]);
    }

    #[test]
    fn smoketest() {
        let mut pool = PoolCache::new(4);

        for i in 1..7 {
            let mut vec = vec![0, 1, 2, 3, 4];
            pool.scope(|s| {
                for e in vec.iter_mut() {
                    s.execute(move || {
                        *e += i;
                    });
                }
            });

            let mut vec2 = vec![0, 1, 2, 3, 4];
            for e in vec2.iter_mut() {
                *e += i;
            }

            assert_eq!(vec, vec2);
        }
    }
}

#[cfg(all(test, feature="nightly"))]
mod benches {
    extern crate test;

    use self::test::{Bencher, black_box};
    use super::PoolCache;
    use std::sync::Mutex;

    // const MS_SLEEP_PER_OP: u32 = 1;

    lazy_static! {
        static ref POOL_1: Mutex<PoolCache> = Mutex::new(PoolCache::new(1));
        static ref POOL_2: Mutex<PoolCache> = Mutex::new(PoolCache::new(2));
        static ref POOL_3: Mutex<PoolCache> = Mutex::new(PoolCache::new(3));
        static ref POOL_4: Mutex<PoolCache> = Mutex::new(PoolCache::new(4));
        static ref POOL_5: Mutex<PoolCache> = Mutex::new(PoolCache::new(5));
        static ref POOL_8: Mutex<PoolCache> = Mutex::new(PoolCache::new(8));
    }

    fn fib(n: u64) -> u64 {
        let mut prev_prev: u64 = 1;
        let mut prev = 1;
        let mut current = 1;
        for _ in 2..(n+1) {
            current = prev_prev.wrapping_add(prev);
            prev_prev = prev;
            prev = current;
        }
        current
    }

    fn threads_interleaved_n(pool: &mut PoolCache)  {
        let size = 1024; // 1kiB

        let mut data = vec![1u8; size];
        pool.scope(|s| {
            for e in data.iter_mut() {
                s.execute(move || {
                    *e += fib(black_box(1000 * (*e as u64))) as u8;
                    //thread::sleep_ms(MS_SLEEP_PER_OP);
                });
            }
        });
    }

    #[bench]
    fn threads_interleaved_1(b: &mut Bencher) {
        b.iter(|| threads_interleaved_n(&mut POOL_1.lock().unwrap()))
    }

    #[bench]
    fn threads_interleaved_2(b: &mut Bencher) {
        b.iter(|| threads_interleaved_n(&mut POOL_2.lock().unwrap()))
    }

    #[bench]
    fn threads_interleaved_4(b: &mut Bencher) {
        b.iter(|| threads_interleaved_n(&mut POOL_4.lock().unwrap()))
    }

    #[bench]
    fn threads_interleaved_8(b: &mut Bencher) {
        b.iter(|| threads_interleaved_n(&mut POOL_8.lock().unwrap()))
    }

    fn threads_chunked_n(pool: &mut PoolCache) {
        let size = 1024 * 1024 * 100 / 4; // 100MiB

        let n = pool.thread_count();
        let mut data = vec![0u32; size];
        pool.scope(|s| {
            let l = (data.len() - 1) / n as usize + 1;
            for es in data.chunks_mut(l) {
                s.execute(move || {
                    if es.len() > 1 {
                        es[0] = 1;
                        es[1] = 1;
                        for i in 2..es.len() {
                            // Fibonnaci gets big fast,
                            // so just wrap around all the time
                            es[i] = es[i-1].wrapping_add(es[i-2]);
                        }
                    }
                    //thread::sleep_ms(MS_SLEEP_PER_OP);
                });
            }
        });
    }

    #[bench]
    fn threads_chunked_1(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_1.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_2(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_2.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_3(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_3.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_4(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_4.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_5(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_5.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_8(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_8.lock().unwrap()))
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use libc::{c_char, c_short, c_int};

pub enum SpcHandle {}

#[link(name = "snes_spc")]
extern {
    // Instantiate a new SPC emulator and return a handle to it.
    fn spc_new() -> *mut SpcHandle;

    // Free an SPC emulator given its handle.
    fn spc_delete(spc: *mut SpcHandle);

    // Load SPC data into emulator.
    fn spc_load_spc(spc: *mut SpcHandle, data: *const u8, len: c_int)
        -> *const c_char;

    // Clear SPC echo buffer.
    fn spc_clear_echo(spc: *mut SpcHandle);

    // Emulate SPC output, recording `count` 16-bit samples to `out`
    fn spc_play(spc: *mut SpcHandle, count: c_int, out: *mut c_short)
        -> *const c_char;
}

/// A simple, safe wrapper around an opaque SNES_SPC handle.
pub struct SnesSpc {
    handle: *mut SpcHandle
}

impl SnesSpc {
    pub fn new() -> SnesSpc {
        unsafe {
            SnesSpc {
                handle: spc_new()
            }
        }
    }

    pub fn load_spc(&mut self, data: &[u8]) {
        unsafe {
            spc_load_spc(self.handle, data.as_ptr(), data.len() as c_int);
        }
    }

    pub fn clear_echo(&mut self) {
        unsafe {
            spc_clear_echo(self.handle);
        }
    }

    pub fn play(&mut self, count: u32, out: &mut [i16]) {
        unsafe {
            // TODO: check that out is big enough :)
            spc_play(self.handle, count as c_int, out.as_mut_ptr());
        }
    }
}

#[test]
fn can_call_unsafe_api_without_exploding() {
    unsafe {
        let mut spc = spc_new();
        spc_delete(spc);
    }
}

#[test]
fn can_use_safe_wrapper_without_being_stabbed() {
    let mut spc = SnesSpc::new();
    spc.clear_echo();
    // Drop it!
}
<commit_msg>Add impl Send for SnesSpc; should be safe since the underlying handle is not exposed<commit_after>extern crate libc;

use libc::{c_char, c_short, c_int};

pub enum SpcHandle {}

#[link(name = "snes_spc")]
extern {
    // Instantiate a new SPC emulator and return a handle to it.
    fn spc_new() -> *mut SpcHandle;

    // Free an SPC emulator given its handle.
    fn spc_delete(spc: *mut SpcHandle);

    // Load SPC data into emulator.
    fn spc_load_spc(spc: *mut SpcHandle, data: *const u8, len: c_int)
        -> *const c_char;

    // Clear SPC echo buffer.
    fn spc_clear_echo(spc: *mut SpcHandle);

    // Emulate SPC output, recording `count` 16-bit samples to `out`
    fn spc_play(spc: *mut SpcHandle, count: c_int, out: *mut c_short)
        -> *const c_char;
}

/// A simple, safe wrapper around an opaque SNES_SPC handle.
pub struct SnesSpc {
    handle: *mut SpcHandle
}

unsafe impl Send for SnesSpc {}

impl SnesSpc {
    pub fn new() -> SnesSpc {
        unsafe {
            SnesSpc {
                handle: spc_new()
            }
        }
    }

    pub fn load_spc(&mut self, data: &[u8]) {
        unsafe {
            spc_load_spc(self.handle, data.as_ptr(), data.len() as c_int);
        }
    }

    pub fn clear_echo(&mut self) {
        unsafe {
            spc_clear_echo(self.handle);
        }
    }

    pub fn play(&mut self, count: u32, out: &mut [i16]) {
        unsafe {
            // TODO: check that out is big enough :)
            spc_play(self.handle, count as c_int, out.as_mut_ptr());
        }
    }
}

#[test]
fn can_call_unsafe_api_without_exploding() {
    unsafe {
        let mut spc = spc_new();
        spc_delete(spc);
    }
}

#[test]
fn can_use_safe_wrapper_without_being_stabbed() {
    let mut spc = SnesSpc::new();
    spc.clear_echo();
    // Drop it!
}
<|endoftext|>


<commit_before>/// A Single-Producer, Multiple-Consumer queue.

use std::sync::mpsc::{channel, Receiver, RecvError, Sender, SendError};
use std::sync::{Arc, RwLock, RwLockReadGuard};
use std::fmt;
use std::any::Any;
use std::error::Error;

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum BroadcastError<T> {
    SendError(T),
    RecvError,
}

impl<T: fmt::Display> fmt::Display for BroadcastError<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            BroadcastError::SendError(ref t) =>
                write!(fmt, "could not send data on channel: {}", t),
            BroadcastError::RecvError =>
                write!(fmt, "could not receive data on channel"),
        }
    }
}

impl<T: Send + fmt::Display + fmt::Debug + Any> Error for BroadcastError<T> {
    fn description(&self) -> &str {
        match *self {
            BroadcastError::SendError(_) => "could not send data on channel",
            BroadcastError::RecvError => "could not receive data on channel",
        }
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl<T> From<SendError<T>> for BroadcastError<T> {
    fn from(err: SendError<T>) -> BroadcastError<T> {
        let SendError(data) = err;
        BroadcastError::SendError(data)
    }
}

impl<T> From<RecvError> for BroadcastError<T> {
    fn from(_err: RecvError) -> BroadcastError<T> {
        BroadcastError::RecvError
    }
}

pub struct Broadcast<T> {
    inner: Arc<Inner<T>>,
}

impl<T: Clone> Broadcast<T> {
    pub fn send(&self, data: T) -> Result<(), BroadcastError<T>> {
        let guard = self.inner.read_senders();
        for s in guard.iter() {
            try!(s.send(data.clone()));
        }

        Ok(())
    }
}

struct Inner<T> {
    senders: RwLock<Vec<Sender<T>>>,
}

impl<T> Inner<T> {
    fn read_senders<'a>(&'a self) -> RwLockReadGuard<'a, Vec<Sender<T>>> {
        self.senders.read().unwrap()
    }

    fn add_sender(&self, sender: Sender<T>) {
        let mut vec = self.senders.write().unwrap();
        vec.push(sender);
    }
}

pub struct Consumer<T> {
    inner: Arc<Inner<T>>,
    receiver: Receiver<T>,
}

impl<T> Consumer<T> {
    fn recv(&self) -> Result<T, BroadcastError<T>> {
        let data = try!(self.receiver.recv());
        Ok(data)
    }
}

impl<T> Clone for Consumer<T> {
    fn clone(&self) -> Self {
        let (s, r) = channel();
        self.inner.add_sender(s);
        Consumer {
            inner: self.inner.clone(),
            receiver: r,
        }
    }
}

pub fn broadcast_channel<T: Clone>() -> (Broadcast<T>, Consumer<T>) {
    let (b, c) = channel();
    let inner = Arc::new(Inner { senders: RwLock::new(vec!(b)) });
    let broadcast = Broadcast { inner: inner.clone() };
    let consumer = Consumer { inner: inner, receiver: c };
    (broadcast, consumer)
}

#[cfg(test)]
mod test {
    use broadcast_channel;
    use super::Inner;

    use std::sync::{Arc, RwLock};
    use std::sync::mpsc::{channel};

    #[test]
    fn inner_iterator() {
        let (s1, r1) = channel();
        let (s2, r2) = channel();
        let inner = Arc::new(Inner { senders: RwLock::new(vec!(s1, s2)) });
        let guard = inner.read_senders();
        for s in guard.iter() {
            assert!(s.send(10u8).is_ok());
        }

        assert_eq!(r1.recv().unwrap(), 10u8);
        assert_eq!(r2.recv().unwrap(), 10u8);
    }

    #[test]
    fn sends_to_multiple_consumers() {
        let (p, c) = broadcast_channel();
        let c2 = c.clone();

        let res = p.send(9u8);
        assert!(res.is_ok());

        let res = c.recv();
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), 9u8);

        let res = c2.recv();
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), 9u8)
    }
}
<commit_msg>Enable sending Broadcast and Consumer to multiple threads<commit_after>/// A Single-Producer, Multiple-Consumer queue.

use std::sync::mpsc::{channel, Receiver, RecvError, Sender, SendError};
use std::sync::{Arc, RwLock, RwLockReadGuard};
use std::fmt;
use std::any::Any;
use std::error::Error;

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum BroadcastError<T> {
    SendError(T),
    RecvError,
}

impl<T: fmt::Display> fmt::Display for BroadcastError<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            BroadcastError::SendError(ref t) =>
                write!(fmt, "could not send data on channel: {}", t),
            BroadcastError::RecvError =>
                write!(fmt, "could not receive data on channel"),
        }
    }
}

impl<T: Send + fmt::Display + fmt::Debug + Any> Error for BroadcastError<T> {
    fn description(&self) -> &str {
        match *self {
            BroadcastError::SendError(_) => "could not send data on channel",
            BroadcastError::RecvError => "could not receive data on channel",
        }
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl<T> From<SendError<T>> for BroadcastError<T> {
    fn from(err: SendError<T>) -> BroadcastError<T> {
        let SendError(data) = err;
        BroadcastError::SendError(data)
    }
}

impl<T> From<RecvError> for BroadcastError<T> {
    fn from(_err: RecvError) -> BroadcastError<T> {
        BroadcastError::RecvError
    }
}

pub struct Broadcast<T> {
    inner: Arc<Inner<T>>,
}

impl<T: Clone> Broadcast<T> {
    pub fn send(&self, data: T) -> Result<(), BroadcastError<T>> {
        let guard = self.inner.read_senders();
        for s in guard.iter() {
            try!(s.send(data.clone()));
        }

        Ok(())
    }
}

// We implement Send/Sync here since we guarantee that the Sender<T>s in the
// vec only have `send()` called by the Broadcast struct. We need sync in order
// to share the vector with the Consumer to add senders too.
//
// TODO: Is there a way to not need to implement these traits?
//
// The same trait bounds on T are used here as in RwLock.
unsafe impl<T: Sync + Send + ?Sized> Sync for Inner<T> {}
unsafe impl<T: Sync + Send + ?Sized> Send for Inner<T> {}
struct Inner<T> {
    senders: RwLock<Vec<Sender<T>>>,
}

impl<T> Inner<T> {
    // This should only be called by Broadcast. Something may or may not go
    // horriblely wrong if send() is called from multiple threads.
    //
    // TODO: Disallow Consumer from calling this.
    fn read_senders<'a>(&'a self) -> RwLockReadGuard<'a, Vec<Sender<T>>> {
        self.senders.read().unwrap()
    }

    fn add_sender(&self, sender: Sender<T>) {
        let mut vec = self.senders.write().unwrap();
        vec.push(sender);
    }
}

pub struct Consumer<T> {
    inner: Arc<Inner<T>>,
    receiver: Receiver<T>,
}

impl<T> Consumer<T> {
    fn recv(&self) -> Result<T, BroadcastError<T>> {
        let data = try!(self.receiver.recv());
        Ok(data)
    }
}

impl<T> Clone for Consumer<T> {
    fn clone(&self) -> Self {
        let (s, r) = channel();
        self.inner.add_sender(s);
        Consumer {
            inner: self.inner.clone(),
            receiver: r,
        }
    }
}

pub fn broadcast_channel<T: Clone>() -> (Broadcast<T>, Consumer<T>) {
    let (b, c) = channel();
    let inner = Arc::new(Inner { senders: RwLock::new(vec!(b)) });
    let broadcast = Broadcast { inner: inner.clone() };
    let consumer = Consumer { inner: inner, receiver: c };
    (broadcast, consumer)
}

#[cfg(test)]
mod test {
    use broadcast_channel;
    use super::Inner;

    use std::sync::{Arc, RwLock};
    use std::sync::mpsc::{channel};
    use std::thread::spawn;

    #[test]
    fn inner_iterator() {
        let (s1, r1) = channel();
        let (s2, r2) = channel();
        let inner = Arc::new(Inner { senders: RwLock::new(vec!(s1, s2)) });
        let guard = inner.read_senders();
        for s in guard.iter() {
            assert!(s.send(10u8).is_ok());
        }

        assert_eq!(r1.recv().unwrap(), 10u8);
        assert_eq!(r2.recv().unwrap(), 10u8);
    }

    #[test]
    fn sends_to_multiple_consumers() {
        let (p, c) = broadcast_channel();
        let c2 = c.clone();

        let res = p.send(9u8);
        assert!(res.is_ok());

        let res = c.recv();
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), 9u8);

        let res = c2.recv();
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), 9u8)
    }

    #[test]
    fn test_send_threads() {
        let (p, c1) = broadcast_channel();
        let c2 = c1.clone();

        let (s1, r1) = channel();
        let (s2, r2) = channel();

        let _thread = spawn(move || {
            assert_eq!(c1.recv().unwrap(), 9u8);
            s1.send(10u8).unwrap();
        });

        let _thread = spawn(move || {
            assert_eq!(c2.recv().unwrap(), 9u8);
            s2.send(10u8).unwrap();
        });

        assert!(p.send(9u8).is_ok());
        assert!(r1.recv().is_ok());
        assert!(r2.recv().is_ok());
    }
}
<|endoftext|>


<commit_before>pub fn primefactors(n: isize) -> Vec<isize> {
    let mut number = n;
    let mut factors = Vec::new();
    if number % 2 == 0 {
        factors.push(2);
        number = number / 2;
    }

    let mut factor = 3;
    let upperlimit = (n as f64).sqrt() as isize + 2;
    while factor <= upperlimit {
        if number % factor == 0 {
            factors.push(factor);
            number = number / factor;
        }
        factor += 2;
    }

    factors
}

#[test]
fn test_primefactors() {
    assert!(primefactors(10) == [2, 5]);
    assert!(primefactors(13195) == [5,7,13,29]);
}
<commit_msg>allow sqrt impl<commit_after>pub fn primefactors(n: isize) -> Vec<isize> {
    let mut number = n;
    let mut factors = Vec::new();
    if number % 2 == 0 {
        factors.push(2);
        number = number / 2;
    }

    let mut factor = 3;
    let upperlimit = (n as f64).sqrt() as isize + 2;
    while factor <= upperlimit {
        if number % factor == 0 {
            factors.push(factor);
            number = number / factor;
        }
        factor += 2;
    }

    factors
}

fn find_root(a: f64, x: f64, epsilon: f64) -> f64 {
    let nextx = (a/x + x) / 2.0;
    if (x-nextx).abs() < epsilon*x {
        nextx
    }
    else {
        find_root(a, nextx, epsilon)
    }
}

pub fn sqrt(n: f64) -> f64 {
    find_root(n, 2.0, 1.0e-40_f64)
}

#[test]
fn test_sqrt() {
    assert!(sqrt(4.0) == 2.0);
}

#[test]
fn test_primefactors() {
    assert!(primefactors(10) == [2, 5]);
    assert!(primefactors(13195) == [5,7,13,29]);
}
<|endoftext|>