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

// Implements a Quadtree data structure to keep track of which tiles have
// been rasterized and which have not.

use geom::point::Point2D;

pub struct Quadtree<T> {
    tile: Option<T>,
    origin: Point2D<f32>,
    size: f32,
    quadrants: [Option<~Quadtree<T>>, ..4],
    scale: @mut f32,
    max_tile_size: uint,
}

priv enum Quadrant {
    TL = 0,
    TR = 1,
    BL = 2,
    BR = 3,
}

impl<T> Quadtree<T> {
    // Public method to create a new Quadtree
    pub fn new(x: uint, y: uint, width: uint, height: uint, tile_size: uint, scale: @mut f32) -> Quadtree<T> {
        if(*scale != 1.0) {
            println("Warning: Quadtree: Quadtree initialized while zoomed; this action is unsupported.");
            println("Please set zoom to 1.0 before creating the Quadtree.");
        }

        // Spaces must be squares and powers of 2, so expand the space until it is
        let longer = width.max(&height);
        let num_tiles = uint::div_ceil(longer, tile_size);
        let power_of_two = uint::next_power_of_two(num_tiles);
        let size = power_of_two * tile_size;

        Quadtree {
            tile: None,
            origin: Point2D(x as f32, y as f32),
            size: size as f32,
            quadrants: [None, None, None, None],
            scale: scale,
            max_tile_size: tile_size,
        }
    }

    // Private method to create new children
    fn new_child(&self, x: f32, y: f32, size: f32) -> Quadtree<T> {
        Quadtree {
            tile: None,
            origin: Point2D(x, y),
            size: size,
            quadrants: [None, None, None, None],
            scale: self.scale,
            max_tile_size: self.max_tile_size,
        }
    }

    /// Determine which child contains a given point
    fn get_quadrant(&self, x: uint, y: uint) -> Quadrant {
        let self_x = (self.origin.x * *(self.scale)).ceil() as uint;
        let self_y = (self.origin.y * *(self.scale)).ceil() as uint;
        let self_size = (self.size * *(self.scale)).ceil() as uint;

        if x < self_x + self_size / 2 {
            if y < self_y + self_size / 2 {
                TL
            } else {
                BL
            }
        } else if y < self_y + self_size / 2 {
            TR
        } else {
            BR
        }
    }

    /// Get the lowest-level (highest resolution) tile associated with a certain pixel
    pub fn get_tile<'r> (&'r self, x: uint, y: uint) -> &'r Option<T> {
        let self_x = (self.origin.x * *(self.scale)).ceil() as uint;
        let self_y = (self.origin.y * *(self.scale)).ceil() as uint;
        let self_size = (self.size * *(self.scale)).ceil() as uint;

        if x >= self_x + self_size || x < self_x
            || y >= self_y + self_size || y < self_y {
            fail!("Quadtree: Tried to get a tile outside of range");
        }

        let index = self.get_quadrant(x,y) as int;
        match self.quadrants[index] {
            None => &'r self.tile,
            Some(ref child) => child.get_tile(x, y),
        }
    }

    /// Add a tile
    pub fn add_tile(&mut self, x: uint, y: uint, tile: T) {
        let self_x = (self.origin.x * *(self.scale)).ceil() as uint;
        let self_y = (self.origin.y * *(self.scale)).ceil() as uint;
        let self_size = (self.size * *(self.scale)).ceil() as uint;

        debug!("Quadtree: Adding: (%?, %?) size:%?px", self_x, self_y, self_size);

        if x >= self_x + self_size || x < self_x
            || y >= self_y + self_size || y < self_y {
            fail!("Quadtree: Tried to add tile to invalid region");
        }

        if self_size <= self.max_tile_size { // We are the child
            self.tile = Some(tile);
            for vec::each([TL, TR, BL, BR]) |quad| {
                self.quadrants[*quad as int] = None;
            }
        } else { //send tile to children
            let quad = self.get_quadrant(x, y);
            match self.quadrants[quad as int] {
                Some(ref mut child) => child.add_tile(x, y, tile),
                None => { //make new child
                    let new_size = self.size / 2.0;
                    let new_x = match quad {
                        TL | BL => self.origin.x,
                        TR | BR => self.origin.x + new_size,
                    };
                    let new_y = match quad {
                        TL | TR => self.origin.y,
                        BL | BR => self.origin.y + new_size,
                    };
                    let mut c = ~self.new_child(new_x, new_y, new_size);
                    c.add_tile(x, y, tile);
                    self.quadrants[quad as int] = Some(c);

                    // If we have 4 children, we probably shouldn't be hanging onto a tile
                    // Though this isn't always true if we have grandchildren
                    match self.quadrants {
                        [Some(_), Some(_), Some(_), Some(_)] => {
                            self.tile = None;
                        }
                        _ => {}
                    }

                }
            }
        }
    }

}

#[test]
fn test_add_tile() {
    let scale = @mut 1.0;
    let mut t = Quadtree::new(50, 30, 20, 20, 10, scale);
    assert!(t.get_tile(50, 30).is_none());
    t.add_tile(50, 30, 1);
    assert!(t.get_tile(50, 30).get() == 1);
    assert!(t.get_tile(59, 39).get() == 1);
    assert!(t.get_tile(60, 40).is_none());
    *scale = 2.0;
    assert!(t.get_tile(110, 70).get() == 1);
    t.add_tile(100, 60, 2);
    assert!(t.get_tile(109, 69).get() == 2);
    assert!(t.get_tile(110, 70).get() == 1);
}<commit_msg>Address pcwalton's comments<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/. */

// Implements a Quadtree data structure to keep track of which tiles have
// been rasterized and which have not.

use geom::point::Point2D;

/// Parent to all quadtree nodes. Stores variables needed at all levels. All method calls
/// at this level are in pixel coordinates.
pub struct Quadtree<T> {
    root: QuadtreeNode<T>,
    max_tile_size: uint,
}

/// A node in the tree. All method calls at this level are in page coordinates.
struct QuadtreeNode<T> {
    /// The tile belonging to this node. Note that parent nodes can have tiles.
    tile: Option<T>,
    /// The positiong of the node in page coordinates.
    origin: Point2D<f32>,
    /// The width and hight of the node in page coordinates.
    size: f32,
    /// The node's children.
    quadrants: [Option<~QuadtreeNode<T>>, ..4],
}

priv enum Quadrant {
    TL = 0,
    TR = 1,
    BL = 2,
    BR = 3,
}

impl<T> Quadtree<T> {
    /// Public method to create a new Quadtree
    pub fn new(x: uint, y: uint, width: uint, height: uint, tile_size: uint) -> Quadtree<T> {
        // Spaces must be squares and powers of 2, so expand the space until it is
        let longer = width.max(&height);
        let num_tiles = uint::div_ceil(longer, tile_size);
        let power_of_two = uint::next_power_of_two(num_tiles);
        let size = power_of_two * tile_size;

        Quadtree {
            root: QuadtreeNode {
                tile: None,
                origin: Point2D(x as f32, y as f32),
                size: size as f32,
                quadrants: [None, None, None, None],
            },
            max_tile_size: tile_size,
        }
    }

    /// Get a tile at a given pixel position and scale.
    pub fn get_tile<'r>(&'r self, x: uint, y: uint, scale: f32) -> &'r Option<T> {
        self.root.get_tile(x as f32 / scale, y as f32 / scale)
    }
    /// Add a tile associtated with a given pixel position and scale.
    pub fn add_tile(&mut self, x: uint, y: uint, scale: f32, tile: T) {
        self.root.add_tile(x as f32 / scale, y as f32 / scale, tile, self.max_tile_size as f32 / scale);
    }

}

impl<T> QuadtreeNode<T> {
    // Private method to create new children
    fn new_child(x: f32, y: f32, size: f32) -> QuadtreeNode<T> {
        QuadtreeNode {
            tile: None,
            origin: Point2D(x, y),
            size: size,
            quadrants: [None, None, None, None],
        }
    }

    /// Determine which child contains a given point in page coords.
    fn get_quadrant(&self, x: f32, y: f32) -> Quadrant {
        if x < self.origin.x + self.size / 2.0 {
            if y < self.origin.y + self.size / 2.0 {
                TL
            } else {
                BL
            }
        } else if y < self.origin.y + self.size / 2.0 {
            TR
        } else {
            BR
        }
    }

    /// Get the lowest-level (highest resolution) tile associated with a given position in page coords.
    fn get_tile<'r> (&'r self, x: f32, y: f32) -> &'r Option<T> {
        if x >= self.origin.x + self.size || x < self.origin.x
            || y >= self.origin.y + self.size || y < self.origin.y {
            fail!("Quadtree: Tried to get a tile outside of range");
        }

        let index = self.get_quadrant(x, y) as int;
        match self.quadrants[index] {
            None => &'r self.tile,
            Some(ref child) => child.get_tile(x, y),
        }
    }

    /// Add a tile associated with a given position in page coords. If the tile size exceeds the maximum,
    /// the node will be split and the method will recurse until the tile size is within limits.
    fn add_tile(&mut self, x: f32, y: f32, tile: T, tile_size: f32) {
        debug!("Quadtree: Adding: (%?, %?) size:%?px", self.origin.x, self.origin.y, self.size);

        if x >= self.origin.x + self.size || x < self.origin.x
            || y >= self.origin.y + self.size || y < self.origin.y {
            fail!("Quadtree: Tried to add tile to invalid region");
        }

        if self.size <= tile_size { // We are the child
            self.tile = Some(tile);
            for vec::each([TL, TR, BL, BR]) |quad| {
                self.quadrants[*quad as int] = None;
            }
        } else { //send tile to children
            let quad = self.get_quadrant(x, y);
            match self.quadrants[quad as int] {
                Some(ref mut child) => child.add_tile(x, y, tile, tile_size),
                None => { //make new child
                    let new_size = self.size / 2.0;
                    let new_x = match quad {
                        TL | BL => self.origin.x,
                        TR | BR => self.origin.x + new_size,
                    };
                    let new_y = match quad {
                        TL | TR => self.origin.y,
                        BL | BR => self.origin.y + new_size,
                    };
                    let mut c = ~QuadtreeNode::new_child(new_x, new_y, new_size);
                    c.add_tile(x, y, tile, tile_size);
                    self.quadrants[quad as int] = Some(c);

                    // If we have 4 children, we probably shouldn't be hanging onto a tile
                    // Though this isn't always true if we have grandchildren
                    match self.quadrants {
                        [Some(_), Some(_), Some(_), Some(_)] => {
                            self.tile = None;
                        }
                        _ => {}
                    }

                }
            }
        }
    }
}

#[test]
fn test_add_tile() {
    let mut t = Quadtree::new(50, 30, 20, 20, 10);
    assert!(t.get_tile(50, 30, 1.0).is_none());
    t.add_tile(50, 30, 1.0, 1);
    assert!(t.get_tile(50, 30, 1.0).get() == 1);
    assert!(t.get_tile(59, 39, 1.0).get() == 1);
    assert!(t.get_tile(60, 40, 1.0).is_none());
    assert!(t.get_tile(110, 70, 2.0).get() == 1);
    t.add_tile(100, 60, 2.0, 2);
    assert!(t.get_tile(109, 69, 2.0).get() == 2);
    assert!(t.get_tile(110, 70, 2.0).get() == 1);
}<|endoftext|>


<commit_before>//! The Rust parser and macro expander.
//!
//! # Note
//!
//! This API is completely unstable and subject to change.

#![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
#![feature(box_syntax)]
#![feature(const_fn)] // For the `transmute` in `P::new`
#![feature(const_panic)]
#![feature(crate_visibility_modifier)]
#![feature(label_break_value)]
#![feature(nll)]
#![feature(or_patterns)]
#![recursion_limit = "256"]

#[macro_use]
extern crate rustc_macros;

#[macro_export]
macro_rules! unwrap_or {
    ($opt:expr, $default:expr) => {
        match $opt {
            Some(x) => x,
            None => $default,
        }
    };
}

pub mod util {
    pub mod classify;
    pub mod comments;
    pub mod lev_distance;
    pub mod literal;
    pub mod parser;
}

pub mod ast;
pub mod attr;
pub mod crate_disambiguator;
pub mod entry;
pub mod expand;
pub mod mut_visit;
pub mod node_id;
pub mod ptr;
pub mod token;
pub mod tokenstream;
pub mod visit;

pub use self::ast::*;

use rustc_data_structures::stable_hasher::{HashStable, StableHasher};

/// Requirements for a `StableHashingContext` to be used in this crate.
/// This is a hack to allow using the `HashStable_Generic` derive macro
/// instead of implementing everything in librustc_middle.
pub trait HashStableContext: rustc_span::HashStableContext {
    fn hash_attr(&mut self, _: &ast::Attribute, hasher: &mut StableHasher);
}

impl<AstCtx: crate::HashStableContext> HashStable<AstCtx> for ast::Attribute {
    fn hash_stable(&self, hcx: &mut AstCtx, hasher: &mut StableHasher) {
        hcx.hash_attr(self, hasher)
    }
}
<commit_msg>Add `#![feature(const_fn_transmute)]` to `rustc_ast`<commit_after>//! The Rust parser and macro expander.
//!
//! # Note
//!
//! This API is completely unstable and subject to change.

#![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
#![feature(box_syntax)]
#![feature(const_fn)] // For the `transmute` in `P::new`
#![feature(const_fn_transmute)]
#![feature(const_panic)]
#![feature(crate_visibility_modifier)]
#![feature(label_break_value)]
#![feature(nll)]
#![feature(or_patterns)]
#![recursion_limit = "256"]

#[macro_use]
extern crate rustc_macros;

#[macro_export]
macro_rules! unwrap_or {
    ($opt:expr, $default:expr) => {
        match $opt {
            Some(x) => x,
            None => $default,
        }
    };
}

pub mod util {
    pub mod classify;
    pub mod comments;
    pub mod lev_distance;
    pub mod literal;
    pub mod parser;
}

pub mod ast;
pub mod attr;
pub mod crate_disambiguator;
pub mod entry;
pub mod expand;
pub mod mut_visit;
pub mod node_id;
pub mod ptr;
pub mod token;
pub mod tokenstream;
pub mod visit;

pub use self::ast::*;

use rustc_data_structures::stable_hasher::{HashStable, StableHasher};

/// Requirements for a `StableHashingContext` to be used in this crate.
/// This is a hack to allow using the `HashStable_Generic` derive macro
/// instead of implementing everything in librustc_middle.
pub trait HashStableContext: rustc_span::HashStableContext {
    fn hash_attr(&mut self, _: &ast::Attribute, hasher: &mut StableHasher);
}

impl<AstCtx: crate::HashStableContext> HashStable<AstCtx> for ast::Attribute {
    fn hash_stable(&self, hcx: &mut AstCtx, hasher: &mut StableHasher) {
        hcx.hash_attr(self, hasher)
    }
}
<|endoftext|>


<commit_before>use ::{KeyType, ValueType};

use wal_file::KeyValuePair;

use std::iter::Peekable;
use std::collections::{BTreeMap, BTreeSet};
use std::collections::btree_map;
use std::collections::btree_set;

pub struct MultiMap<K: KeyType, V: ValueType> {
    multi_map: BTreeMap<K, BTreeSet<V>>
}

pub struct MultiMapIterator<'a, K: KeyType + 'a, V: ValueType + 'a> {
    // multi_map: MultiMap<K,V>, // the underlying multi map
    key_it: Peekable<btree_map::Iter<'a,K,BTreeSet<V>>>,
    value_it: &'a btree_set::Iter<'a,V>,
}

impl <'a, K: KeyType, V: ValueType> MultiMap<K,V> {
    pub fn new() -> MultiMap<K,V> {
        return MultiMap{multi_map: BTreeMap::<K,BTreeSet<V>>::new()};
    }
}

impl <'a, K: KeyType, V: ValueType> IntoIterator for &'a mut MultiMap<K,V> {
    type Item = KeyValuePair<K,V>;
    type IntoIter = MultiMapIterator<'a,K,V>;

    fn into_iter(self) -> Self::IntoIter {
        let mut key_it = self.multi_map.iter().peekable();
        let value_it = match key_it.peek() {
            Some(x) => &x.1.iter(),
            None => &BTreeSet::new().iter()
        };

        return MultiMapIterator{key_it: key_it, value_it: value_it};
    }
}

impl <'a, K: KeyType, V: ValueType> Iterator for MultiMapIterator<'a,K,V> {
    type Item = KeyValuePair<K,V>;

    fn next(&mut self) -> Option<Self::Item> {
        None
    }
}

<commit_msg>Another attempt at getting multi_map iterators working<commit_after>use ::{KeyType, ValueType};

use wal_file::KeyValuePair;

use std::iter::{Peekable, empty, Map};
use std::collections::{BTreeMap, BTreeSet};
use std::collections::btree_map;
use std::collections::btree_set;

pub struct MultiMap<K: KeyType, V: ValueType> {
    multi_map: BTreeMap<K, BTreeSet<V>>
}

pub struct MultiMapIterator<'a, K: KeyType + 'a, V: ValueType + 'a> {
    key_it: Peekable<btree_map::Iter<'a,K,BTreeSet<V>>>,
    value_it: btree_set::Iter<'a,V>,
}

impl <'a, K: KeyType, V: ValueType> MultiMap<K,V> {
    pub fn new() -> MultiMap<K,V> {
        return MultiMap{multi_map: BTreeMap::<K,BTreeSet<V>>::new()};
    }
}

impl <'a, K: KeyType, V: ValueType> IntoIterator for &'a mut MultiMap<K,V> {
    type Item = KeyValuePair<K,V>;
    type IntoIter = MultiMapIterator<'a,K,V>;

    fn into_iter(self) -> Self::IntoIter {
        let mut key_it = self.multi_map.iter().peekable();
        let value_it = match key_it.peek() {
            Some(&(k,v)) => v.iter(),
            None => empty::<btree_set::Iter<'a,V>>()
        };

        MultiMapIterator{key_it: key_it, value_it: value_it}
    }
}

impl <'a, K: KeyType, V: ValueType> Iterator for MultiMapIterator<'a,K,V> {
    type Item = KeyValuePair<K,V>;

    fn next(&mut self) -> Option<Self::Item> {
        None
    }
}

<|endoftext|>


<commit_before>//! Bindings to libgit2's raw git_strarray type

use std::ops::Deref;

use oid::Oid;
use raw;
use util::Binding;
use std::slice;
use std::mem;

/// An oid array structure used by libgit2
///
/// Some apis return arrays of oids which originate from libgit2. This
/// wrapper type behaves a little like `Vec<&Oid>` but does so without copying
/// the underlying Oids until necessary.
pub struct OidArray {
    raw: raw::git_oidarray,
}

impl OidArray {
    /// Returns None if i is out of bounds.
    pub fn get(&self, i: usize) -> Option<Oid> {
        if i < self.raw.count as usize {
            Some(self[i])
        } else {
            None
        }
    }
}

impl Deref for OidArray {
    type Target = [Oid];

    fn deref(&self) -> &[Oid] {
        unsafe {
            debug_assert_eq!(mem::size_of::<Oid>(), mem::size_of_val(&*self.raw.ids));

            slice::from_raw_parts(self.raw.ids as *const Oid, self.raw.count as usize)
        }
    }
}

impl Binding for OidArray {
    type Raw = raw::git_oidarray;
    unsafe fn from_raw(raw: raw::git_oidarray) -> OidArray {
        OidArray { raw: raw }
    }
    fn raw(&self) -> raw::git_oidarray { self.raw }
}

impl Drop for OidArray {
    fn drop(&mut self) {
        unsafe { raw::git_oidarray_free(&mut self.raw) }
    }
}
<commit_msg>replace get method with one provided by Deref<commit_after>//! Bindings to libgit2's raw git_strarray type

use std::ops::Deref;

use oid::Oid;
use raw;
use util::Binding;
use std::slice;
use std::mem;

/// An oid array structure used by libgit2
///
/// Some apis return arrays of oids which originate from libgit2. This
/// wrapper type behaves a little like `Vec<&Oid>` but does so without copying
/// the underlying Oids until necessary.
pub struct OidArray {
    raw: raw::git_oidarray,
}

impl Deref for OidArray {
    type Target = [Oid];

    fn deref(&self) -> &[Oid] {
        unsafe {
            debug_assert_eq!(mem::size_of::<Oid>(), mem::size_of_val(&*self.raw.ids));

            slice::from_raw_parts(self.raw.ids as *const Oid, self.raw.count as usize)
        }
    }
}

impl Binding for OidArray {
    type Raw = raw::git_oidarray;
    unsafe fn from_raw(raw: raw::git_oidarray) -> OidArray {
        OidArray { raw: raw }
    }
    fn raw(&self) -> raw::git_oidarray { self.raw }
}

impl Drop for OidArray {
    fn drop(&mut self) {
        unsafe { raw::git_oidarray_free(&mut self.raw) }
    }
}
<|endoftext|>


<commit_before>use std::f64;
use std::ops::{Add, Sub, Mul, Div};

#[derive(Clone, Copy)]
pub enum Parameter {
    Fixed(f64),
    Exponential {
        init: f64,
        floor: f64,
        count: u32,
        decay: f64,
    },
    Polynomial {
        init: f64,
        floor: f64,
        count: u32,
        exponent: f64,
    }
}

impl Parameter {
    pub fn fixed(value: f64) -> Parameter {
        Parameter::Fixed(value)
    }

    pub fn exponential(init: f64, decay: f64, floor: f64) -> Parameter {
        Parameter::Exponential {
            init: init,
            floor: floor,
            count: 0,
            decay: decay,
        }
    }

    pub fn polynomial(init: f64, exponent: f64, floor: f64) -> Parameter {
        Parameter::Polynomial {
            init: init,
            floor: floor,
            count: 0,
            exponent: exponent,
        }
    }

    pub fn value(&self) -> f64 {
        match self {
            &Parameter::Fixed(v) => v,

            &Parameter::Exponential {
                init: i, floor: f, count: c, decay: d
            } => f64::max(i * d.powf(c as f64), f),

            &Parameter::Polynomial {
                init: i, floor: f, count: c, exponent: e
            } => f64::max(i * (c as f64).powf(e), f),
        }
    }

    pub fn to_fixed(self) -> Parameter {
        Parameter::Fixed(self.value())
    }

    pub fn step(self) -> Parameter {
        match self {
            Parameter::Fixed(_) => self,
            Parameter::Exponential {
                init: i, floor: f, count: c, decay: d
            } => Parameter::Exponential {
                init: i,
                floor: f,
                count: c + 1,
                decay: d,
            },
            Parameter::Polynomial {
                init: i, floor: f, count: c, exponent: e
            } => Parameter::Polynomial {
                init: i,
                floor: f,
                count: c + 1,
                exponent: e,
            },
        }
    }

    pub fn back(self) -> Parameter {
        match self {
            Parameter::Fixed(_) => self,
            Parameter::Exponential {
                init: i, floor: f, count: c, decay: d
            } => Parameter::Exponential {
                init: i,
                floor: f,
                count: c - 1,
                decay: d,
            },
            Parameter::Polynomial {
                init: i, floor: f, count: c, exponent: e
            } => Parameter::Polynomial {
                init: i,
                floor: f,
                count: c - 1,
                exponent: e,
            },
        }
    }
}

impl Into<Parameter> for f64 {
    fn into(self) -> Parameter {
        Parameter::Fixed(self)
    }
}

macro_rules! impl_op {
    ($name: ident, $num_type: ty, $fn_name: ident, $op: tt) => {
        impl $name<$num_type> for Parameter {
            type Output = $num_type;

            fn $fn_name(self, other: $num_type) -> $num_type {
                self.value() $op other
            }
        }

        impl $name<Parameter> for $num_type {
            type Output = $num_type;

            fn $fn_name(self, other: Parameter) -> $num_type {
                self $op other.value()
            }
        }

        impl $name<Parameter> for Parameter {
            type Output = $num_type;

            fn $fn_name(self, other: Parameter) -> $num_type {
                self.value() $op other.value()
            }
        }
    }
}

impl_op!(Add, f64, add, +);
impl_op!(Sub, f64, sub, -);
impl_op!(Mul, f64, mul, *);
impl_op!(Div, f64, div, /);

// TODO: Add tests
<commit_msg>Added tests for Parameter<commit_after>use std::f64;
use std::cmp::max;
use std::ops::{Add, Sub, Mul, Div};

#[derive(Clone, Copy)]
pub enum Parameter {
    Fixed(f64),
    Exponential {
        init: f64,
        floor: f64,
        count: u32,
        decay: f64,
    },
    Polynomial {
        init: f64,
        floor: f64,
        count: u32,
        exponent: f64,
    }
}

impl Parameter {
    pub fn fixed(value: f64) -> Parameter {
        Parameter::Fixed(value)
    }

    pub fn exponential(init: f64, floor: f64, decay: f64) -> Parameter {
        Parameter::Exponential {
            init: init,
            floor: floor,
            count: 0,
            decay: decay,
        }
    }

    pub fn polynomial(init: f64, floor: f64, exponent: f64) -> Parameter {
        Parameter::Polynomial {
            init: init,
            floor: floor,
            count: 1,
            exponent: exponent,
        }
    }

    pub fn value(&self) -> f64 {
        match self {
            &Parameter::Fixed(v) => v,

            &Parameter::Exponential {
                init: i, floor: f, count: c, decay: d
            } => f64::max(i * d.powf(c as f64), f),

            &Parameter::Polynomial {
                init: i, floor: f, count: c, exponent: e
            } => f64::max(i / (c as f64).powf(e), f),
        }
    }

    pub fn to_fixed(self) -> Parameter {
        Parameter::Fixed(self.value())
    }

    pub fn step(self) -> Parameter {
        match self {
            Parameter::Fixed(_) => self,
            Parameter::Exponential {
                init: i, floor: f, count: c, decay: d
            } => Parameter::Exponential {
                init: i,
                floor: f,
                count: c.saturating_add(1),
                decay: d,
            },
            Parameter::Polynomial {
                init: i, floor: f, count: c, exponent: e
            } => Parameter::Polynomial {
                init: i,
                floor: f,
                count: c.saturating_add(1),
                exponent: e,
            },
        }
    }

    pub fn back(self) -> Parameter {
        match self {
            Parameter::Fixed(_) => self,
            Parameter::Exponential {
                init: i, floor: f, count: c, decay: d
            } => Parameter::Exponential {
                init: i,
                floor: f,
                count: c.saturating_sub(1),
                decay: d,
            },
            Parameter::Polynomial {
                init: i, floor: f, count: c, exponent: e
            } => Parameter::Polynomial {
                init: i,
                floor: f,
                count: max(1, c.saturating_sub(1)),
                exponent: e,
            },
        }
    }
}

impl Into<Parameter> for f64 {
    fn into(self) -> Parameter {
        Parameter::Fixed(self)
    }
}

macro_rules! impl_op {
    ($name: ident, $num_type: ty, $fn_name: ident, $op: tt) => {
        impl $name<$num_type> for Parameter {
            type Output = $num_type;

            fn $fn_name(self, other: $num_type) -> $num_type {
                self.value() $op other
            }
        }

        impl $name<Parameter> for $num_type {
            type Output = $num_type;

            fn $fn_name(self, other: Parameter) -> $num_type {
                self $op other.value()
            }
        }

        impl $name<Parameter> for Parameter {
            type Output = $num_type;

            fn $fn_name(self, other: Parameter) -> $num_type {
                self.value() $op other.value()
            }
        }
    }
}

impl_op!(Add, f64, add, +);
impl_op!(Sub, f64, sub, -);
impl_op!(Mul, f64, mul, *);
impl_op!(Div, f64, div, /);

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

    #[test]
    fn test_fixed() {
        let mut p = Parameter::fixed(1.0);

        assert_eq!(p.value(), 1.0);

        for _ in 0..1000 {
            p = p.step();
            assert_eq!(p.value(), 1.0);
        }

        for _ in 0..1000 {
            p = p.back();
            assert_eq!(p.value(), 1.0);
        }
    }

    #[test]
    fn test_exponential() {
        let mut p = Parameter::exponential(1.0, 0.5, 0.9);

        assert!((p.value() - 1.0).abs() < 1e-7);

        p = p.step();
        assert!((p.value() - 0.9).abs() < 1e-7);

        p = p.step();
        assert!((p.value() - 0.81).abs() < 1e-7);

        p = p.step();
        assert!((p.value() - 0.729).abs() < 1e-7);

        p = p.back();
        assert!((p.value() - 0.81).abs() < 1e-7);

        p = p.back();
        assert!((p.value() - 0.9).abs() < 1e-7);

        p = p.back();
        assert!((p.value() - 1.0).abs() < 1e-7);

        p = p.back();
        assert!((p.value() - 1.0).abs() < 1e-7);

        for _ in 0..1000 {
            p = p.step();
            assert!(p.value() >= 0.5);
        }

        assert!((p.value() - 0.5).abs() < 1e-7);
    }

    #[test]
    fn test_polynomial() {
        let mut p = Parameter::polynomial(1.0, 0.1, 0.6);

        assert!((p.value() - 1.0).abs() < 1e-7);

        p = p.step();
        assert!((p.value() - 0.659753955386447).abs() < 1e-7);

        p = p.step();
        assert!((p.value() - 0.517281857971786).abs() < 1e-7);

        p = p.step();
        assert!((p.value() - 0.435275281648062).abs() < 1e-7);

        p = p.back();
        assert!((p.value() - 0.517281857971786).abs() < 1e-7);

        p = p.back();
        assert!((p.value() - 0.659753955386447).abs() < 1e-7);

        p = p.back();
        assert!((p.value() - 1.0).abs() < 1e-7);

        p = p.back();
        assert!((p.value() - 1.0).abs() < 1e-7);

        for _ in 0..1000 {
            p = p.step();
            assert!(p.value() >= 0.1);
        }

        assert!((p.value() - 0.1).abs() < 1e-7);
    }

    #[test]
    fn test_to_fixed() {
        let mut p = Parameter::exponential(1.0, 0.5, 0.9);
        p = p.step().to_fixed();

        assert!((p.value() - 0.9).abs() < 1e-7);

        p = p.step().step().step().back().back();
        assert!((p.value() - 0.9).abs() < 1e-7);
    }
}
<|endoftext|>


<commit_before>use std::any::Any;
use std::ops::Deref;
use std::path::PathBuf;

use input::Input;
use output::Output;
use service::ServiceAccess;
use service::StaticServices;

use hyper::server::request::Request as HyperRequest;
use hyper::server::response::Response as HyperResponse;
use hyper::uri::RequestUri as HyperRequestUri;
use hyper::method::Method as HyperMethod;

pub struct Route {
    pub url: Pattern,
    pub method: MethodsMask,
    pub handler: Box<Handler + Send + Sync>,
}

impl Route {
    /// Returns the route parameters, or `Err` if this route can't handle the given request.
    pub fn matches(&self, request: &HyperRequest) -> Result<Box<Any>, ()> {
        if !self.method.matches(&request.method) {
            return Err(());
        }

        match request.uri {
            HyperRequestUri::AbsolutePath(ref p) => self.url.parse(p),
            _ => Err(())
        }
    }
}

/// Represents a URL pattern.
///
/// Contains a function that will return the route parameters, or `Err` if it doesn't match the
/// request's URL.
pub struct Pattern(pub Box<Fn(&str) -> Result<Box<Any>, ()> + Send + Sync>);

impl Pattern {
    /// Return `Err` if this pattern doesn't match the given URL, otherwise returns the
    /// route parameters.
    pub fn parse(&self, url: &str) -> Result<Box<Any>, ()> {
        (self.0)(url)
    }
}

/// Describes which methods must be used by the request for a route to be used.
pub struct MethodsMask {
    /// True if the `GET` method matches this mask.
    pub get: bool,
    /// True if the `POST` method matches this mask.
    pub post: bool,
    /// True if the `PUT` method matches this mask.
    pub put: bool,
    /// True if the `DELETE` method matches this mask.
    pub delete: bool,
}

impl MethodsMask {
    /// Parses from a string of the `route!` macro.
    pub fn parse(_: &str) -> MethodsMask {
        // FIXME:
        MethodsMask {
            get: true,
            post: false,
            put: false,
            delete: false,
        }
    }

    /// Returns true if the mask contains the specified method.
    pub fn matches(&self, method: &HyperMethod) -> bool {
        match method {
            &HyperMethod::Get => self.get,
            &HyperMethod::Post => self.post,
            &HyperMethod::Put => self.put,
            &HyperMethod::Delete => self.delete,
            _ => false
        }
    }
}

pub struct Router {
    /// List of the routes to try to match. They will be tried in this order.
    pub routes: Vec<Route>,
}

/// Describes types that can process a route.
pub trait Handler {
    /// Handles a request.
    fn call(&self, HyperRequest, HyperResponse, &StaticServices, route_params: &Box<Any>);
}

macro_rules! impl_handler {
    ($($p:ident),*) => (
        impl<'a, I, O $(, $p)*> Handler for fn(I $(, $p)*) -> O
                                            where I: Input, O: Output $(, $p: ServiceAccess<'a>)*
        {
            fn call(&self, request: HyperRequest, response: HyperResponse,
                    services: &StaticServices, route_params: &Box<Any>)
            {
                let input = match I::process(request) {
                    Ok(i) => i,
                    Err(_) => return        // TODO: handle properly
                };

                // TODO: Properly handling lifetimes here would require HKTs which are not
                //       supported by Rust. Considering that services are never destroyed, it's
                //       ok to cast their lifetime to whatever we want ; however there is a danger
                //       with route parameters and this should be fixed.
                $(
                    let $p = $p::load(unsafe { ::std::mem::transmute(services) },
                                      unsafe { ::std::mem::transmute(route_params) });
                )*

                let output = (*self)(input $(, $p)*);
                output.send(response, services);
            }
        }
    );
}

impl_handler!();
impl_handler!(S1);
impl_handler!(S1, S2);
impl_handler!(S1, S2, S3);
impl_handler!(S1, S2, S3, S4);
impl_handler!(S1, S2, S3, S4, S5);
impl_handler!(S1, S2, S3, S4, S5, S6);
impl_handler!(S1, S2, S3, S4, S5, S6, S7);
impl_handler!(S1, S2, S3, S4, S5, S6, S7, S8);
impl_handler!(S1, S2, S3, S4, S5, S6, S7, S8, S9);
impl_handler!(S1, S2, S3, S4, S5, S6, S7, S8, S9, S10);
impl_handler!(S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11);

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Params<'a, T: 'a>(&'a T);

impl<'a, T: 'a> ServiceAccess<'a> for Params<'a, T> where T: Any {
    fn load(_: &'a StaticServices, params: &'a Box<Any>) -> Params<'a, T> {
        Params(params.downcast_ref().unwrap())      // TODO: don't panic
    }
}

impl<'a, T> Deref for Params<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        self.0
    }
}

// TODO: fix the trailing '/' problem

#[macro_export]
macro_rules! router {
    (__parse_route $routes:ident [$($ex:tt)*] / $($t:tt)+) => (
        {
            let method = router!(__parse_method $($ex)*);
            router!(__parse_route2 $routes method [/] $($t)+)
        }
    );

    (__parse_route $routes:ident [$($ex:tt)*] $f:tt $($t:tt)*) => (
        router!(__parse_route $routes [$($ex)* $f] $($t)*)
    );

    (__parse_route $routes:ident []) => ();

    (__parse_route2 $routes:ident $method:ident [$($ex:tt)*] => $handler:expr, $($t:tt)*) => (
        {
            let pattern = router!(__parse_pattern $($ex)*);
            let handler = Box::new($handler) as Box<$crate::route::Handler + Send + Sync>;
            $routes.push($crate::route::Route {
                url: pattern,
                method: $method,
                handler: handler,
            });

            router!(__parse_route $routes [] $($t)*);
        }
    );

    (__parse_route2 $routes:ident $method:ident [$($ex:tt)*] => $handler:expr) => (
        router!(__parse_route2 $routes $method [$($ex)*] => $handler,)
    );

    (__parse_route2 $routes:ident $method:ident [$($ex:tt)*] $f:tt $($t:tt)*) => (
        router!(__parse_route2 $routes $method [$($ex)* $f] $($t)*)
    );

    (__parse_pattern $($t:tt)*) => (
        $crate::route::Pattern(Box::new(move |input| {
            router!(__parse_pattern_inner (input.trim_right_matches('/')) () $($t)*)
        }))
    );

    (__parse_pattern_inner ($input:expr) () [ $s:ident ]) => (
        {
            if $input.len() != 0 {
                return Err(());
            }

            Ok(Box::new($s))
        }
    );

    (__parse_pattern_inner ($input:expr) ($(, $mem:ident:$val:expr)+) [ $s:ident ]) => (
        {
            if $input.len() != 0 {
                return Err(());
            }

            Ok(Box::new($s {
                $(
                    $mem: match $val.parse() {
                        Ok(r) => r,
                        Err(_) => return Err(())
                    },
                )*
            }))
        }
    );

    (__parse_pattern_inner ($input:expr) ()) => (
        {
            if $input.len() != 0 {
                return Err(());
            }

            Ok(Box::new(()))
        }
    );

    (__parse_pattern_inner ($input:expr) ($($t:tt)*) / [ $s:ident ]) => (
        router!(__parse_pattern_inner ($input) ($($t)*) [$s])
    );

    (__parse_pattern_inner ($input:expr) ($($t:tt)*) /) => (
        router!(__parse_pattern_inner ($($t)*) ($input))
    );

    (__parse_pattern_inner ($input:expr) ($($e:tt)*) / { $val:ident } $($t:tt)*) => (
        {
            if !$input.starts_with('/') {
                return Err(());
            }

            let end = $input[1 ..].find('/').map(|p| p + 1).unwrap_or($input.len());
            let matched = &$input[1 .. end];

            router!(__parse_pattern_inner (&$input[end ..]) ($($e)* , $val: matched) $($t)*)
        }
    );

    (__parse_pattern_inner ($input:expr) ($($e:tt)*) / $val:ident $($t:tt)*) => (
        {
            let s = concat!("/", stringify!($val));
            if !$input.starts_with(s) {
                return Err(());
            }

            router!(__parse_pattern_inner (&$input[s.len() ..]) ($($e)*) $($t)*)
        }
    );

    (__parse_method $($t:tt)*) => (
        // TODO:
        $crate::route::MethodsMask { get: true, post: false, put: false, delete: false }
    );

    // main route
    ($($t:tt)+) => (
        {
            let mut routes = Vec::new();
            router!(__parse_route routes [] $($t)+);
            $crate::route::Router { routes: routes }
        }
    );
}
<commit_msg>Implement Handler for Box<Fn(...)><commit_after>use std::any::Any;
use std::ops::Deref;
use std::path::PathBuf;

use input::Input;
use output::Output;
use service::ServiceAccess;
use service::StaticServices;

use hyper::server::request::Request as HyperRequest;
use hyper::server::response::Response as HyperResponse;
use hyper::uri::RequestUri as HyperRequestUri;
use hyper::method::Method as HyperMethod;

pub struct Route {
    pub url: Pattern,
    pub method: MethodsMask,
    pub handler: Box<Handler + Send + Sync>,
}

impl Route {
    /// Returns the route parameters, or `Err` if this route can't handle the given request.
    pub fn matches(&self, request: &HyperRequest) -> Result<Box<Any>, ()> {
        if !self.method.matches(&request.method) {
            return Err(());
        }

        match request.uri {
            HyperRequestUri::AbsolutePath(ref p) => self.url.parse(p),
            _ => Err(())
        }
    }
}

/// Represents a URL pattern.
///
/// Contains a function that will return the route parameters, or `Err` if it doesn't match the
/// request's URL.
pub struct Pattern(pub Box<Fn(&str) -> Result<Box<Any>, ()> + Send + Sync>);

impl Pattern {
    /// Return `Err` if this pattern doesn't match the given URL, otherwise returns the
    /// route parameters.
    pub fn parse(&self, url: &str) -> Result<Box<Any>, ()> {
        (self.0)(url)
    }
}

/// Describes which methods must be used by the request for a route to be used.
pub struct MethodsMask {
    /// True if the `GET` method matches this mask.
    pub get: bool,
    /// True if the `POST` method matches this mask.
    pub post: bool,
    /// True if the `PUT` method matches this mask.
    pub put: bool,
    /// True if the `DELETE` method matches this mask.
    pub delete: bool,
}

impl MethodsMask {
    /// Parses from a string of the `route!` macro.
    pub fn parse(_: &str) -> MethodsMask {
        // FIXME:
        MethodsMask {
            get: true,
            post: false,
            put: false,
            delete: false,
        }
    }

    /// Returns true if the mask contains the specified method.
    pub fn matches(&self, method: &HyperMethod) -> bool {
        match method {
            &HyperMethod::Get => self.get,
            &HyperMethod::Post => self.post,
            &HyperMethod::Put => self.put,
            &HyperMethod::Delete => self.delete,
            _ => false
        }
    }
}

pub struct Router {
    /// List of the routes to try to match. They will be tried in this order.
    pub routes: Vec<Route>,
}

/// Describes types that can process a route.
pub trait Handler {
    /// Handles a request.
    fn call(&self, HyperRequest, HyperResponse, &StaticServices, route_params: &Box<Any>);
}

macro_rules! impl_handler {
    ($($p:ident),*) => (
        impl<'a, I, O $(, $p)*> Handler for fn(I $(, $p)*) -> O
                                            where I: Input, O: Output $(, $p: ServiceAccess<'a>)*
        {
            #[allow(non_snake_case)]
            fn call(&self, request: HyperRequest, response: HyperResponse,
                    services: &StaticServices, route_params: &Box<Any>)
            {
                let input = match I::process(request) {
                    Ok(i) => i,
                    Err(_) => return        // TODO: handle properly
                };

                // TODO: Properly handling lifetimes here would require HKTs which are not
                //       supported by Rust. Considering that services are never destroyed, it's
                //       ok to cast their lifetime to whatever we want ; however there is a danger
                //       with route parameters and this should be fixed.
                $(
                    let $p = $p::load(unsafe { ::std::mem::transmute(services) },
                                      unsafe { ::std::mem::transmute(route_params) });
                )*

                let output = (*self)(input $(, $p)*);
                output.send(response, services);
            }
        }

        impl<'a, I, O $(, $p)*> Handler for Box<Fn(I $(, $p)*) -> O>
                                            where I: Input, O: Output $(, $p: ServiceAccess<'a>)*
        {
            #[allow(non_snake_case)]
            fn call(&self, request: HyperRequest, response: HyperResponse,
                    services: &StaticServices, route_params: &Box<Any>)
            {
                let input = match I::process(request) {
                    Ok(i) => i,
                    Err(_) => return        // TODO: handle properly
                };

                // TODO: Properly handling lifetimes here would require HKTs which are not
                //       supported by Rust. Considering that services are never destroyed, it's
                //       ok to cast their lifetime to whatever we want ; however there is a danger
                //       with route parameters and this should be fixed.
                $(
                    let $p = $p::load(unsafe { ::std::mem::transmute(services) },
                                      unsafe { ::std::mem::transmute(route_params) });
                )*

                let output = (*self)(input $(, $p)*);
                output.send(response, services);
            }
        }
    );
}

impl_handler!();
impl_handler!(S1);
impl_handler!(S1, S2);
impl_handler!(S1, S2, S3);
impl_handler!(S1, S2, S3, S4);
impl_handler!(S1, S2, S3, S4, S5);
impl_handler!(S1, S2, S3, S4, S5, S6);
impl_handler!(S1, S2, S3, S4, S5, S6, S7);
impl_handler!(S1, S2, S3, S4, S5, S6, S7, S8);
impl_handler!(S1, S2, S3, S4, S5, S6, S7, S8, S9);
impl_handler!(S1, S2, S3, S4, S5, S6, S7, S8, S9, S10);
impl_handler!(S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11);

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Params<'a, T: 'a>(&'a T);

impl<'a, T: 'a> ServiceAccess<'a> for Params<'a, T> where T: Any {
    fn load(_: &'a StaticServices, params: &'a Box<Any>) -> Params<'a, T> {
        Params(params.downcast_ref().unwrap())      // TODO: don't panic
    }
}

impl<'a, T> Deref for Params<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        self.0
    }
}

// TODO: fix the trailing '/' problem

#[macro_export]
macro_rules! router {
    (__parse_route $routes:ident [$($ex:tt)*] / $($t:tt)+) => (
        {
            let method = router!(__parse_method $($ex)*);
            router!(__parse_route2 $routes method [/] $($t)+)
        }
    );

    (__parse_route $routes:ident [$($ex:tt)*] $f:tt $($t:tt)*) => (
        router!(__parse_route $routes [$($ex)* $f] $($t)*)
    );

    (__parse_route $routes:ident []) => ();

    (__parse_route2 $routes:ident $method:ident [$($ex:tt)*] => $handler:expr, $($t:tt)*) => (
        {
            let pattern = router!(__parse_pattern $($ex)*);
            let handler = Box::new($handler) as Box<$crate::route::Handler + Send + Sync>;
            $routes.push($crate::route::Route {
                url: pattern,
                method: $method,
                handler: handler,
            });

            router!(__parse_route $routes [] $($t)*);
        }
    );

    (__parse_route2 $routes:ident $method:ident [$($ex:tt)*] => $handler:expr) => (
        router!(__parse_route2 $routes $method [$($ex)*] => $handler,)
    );

    (__parse_route2 $routes:ident $method:ident [$($ex:tt)*] $f:tt $($t:tt)*) => (
        router!(__parse_route2 $routes $method [$($ex)* $f] $($t)*)
    );

    (__parse_pattern $($t:tt)*) => (
        $crate::route::Pattern(Box::new(move |input| {
            router!(__parse_pattern_inner (input.trim_right_matches('/')) () $($t)*)
        }))
    );

    (__parse_pattern_inner ($input:expr) () [ $s:ident ]) => (
        {
            if $input.len() != 0 {
                return Err(());
            }

            Ok(Box::new($s))
        }
    );

    (__parse_pattern_inner ($input:expr) ($(, $mem:ident:$val:expr)+) [ $s:ident ]) => (
        {
            if $input.len() != 0 {
                return Err(());
            }

            Ok(Box::new($s {
                $(
                    $mem: match $val.parse() {
                        Ok(r) => r,
                        Err(_) => return Err(())
                    },
                )*
            }))
        }
    );

    (__parse_pattern_inner ($input:expr) ()) => (
        {
            if $input.len() != 0 {
                return Err(());
            }

            Ok(Box::new(()))
        }
    );

    (__parse_pattern_inner ($input:expr) ($($t:tt)*) / [ $s:ident ]) => (
        router!(__parse_pattern_inner ($input) ($($t)*) [$s])
    );

    (__parse_pattern_inner ($input:expr) ($($t:tt)*) /) => (
        router!(__parse_pattern_inner ($($t)*) ($input))
    );

    (__parse_pattern_inner ($input:expr) ($($e:tt)*) / { $val:ident } $($t:tt)*) => (
        {
            if !$input.starts_with('/') {
                return Err(());
            }

            let end = $input[1 ..].find('/').map(|p| p + 1).unwrap_or($input.len());
            let matched = &$input[1 .. end];

            router!(__parse_pattern_inner (&$input[end ..]) ($($e)* , $val: matched) $($t)*)
        }
    );

    (__parse_pattern_inner ($input:expr) ($($e:tt)*) / $val:ident $($t:tt)*) => (
        {
            let s = concat!("/", stringify!($val));
            if !$input.starts_with(s) {
                return Err(());
            }

            router!(__parse_pattern_inner (&$input[s.len() ..]) ($($e)*) $($t)*)
        }
    );

    (__parse_method $($t:tt)*) => (
        // TODO:
        $crate::route::MethodsMask { get: true, post: false, put: false, delete: false }
    );

    // main route
    ($($t:tt)+) => (
        {
            let mut routes = Vec::new();
            router!(__parse_route routes [] $($t)+);
            $crate::route::Router { routes: routes }
        }
    );
}
<|endoftext|>


<commit_before>//!
//! # Scheduler
//!

use std::mem;
use std::sync::*;
use std::thread::*;
use std::sync::mpsc::*;
use std::collections::vec_deque::*;

lazy_static! {
    static ref SCHEDULER: Arc<Scheduler> = Arc::new(Scheduler::new());
}

///
/// Trait implemented by things that can be scheduled as a job
///
trait ScheduledJob : Send {
    /// Runs this particular job
    fn run(&mut self);
}

///
/// Basic job is just a FnOnce
///
struct Job<TFn>
where TFn: Send+FnOnce() -> () {
    action: Option<TFn>
}

impl<TFn> Job<TFn>
where TFn: Send+FnOnce() -> () {
    fn new(action: TFn) -> Job<TFn> {
        Job { action: Some(action) }
    }
}

impl<TFn> ScheduledJob for Job<TFn>
where TFn: Send+FnOnce() -> () {
    fn run(&mut self) {
        // Consume the action when it's run
        let mut action = None;
        mem::swap(&mut action, &mut self.action);

        if let Some(action) = action {
            action();
        } else {
            panic!("Cannot schedule an action twice");
        }
    }
}

///
/// The scheduler is used to schedule tasks onto a pool of threads
///
pub struct Scheduler {
    /// The queues that are active in the scheduler
    queues: Arc<Mutex<Vec<Weak<JobQueue>>>>,

    /// Active threads
    threads: Mutex<Vec<SchedulerThread>>
}

///
/// A job queue provides a list of jobs to perform in order
///
pub struct JobQueue {
    /// Jobs scheduled on this queue
    queue: Mutex<VecDeque<Box<ScheduledJob>>>,

    /// True while this queue is running
    running: Mutex<bool>
}

///
/// A scheduler thread reads from the scheduler queue
///
struct SchedulerThread {
    /// The jobs that this thread should run
    jobs: Sender<Box<ScheduledJob>>,

    /// The thread itself
    thread: JoinHandle<()>,

    /// Flag that indicates that this thread is busy
    busy: Arc<Mutex<bool>>
}

impl SchedulerThread {
    ///
    /// Creates a new scheduler thread
    ///
    fn new() -> SchedulerThread {
        // All the thread does is run jobs from its channel
        let (jobs_in, jobs_out): (Sender<Box<ScheduledJob>>, Receiver<Box<ScheduledJob>>) = channel();
        let thread = spawn(move || {
            while let Ok(mut job) = jobs_out.recv() {
                job.run();
            }
        });

        SchedulerThread {
            jobs:   jobs_in,
            thread: thread,
            busy:   Arc::new(Mutex::new(false))
        }
    }

    ///
    /// Schedules a job to be run on this thread
    ///
    fn run<Job: 'static+ScheduledJob>(&self, job: Job) {
        self.jobs.send(Box::new(job)).unwrap();
    }
}

impl JobQueue {
    ///
    /// Creates a new job queue
    ///
    fn new() -> JobQueue {
        JobQueue {
            queue:      Mutex::new(VecDeque::new()),
            running:    Mutex::new(false)
        }
    }

    ///
    /// Adds a new job to this queue, returns true if the queue is dormant and needs to be started
    ///
    fn queue<TJob: 'static+ScheduledJob>(&self, job: TJob) -> bool {
        let mut queue   = self.queue.lock().unwrap();
        let running     = self.running.lock().unwrap();

        queue.push_back(Box::new(job));

        !*running
    }

    ///
    /// If there are any jobs waiting, dequeues the next one
    ///
    fn dequeue(&self) -> Option<Box<ScheduledJob>> {
        let mut queue = self.queue.lock().unwrap();

        queue.pop_front()
    }

    ///
    /// Runs jobs on this queue until there are none left, marking the job as inactive when done
    ///
    fn drain(&self) {
        let mut done = false;

        while !done {
            // Run jobs until the queue is drained
            while let Some(mut job) = self.dequeue() {
                job.run();
            }

            // Mark as not running any more
            {
                let queue       = self.queue.lock().unwrap();
                let mut running = self.running.lock().unwrap();

                // If the queue is empty at the point where we obtain the 'running' lock, we can deactivate ourselves
                if queue.len() == 0 {
                    *running    = false;
                    done        = true;
                }
            }
        }
    }
}

impl Scheduler {
    ///
    /// Creates a new scheduler
    ///
    /// (There's only actually one scheduler)
    ///
    fn new() -> Scheduler {
        let result = Scheduler {
            queues:     Arc::new(Mutex::new(vec![])),
            threads:    Mutex::new(vec![])
        };

        result.spawn_thread();
        result.spawn_thread();
        result.spawn_thread();
        result.spawn_thread();

        result
    }

    ///
    /// Finds the next queue that should be run. If this returns successfully, the queue will
    /// be marked as running.
    ///
    fn next_to_run(queues: &Arc<Mutex<Vec<Weak<JobQueue>>>>) -> Option<Arc<JobQueue>> {
        // Search the queues...
        let queues = queues.lock().unwrap();

        // Find a queue where is_running is false
        for q in queues.iter() {
            // Queue is a weak ref, check that it's still in use
            if let Some(q) = q.upgrade() {
                // If the queue is not running, then mark it as running and return it
                let mut is_running = q.running.lock().unwrap();
                if !*is_running {
                    // Clone here is necessary because the is_running update is borrowing q
                    *is_running = true;
                    return Some(q.clone());
                }
            }
        }

        None
    }

    ///
    /// Attempts to schedule a task on a dormant thread
    ///
    fn schedule_dormant<TFn>(&self, job: TFn) -> bool
    where TFn: 'static+Send+FnOnce() -> () {
        let threads = self.threads.lock().unwrap();

        for thread in threads.iter() {
            let mut busy = thread.busy.lock().unwrap();

            if !*busy {
                let also_busy = thread.busy.clone();

                *busy = true;
                thread.run(Job::new(move || {
                    // Run the job
                    job();

                    // Thread is dormant again once this job completes
                    let mut busy = also_busy.lock().unwrap();
                    *busy = false;
                }));

                return true;
            }
        }

        // No dormant threads were found
        false
    }

    ///
    /// Wakes a thread to run a dormant queue. Returns true if a thread was woken up
    ///
    fn schedule_thread(&self) -> bool {
        // Find a dormant thread and activate it
        let queues = self.queues.clone();

        self.schedule_dormant(move || {
            // Run queues until there are no more to run, then become dormant again
            while let Some(work) = Self::next_to_run(&queues) {
                work.drain();
            }

            // TODO: if there are no dormant threads, there's a race here at the moment as this thread won't get rescheduled while it's 'dying'
        })
    }

    ///
    /// Spawns a thread in this scheduler
    ///
    pub fn spawn_thread(&self) {
        let new_thread = SchedulerThread::new();
        self.threads.lock().unwrap().push(new_thread);
    }

    ///
    /// Creates a new job queue for this scheduler
    ///
    pub fn create_job_queue(&self) -> Arc<JobQueue> {
        let new_queue = Arc::new(JobQueue::new());

        self.queues.lock().unwrap().push(Arc::downgrade(&new_queue));

        new_queue
    }

    ///
    /// Schedules a job on this scheduler
    ///
    pub fn async<TFn: 'static+Send+FnOnce() -> ()>(&self, queue: &Arc<JobQueue>, job: TFn) {
        if queue.queue(Job::new(job)) {
            // A true result indicates that the job was scheduled but the queue is not running. Try to schedule a thread if this occurs.
            self.schedule_thread();
        }
    }
}

///
/// Retrieves the global scheduler
///
pub fn scheduler<'a>() -> &'a Scheduler {
    &SCHEDULER
}

///
/// Creates a scheduler queue
///
pub fn queue() -> Arc<JobQueue> {
    scheduler().create_job_queue()
}

///
/// Creates a scheduler queue
///
pub fn async<TFn: 'static+Send+FnOnce() -> ()>(queue: &Arc<JobQueue>, job: TFn) {
    scheduler().async(queue, job)
}

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

    #[test]
    fn can_schedule_async() {
        let (tx, rx)    = channel();
        let queue       = queue();

        async(&queue, move || {
            tx.send(42).unwrap();
        });

        assert!(rx.recv().unwrap() == 42);
    }

    #[test]
    fn will_schedule_in_order() {
        let (tx, rx)    = channel();
        let queue       = queue();

        let (tx1, tx2)  = (tx.clone(), tx.clone());

        async(&queue, move || {
            sleep(Duration::from_millis(100));
            tx1.send(1).unwrap();
        });
        async(&queue, move || {
            tx2.send(2).unwrap();
        });

        assert!(rx.recv().unwrap() == 1);
        assert!(rx.recv().unwrap() == 2);
    }

    #[test]
    fn will_schedule_separate_queues_in_parallel() {
        let (tx, rx)        = channel();
        let queue1          = queue();
        let queue2          = queue();
        let queue2_has_run  = Arc::new(Mutex::new(false));

        let queue1_check = queue2_has_run.clone();

        async(&queue1, move || {
            // The other task needs to start within 100ms for this to work
            sleep(Duration::from_millis(100));
            tx.send(*queue1_check.lock().unwrap()).unwrap();
        });
        async(&queue2, move || {
            *queue2_has_run.lock().unwrap() = true;
        });

        assert!(rx.recv().unwrap() == true);
    }
}
<commit_msg>Fix race condition when shutting down a running thread<commit_after>//!
//! # Scheduler
//!

use std::mem;
use std::sync::*;
use std::thread::*;
use std::sync::mpsc::*;
use std::collections::vec_deque::*;

lazy_static! {
    static ref SCHEDULER: Arc<Scheduler> = Arc::new(Scheduler::new());
}

///
/// Trait implemented by things that can be scheduled as a job
///
trait ScheduledJob : Send {
    /// Runs this particular job
    fn run(&mut self);
}

///
/// Basic job is just a FnOnce
///
struct Job<TFn>
where TFn: Send+FnOnce() -> () {
    action: Option<TFn>
}

impl<TFn> Job<TFn>
where TFn: Send+FnOnce() -> () {
    fn new(action: TFn) -> Job<TFn> {
        Job { action: Some(action) }
    }
}

impl<TFn> ScheduledJob for Job<TFn>
where TFn: Send+FnOnce() -> () {
    fn run(&mut self) {
        // Consume the action when it's run
        let mut action = None;
        mem::swap(&mut action, &mut self.action);

        if let Some(action) = action {
            action();
        } else {
            panic!("Cannot schedule an action twice");
        }
    }
}

///
/// The scheduler is used to schedule tasks onto a pool of threads
///
pub struct Scheduler {
    /// The queues that are active in the scheduler
    queues: Arc<Mutex<Vec<Weak<JobQueue>>>>,

    /// Active threads
    threads: Mutex<Vec<SchedulerThread>>
}

///
/// A job queue provides a list of jobs to perform in order
///
pub struct JobQueue {
    /// Jobs scheduled on this queue
    queue: Mutex<VecDeque<Box<ScheduledJob>>>,

    /// True while this queue is running
    running: Mutex<bool>
}

///
/// A scheduler thread reads from the scheduler queue
///
struct SchedulerThread {
    /// The jobs that this thread should run
    jobs: Sender<Box<ScheduledJob>>,

    /// The thread itself
    thread: JoinHandle<()>,

    /// Flag that indicates that this thread is busy
    busy: Arc<Mutex<bool>>
}

impl SchedulerThread {
    ///
    /// Creates a new scheduler thread
    ///
    fn new() -> SchedulerThread {
        // All the thread does is run jobs from its channel
        let (jobs_in, jobs_out): (Sender<Box<ScheduledJob>>, Receiver<Box<ScheduledJob>>) = channel();
        let thread = spawn(move || {
            while let Ok(mut job) = jobs_out.recv() {
                job.run();
            }
        });

        SchedulerThread {
            jobs:   jobs_in,
            thread: thread,
            busy:   Arc::new(Mutex::new(false))
        }
    }

    ///
    /// Schedules a job to be run on this thread
    ///
    fn run<Job: 'static+ScheduledJob>(&self, job: Job) {
        self.jobs.send(Box::new(job)).unwrap();
    }
}

impl JobQueue {
    ///
    /// Creates a new job queue
    ///
    fn new() -> JobQueue {
        JobQueue {
            queue:      Mutex::new(VecDeque::new()),
            running:    Mutex::new(false)
        }
    }

    ///
    /// Adds a new job to this queue, returns true if the queue is dormant and needs to be started
    ///
    fn queue<TJob: 'static+ScheduledJob>(&self, job: TJob) -> bool {
        let mut queue   = self.queue.lock().unwrap();
        let running     = self.running.lock().unwrap();

        queue.push_back(Box::new(job));

        !*running
    }

    ///
    /// If there are any jobs waiting, dequeues the next one
    ///
    fn dequeue(&self) -> Option<Box<ScheduledJob>> {
        let mut queue = self.queue.lock().unwrap();

        queue.pop_front()
    }

    ///
    /// Runs jobs on this queue until there are none left, marking the job as inactive when done
    ///
    fn drain(&self) {
        let mut done = false;

        while !done {
            // Run jobs until the queue is drained
            while let Some(mut job) = self.dequeue() {
                job.run();
            }

            // Mark as not running any more
            {
                let queue       = self.queue.lock().unwrap();
                let mut running = self.running.lock().unwrap();

                // If the queue is empty at the point where we obtain the 'running' lock, we can deactivate ourselves
                if queue.len() == 0 {
                    *running    = false;
                    done        = true;
                }
            }
        }
    }
}

impl Scheduler {
    ///
    /// Creates a new scheduler
    ///
    /// (There's only actually one scheduler)
    ///
    fn new() -> Scheduler {
        let result = Scheduler {
            queues:     Arc::new(Mutex::new(vec![])),
            threads:    Mutex::new(vec![])
        };

        result.spawn_thread();
        result.spawn_thread();
        result.spawn_thread();
        result.spawn_thread();

        result
    }

    ///
    /// Finds the next queue that should be run. If this returns successfully, the queue will
    /// be marked as running.
    ///
    fn next_to_run(queues: &Arc<Mutex<Vec<Weak<JobQueue>>>>) -> Option<Arc<JobQueue>> {
        // Search the queues...
        let queues = queues.lock().unwrap();

        // Find a queue where is_running is false
        for q in queues.iter() {
            // Queue is a weak ref, check that it's still in use
            if let Some(q) = q.upgrade() {
                // If the queue is not running, then mark it as running and return it
                let mut is_running = q.running.lock().unwrap();
                if !*is_running {
                    // Clone here is necessary because the is_running update is borrowing q
                    *is_running = true;
                    return Some(q.clone());
                }
            }
        }

        None
    }

    ///
    /// Attempts to schedule a task on a dormant thread
    ///
    fn schedule_dormant<NextJob, RunJob, JobData>(&self, next_job: NextJob, job: RunJob) -> bool
    where RunJob: 'static+Send+Fn(JobData) -> (), NextJob: 'static+Send+Fn() -> Option<JobData> {
        let threads = self.threads.lock().unwrap();

        for thread in threads.iter() {
            let mut busy = thread.busy.lock().unwrap();

            if !*busy {
                let also_busy = thread.busy.clone();

                *busy = true;
                thread.run(Job::new(move || {
                    let mut done = false;

                    while !done {
                        // Obtain the next job
                        let job_data = {
                            let mut busy = also_busy.lock().unwrap();
                            let job_data = next_job();

                            // If there's no next job, then this thread is no longer busy
                            if job_data.is_none() {
                                *busy = false;
                            }

                            job_data
                        };

                        // Run the job if there is one, stop the thread if there is not
                        if let Some(job_data) = job_data {
                            job(job_data);
                        } else {
                            done = true;
                        }
                    }
                }));

                return true;
            }
        }

        // No dormant threads were found
        false
    }

    ///
    /// Wakes a thread to run a dormant queue. Returns true if a thread was woken up
    ///
    fn schedule_thread(&self) -> bool {
        // Find a dormant thread and activate it
        let queues = self.queues.clone();

        // Schedule work on this dormant thread
        self.schedule_dormant(move || Self::next_to_run(&queues), move |work| work.drain())
    }

    ///
    /// Spawns a thread in this scheduler
    ///
    pub fn spawn_thread(&self) {
        let new_thread = SchedulerThread::new();
        self.threads.lock().unwrap().push(new_thread);
    }

    ///
    /// Creates a new job queue for this scheduler
    ///
    pub fn create_job_queue(&self) -> Arc<JobQueue> {
        let new_queue = Arc::new(JobQueue::new());

        self.queues.lock().unwrap().push(Arc::downgrade(&new_queue));

        new_queue
    }

    ///
    /// Schedules a job on this scheduler
    ///
    pub fn async<TFn: 'static+Send+FnOnce() -> ()>(&self, queue: &Arc<JobQueue>, job: TFn) {
        if queue.queue(Job::new(job)) {
            // A true result indicates that the job was scheduled but the queue is not running. Try to schedule a thread if this occurs.
            self.schedule_thread();
        }
    }
}

///
/// Retrieves the global scheduler
///
pub fn scheduler<'a>() -> &'a Scheduler {
    &SCHEDULER
}

///
/// Creates a scheduler queue
///
pub fn queue() -> Arc<JobQueue> {
    scheduler().create_job_queue()
}

///
/// Creates a scheduler queue
///
pub fn async<TFn: 'static+Send+FnOnce() -> ()>(queue: &Arc<JobQueue>, job: TFn) {
    scheduler().async(queue, job)
}

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

    #[test]
    fn can_schedule_async() {
        let (tx, rx)    = channel();
        let queue       = queue();

        async(&queue, move || {
            tx.send(42).unwrap();
        });

        assert!(rx.recv().unwrap() == 42);
    }

    #[test]
    fn will_schedule_in_order() {
        let (tx, rx)    = channel();
        let queue       = queue();

        let (tx1, tx2)  = (tx.clone(), tx.clone());

        async(&queue, move || {
            sleep(Duration::from_millis(100));
            tx1.send(1).unwrap();
        });
        async(&queue, move || {
            tx2.send(2).unwrap();
        });

        assert!(rx.recv().unwrap() == 1);
        assert!(rx.recv().unwrap() == 2);
    }

    #[test]
    fn will_schedule_separate_queues_in_parallel() {
        let (tx, rx)        = channel();
        let queue1          = queue();
        let queue2          = queue();
        let queue2_has_run  = Arc::new(Mutex::new(false));

        let queue1_check = queue2_has_run.clone();

        async(&queue1, move || {
            // The other task needs to start within 100ms for this to work
            sleep(Duration::from_millis(100));
            tx.send(*queue1_check.lock().unwrap()).unwrap();
        });
        async(&queue2, move || {
            *queue2_has_run.lock().unwrap() = true;
        });

        assert!(rx.recv().unwrap() == true);
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::fmt;
use std::ptr;
use std::iter;

use rand::{thread_rng, Rng};

const DEFAULT_LEVEL: usize = 4;

type Link<T> = Option<Box<T>>;

#[allow(raw_pointer_derive)]
#[derive(Debug)]
struct Rawlink<T> {
    p: *mut T,
}

impl<T> Copy for Rawlink<T> {}
unsafe impl<T:Send> Send for Rawlink<T> {}
unsafe impl<T:Sync> Sync for Rawlink<T> {}

fn random_level() -> usize {
    let mut rng = thread_rng();
    let mut level = 0;
    loop {
        if rng.gen_weighted_bool(2) {
            level += 1;
            continue;
        }
        break;
    }

    level
}

#[derive(Debug)]
pub struct SkipNode<Key,E> {
    key: Key,
    it: E,
    next: Link<SkipNode<Key,E>>,
    prev: Rawlink<SkipNode<Key,E>>,
    // level 0 to DEFAULT_LEVEL
    forward: Vec<Rawlink<SkipNode<Key,E>>>,
}

impl<Key: PartialOrd, E> SkipNode<Key,E> {
    // level: 0 ~ DEFAULT_LEVEL
    fn new(key: Key, it: E, level: usize) -> SkipNode<Key,E> {
        SkipNode {
            key: key,
            it: it,
            next: None,
            prev: Rawlink::none(),
            forward: iter::repeat(Rawlink::none()).take(level).collect(),
        }
    }

    #[inline]
    fn level(&self) -> usize {
        self.forward.len()
    }

    fn to_ptr(&mut self) -> Rawlink<SkipNode<Key,E>> {
        Rawlink::some(self)
    }

    fn promote_level(&mut self, new_level: usize, forward: Vec<Rawlink<Self>>) {
        let level = self.level();
        for i in level .. new_level {
            self.forward.push(forward[i]);
        }
        assert!(self.level() == new_level, "promote_level()");
    }

    fn insert(&mut self, key: Key, it: E, level: usize) {
    }
}

pub struct SkipList<Key,E> {
    head: Link<SkipNode<Key,E>>,
    forward: Vec<Rawlink<SkipNode<Key,E>>>,
    level: usize,
    size: usize,
}

impl<Key: PartialOrd + fmt::Debug, E: fmt::Debug> SkipList<Key,E> {
    /// create new empty SkipList
    pub fn new() -> SkipList<Key, E> {
        SkipList {
            head: None,
            forward: iter::repeat(Rawlink::none()).take(DEFAULT_LEVEL).collect(),
            level: DEFAULT_LEVEL,
            size: 0,
        }
    }

    pub fn level(&self) -> usize {
        self.level
    }

    pub fn contains_key(&self, key: &Key) -> bool {
        self.find(key).is_some()
    }

    pub fn find(&self, key: &Key) -> Option<&E> {
        let level = self.level();
        let mut x = self.forward[level-1];
        for i in (0..level).rev() {
            while x.resolve().map_or(false, |n| n.forward[i].is_some()) &&
                x.resolve().map_or(false, |n| n.forward[i].resolve().unwrap().key < *key) {
                    let nx = x.resolve().map_or_else(Rawlink::none, |n| n.forward[i] );
                    x = nx;
                }
        }

        while x.resolve().map_or(false, |n| n.next.is_some()) &&
            x.resolve().map_or(false, |n| n.next.as_ref().unwrap().key < *key) {
                let nx = x.resolve_mut().map_or_else(Rawlink::none, |n| {
                    n.next.as_mut().map_or_else(Rawlink::none, |n| Rawlink::some(&mut **n))
                });
                x = nx
            }

        x.resolve().map_or(None, |n| {
            if n.key == *key {
                Some(&n.it)
            } else {
                None
            }
        })
    }

    fn adjust_head(&mut self, new_level: usize) {
        let diff = new_level - self.level;
        let head_link  = Rawlink::from(&mut self.head);
        let level = self.level();

        for i in level .. new_level {
            self.forward.push(head_link);
            self.head.as_mut().map(|n| n.forward.push(Rawlink::none()));
        }
        assert_eq!(self.forward.len(), new_level);
        assert_eq!(self.head.as_ref().map_or(new_level, |n| n.level()), new_level);
    }

    // Due to head node must be of same level as List,
    // inserting with decreasing order will lead to almost same bad performance as a linked list
    pub fn insert(&mut self, key: Key, it: E) {
        let mut new_level = random_level();
        if new_level > self.level { // new node will be deepest
            self.adjust_head(new_level);
            self.level = new_level;
        }
        self.size += 1;

        if self.head.is_none() {
            new_level = self.level;
            self.head = Some(Box::new(SkipNode::new(key, it, new_level)));
            let p = Rawlink::from(&mut self.head);
            for i in 0..new_level {
                self.forward[i] = p;
            }
        } else if self.head.as_ref().map_or(false, |n| n.key > key) {
            new_level = self.level;
            // insert at head
            let mut new_node = Some(Box::new(SkipNode::new(key, it, new_level)));
            let new_link = new_node.as_mut().map_or_else(Rawlink::none, |n| {
                Rawlink::some(&mut **n)
            });

            for i in 0..new_level {
                new_node.as_mut().map(|n| {
                    n.forward[i] = self.forward[i]
                });
            }

            for i in 0..new_level {
                self.forward[i] = new_link
            }

            new_node.as_mut().map(|n| n.next = self.head.take());
            self.head = new_node;
        } else {
            println!("crash0");

            let mut x = self.head.as_mut().map_or_else(Rawlink::none, |n| {
                Rawlink::some(&mut **n)
            });
            // insert normally
            let mut update: Vec<Rawlink<SkipNode<Key,E>>> = self.forward[..new_level].to_vec();
            if new_level > 0 {  // need to insert skip pointers
                println!("new level => {}", new_level);
                x = update[new_level-1];
                println!("crash2");
                for i in (0..new_level).rev() {
                    while x.resolve().map_or(false, |n| n.forward[i].is_some()) &&
                        x.resolve().map_or(false, |n| n.forward[i].resolve().unwrap().key < key) {
                            let nx = x.resolve().map_or_else(Rawlink::none, |n| n.forward[i] );
                            x = nx;
                        }
                    update[i] = x.resolve_mut().map_or_else(Rawlink::none, |n| {
                        Rawlink::some(&mut *n)
                    });
                }
            }

            println!("crash1");
            let mut y = x.resolve_mut().map_or_else(Rawlink::none, |n| {
                Rawlink::some(&mut *n)
            });
            // When head node level is lower than current
            if y.is_none() {
                println!("update => {:?}", update);
                y = self.head.as_mut().map_or_else(Rawlink::none, |n| {
                    Rawlink::some(&mut **n)
                });
            }
            while y.resolve().map_or(false, |n| n.next.is_some()) &&
                y.resolve().map_or(false, |n| n.next.as_ref().unwrap().key < key) {
                    let ny = y.resolve_mut().map_or_else(Rawlink::none, |n| {
                        n.next.as_mut().map_or_else(Rawlink::none, |n| Rawlink::some(&mut **n))
                    });
                    y = ny
                }
            assert!(y.is_some());
            // create node and insert
            let mut new_node = Some(Box::new(SkipNode::new(key, it, self.level)));
            let new_link = new_node.as_mut().map_or_else(Rawlink::none, |n| {
                Rawlink::some(&mut **n)
            });

            for i in 0..new_level {
                new_node.as_mut().map(|n| {
                    n.forward[i] = update[i].resolve_mut().map_or_else(Rawlink::none, |nx| {
                        nx.forward[i]
                    });
                });
                // if update is empty, then update head node's link
                update[i].resolve_mut().map_or_else(|| {
                    self.forward[i] = new_link;
                },
                    |prev| {
                    prev.forward[i] = new_link;
                });
            }

            // move in
            y.resolve_mut().map(|n| {
                new_node.as_mut().map(|new| {
                    new.next = n.next.take();
                });
                n.next = new_node;
            });
        }
    }

    pub fn remove(&mut self, key: &Key) -> Option<E> {
        if self.head.is_none() {
            return None;
        }
        let level = self.level();
        let mut x = self.forward[level-1];
        let mut left = x;

        for i in (0..level).rev() {
            while x.resolve().map_or(false, |n| n.forward[i].is_some()) &&
                x.resolve().map_or(false, |n| n.forward[i].resolve().unwrap().key < *key) {
                    let nx = x.resolve().map_or_else(Rawlink::none, |n| n.forward[i] );
                    x = nx;
                }
        }

        while x.resolve().map_or(false, |n| n.next.is_some()) &&
            x.resolve().map_or(false, |n| n.next.as_ref().unwrap().key < *key) {
                let nx = x.resolve_mut().map_or_else(Rawlink::none, |n| {
                    n.next.as_mut().map_or_else(Rawlink::none, |n| Rawlink::some(&mut **n))
                });
                left = x;
                x = nx
            }

        if !x.resolve().map_or(false, |n| n.key == *key ) {
            None
        } else if x.p == left.p && x.is_some() {
            println!("fuck equels");
            // this means remove head
            let head = self.head.take().unwrap();
            let head = *head;   // unwrap Box
            let SkipNode { it, next, forward, .. } = head;
            let mut new_head = next;

            // calculate new level, means, only head nodes
            let new_level = forward.iter().take_while(|nx| nx.is_some()).count();

            self.forward = iter::repeat(Rawlink::from(&mut new_head)).take(new_level).collect();
            self.level = new_level;

            new_head.as_mut().map(|n| n.promote_level(new_level, forward));
            self.head = new_head;

            Some(it)
        } else {
            unimplemented!()
        }
    }

    pub fn size(&self) -> usize {
        self.size
    }
}

impl<Key: PartialOrd + fmt::Display + fmt::Debug, E: fmt::Debug> fmt::Display for SkipList<Key,E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.head.is_none() {
            write!(f, "<empty skip list>")
        } else {
            write!(f, "\nlv0 ");
            let mut x = self.head.as_ref();
            while x.is_some() {
                write!(f, "{} --> ", x.as_ref().map_or_else(String::new, |n| format!("{}", n.key)));
                x = x.as_ref().map_or(None, |n| n.next.as_ref());
            }
            writeln!(f, "");
            for i in 0..self.level {
                write!(f, "lv{} ", i+1);
                let mut x = self.forward[i];
                while x.is_some() {
                    write!(f, "{} ..> ",
                           x.resolve().map_or_else(String::new, |n| format!("{}", n.key)));
                    if x.resolve().map_or(false, |n| n.level() <= i) {
                        break;
                    }
                    x = x.resolve().map_or_else(Rawlink::none, |n| n.forward[i]);
                }
                writeln!(f, "");
            }
            Ok(())
        }
    }
}

/// Rawlink is a type like Option<T> but for holding a raw mutable pointer.
impl<T> Rawlink<T> {
    /// Like `Option::None` for Rawlink.
    fn none() -> Rawlink<T> {
        Rawlink{p: ptr::null_mut()}
    }

    /// Like `Option::Some` for Rawlink
    fn some(n: &mut T) -> Rawlink<T> {
        Rawlink{p: n}
    }

    fn is_some(&self) -> bool {
        !self.is_none()
    }

    fn is_none(&self) -> bool {
        self.p.is_null()
    }

    fn take(&mut self) -> Rawlink<T> {
        mem::replace(self, Rawlink::none())
    }

    /// Convert the `Rawlink` into an immutable Option value.
    fn resolve<'a>(&self) -> Option<&'a T> {
        if self.p.is_null() {
            None
        } else {
            Some(unsafe { &*self.p })
        }
    }

    /// Convert the `Rawlink` into a mutable Option value.
    fn resolve_mut<'a>(&mut self) -> Option<&'a mut T> {
        if self.p.is_null() {
            None
        } else {
            Some(unsafe { &mut *self.p })
        }
    }
}

impl<'a, Key, E> From<&'a mut Link<SkipNode<Key, E>>> for Rawlink<SkipNode<Key, E>> {
    fn from(node: &'a mut Link<SkipNode<Key, E>>) -> Self {
        match node.as_mut() {
            None => Rawlink::none(),
            Some(ptr) => Rawlink::some(&mut **ptr),
        }
    }
}

impl<T> Clone for Rawlink<T> {
    #[inline]
    fn clone(&self) -> Rawlink<T> {
        Rawlink{p: self.p}
    }
}

#[test]
fn test_skip_list() {
    let mut list: SkipList<i32, ()> = SkipList::new();

    let mut rng = thread_rng();

    //let vals = vec![ -18130, 16865, -1813, 1686, -181, 168, -18, 16];
    for i in 0 .. 10 {
        let val = rng.gen_range(0, 2000);
        // let val = vals[i];
        println!("list => {}", list);
        println!("DEBUG {} insert => {}", i+1, val);
        list.insert(val, ());
    }

    println!("list => {}", list);
    println!("level => {}", list.level());

    list.insert(20, ());
    println!("has(20) => {}", list.contains_key(&20));
    println!("list => {}", list);

    list.remove(&20);
    println!("list => {}", list);
}
<commit_msg>skip_list: fix bug when calling find() on middle key<commit_after>use std::mem;
use std::fmt;
use std::ptr;
use std::iter;

use rand::{thread_rng, Rng};

const DEFAULT_LEVEL: usize = 4;

type Link<T> = Option<Box<T>>;

#[allow(raw_pointer_derive)]
#[derive(Debug)]
struct Rawlink<T> {
    p: *mut T,
}

impl<T> Copy for Rawlink<T> {}
unsafe impl<T:Send> Send for Rawlink<T> {}
unsafe impl<T:Sync> Sync for Rawlink<T> {}

fn random_level() -> usize {
    let mut rng = thread_rng();
    let mut level = 0;
    loop {
        if rng.gen_weighted_bool(2) {
            level += 1;
            continue;
        }
        break;
    }

    level
}

#[derive(Debug)]
pub struct SkipNode<Key,E> {
    key: Key,
    it: E,
    next: Link<SkipNode<Key,E>>,
    prev: Rawlink<SkipNode<Key,E>>,
    // level 0 to DEFAULT_LEVEL
    forward: Vec<Rawlink<SkipNode<Key,E>>>,
}

impl<Key: PartialOrd, E> SkipNode<Key,E> {
    // level: 0 ~ DEFAULT_LEVEL
    fn new(key: Key, it: E, level: usize) -> SkipNode<Key,E> {
        SkipNode {
            key: key,
            it: it,
            next: None,
            prev: Rawlink::none(),
            forward: iter::repeat(Rawlink::none()).take(level).collect(),
        }
    }

    #[inline]
    fn level(&self) -> usize {
        self.forward.len()
    }

    fn to_ptr(&mut self) -> Rawlink<SkipNode<Key,E>> {
        Rawlink::some(self)
    }

    fn promote_level(&mut self, new_level: usize, forward: Vec<Rawlink<Self>>) {
        let level = self.level();
        for i in level .. new_level {
            self.forward.push(forward[i]);
        }
        assert!(self.level() == new_level, "promote_level()");
    }

    fn insert(&mut self, key: Key, it: E, level: usize) {
    }
}

pub struct SkipList<Key,E> {
    head: Link<SkipNode<Key,E>>,
    forward: Vec<Rawlink<SkipNode<Key,E>>>,
    level: usize,
    size: usize,
}

impl<Key: PartialOrd + fmt::Debug, E: fmt::Debug> SkipList<Key,E> {
    /// create new empty SkipList
    pub fn new() -> SkipList<Key, E> {
        SkipList {
            head: None,
            forward: iter::repeat(Rawlink::none()).take(DEFAULT_LEVEL).collect(),
            level: DEFAULT_LEVEL,
            size: 0,
        }
    }

    pub fn level(&self) -> usize {
        self.level
    }

    pub fn contains_key(&self, key: &Key) -> bool {
        self.find(key).is_some()
    }

    pub fn find(&self, key: &Key) -> Option<&E> {
        let level = self.level();
        let mut x = self.forward[level-1];
        for i in (0..level).rev() {
            while x.resolve().map_or(false, |n| n.forward[i].is_some()) &&
                x.resolve().map_or(false, |n| n.forward[i].resolve().unwrap().key < *key) {
                    let nx = x.resolve().map_or_else(Rawlink::none, |n| n.forward[i] );
                    x = nx;
                }
        }

        while x.resolve().map_or(false, |n| n.next.is_some()) &&
            x.resolve().map_or(false, |n| n.next.as_ref().unwrap().key < *key) {
                let nx = x.resolve_mut().map_or_else(Rawlink::none, |n| {
                    n.next.as_mut().map_or_else(Rawlink::none, |n| Rawlink::some(&mut **n))
                });
                x = nx;
            }

        // current x.key is lower than key
        // jump next
        x = x.resolve_mut().map_or_else(Rawlink::none, |n| Rawlink::from(&mut n.next));
        x.resolve().map_or(None, |n| {
            if n.key == *key {
                Some(&n.it)
            } else {
                None
            }
        })
    }

    fn adjust_head(&mut self, new_level: usize) {
        let diff = new_level - self.level;
        let head_link  = Rawlink::from(&mut self.head);
        let level = self.level();

        for i in level .. new_level {
            self.forward.push(head_link);
            self.head.as_mut().map(|n| n.forward.push(Rawlink::none()));
        }
        assert_eq!(self.forward.len(), new_level);
        assert_eq!(self.head.as_ref().map_or(new_level, |n| n.level()), new_level);
    }

    // Due to head node must be of same level as List,
    // inserting with decreasing order will lead to almost same bad performance as a linked list
    pub fn insert(&mut self, key: Key, it: E) {
        let mut new_level = random_level();
        if new_level > self.level { // new node will be deepest
            self.adjust_head(new_level);
            self.level = new_level;
        }
        self.size += 1;

        if self.head.is_none() {
            new_level = self.level;
            self.head = Some(Box::new(SkipNode::new(key, it, new_level)));
            let p = Rawlink::from(&mut self.head);
            for i in 0..new_level {
                self.forward[i] = p;
            }
        } else if self.head.as_ref().map_or(false, |n| n.key > key) {
            new_level = self.level;
            // insert at head
            let mut new_node = Some(Box::new(SkipNode::new(key, it, new_level)));
            let new_link = new_node.as_mut().map_or_else(Rawlink::none, |n| {
                Rawlink::some(&mut **n)
            });

            for i in 0..new_level {
                new_node.as_mut().map(|n| {
                    n.forward[i] = self.forward[i]
                });
            }

            for i in 0..new_level {
                self.forward[i] = new_link
            }

            new_node.as_mut().map(|n| n.next = self.head.take());
            self.head = new_node;
        } else {
            println!("crash0");

            let mut x = self.head.as_mut().map_or_else(Rawlink::none, |n| {
                Rawlink::some(&mut **n)
            });
            // insert normally
            let mut update: Vec<Rawlink<SkipNode<Key,E>>> = self.forward[..new_level].to_vec();
            if new_level > 0 {  // need to insert skip pointers
                println!("new level => {}", new_level);
                x = update[new_level-1];
                println!("crash2");
                for i in (0..new_level).rev() {
                    while x.resolve().map_or(false, |n| n.forward[i].is_some()) &&
                        x.resolve().map_or(false, |n| n.forward[i].resolve().unwrap().key < key) {
                            let nx = x.resolve().map_or_else(Rawlink::none, |n| n.forward[i] );
                            x = nx;
                        }
                    update[i] = x.resolve_mut().map_or_else(Rawlink::none, |n| {
                        Rawlink::some(&mut *n)
                    });
                }
            }

            println!("crash1");
            let mut y = x.resolve_mut().map_or_else(Rawlink::none, |n| {
                Rawlink::some(&mut *n)
            });
            // When head node level is lower than current
            if y.is_none() {
                println!("update => {:?}", update);
                y = self.head.as_mut().map_or_else(Rawlink::none, |n| {
                    Rawlink::some(&mut **n)
                });
            }
            while y.resolve().map_or(false, |n| n.next.is_some()) &&
                y.resolve().map_or(false, |n| n.next.as_ref().unwrap().key < key) {
                    let ny = y.resolve_mut().map_or_else(Rawlink::none, |n| {
                        n.next.as_mut().map_or_else(Rawlink::none, |n| Rawlink::some(&mut **n))
                    });
                    y = ny
                }
            assert!(y.is_some());
            // create node and insert
            let mut new_node = Some(Box::new(SkipNode::new(key, it, self.level)));
            let new_link = new_node.as_mut().map_or_else(Rawlink::none, |n| {
                Rawlink::some(&mut **n)
            });

            for i in 0..new_level {
                new_node.as_mut().map(|n| {
                    n.forward[i] = update[i].resolve_mut().map_or_else(Rawlink::none, |nx| {
                        nx.forward[i]
                    });
                });
                // if update is empty, then update head node's link
                update[i].resolve_mut().map_or_else(|| {
                    self.forward[i] = new_link;
                },
                    |prev| {
                    prev.forward[i] = new_link;
                });
            }

            // move in
            y.resolve_mut().map(|n| {
                new_node.as_mut().map(|new| {
                    new.next = n.next.take();
                });
                n.next = new_node;
            });
        }
    }

    pub fn remove(&mut self, key: &Key) -> Option<E> {
        if self.head.is_none() {
            return None;
        }
        let level = self.level();
        let mut x = self.forward[level-1];
        let mut left = x;

        for i in (0..level).rev() {
            while x.resolve().map_or(false, |n| n.forward[i].is_some()) &&
                x.resolve().map_or(false, |n| n.forward[i].resolve().unwrap().key < *key) {
                    let nx = x.resolve().map_or_else(Rawlink::none, |n| n.forward[i] );
                    x = nx;
                }
        }

        while x.resolve().map_or(false, |n| n.next.is_some()) &&
            x.resolve().map_or(false, |n| n.next.as_ref().unwrap().key < *key) {
                let nx = x.resolve_mut().map_or_else(Rawlink::none, |n| {
                    n.next.as_mut().map_or_else(Rawlink::none, |n| Rawlink::some(&mut **n))
                });
                left = x;
                x = nx
            }

        if x.resolve().map_or(true, |n| n.key != *key ) {
            println!("not found");
            None
        } else if x.p == left.p && x.is_some() {
            println!("fuck equels");
            // this means remove head
            let head = self.head.take().unwrap();
            let head = *head;   // unwrap Box
            let SkipNode { it, next, forward, .. } = head;
            let mut new_head = next;

            // calculate new level, means, only head nodes
            let new_level = forward.iter().take_while(|nx| nx.is_some()).count();

            self.forward = iter::repeat(Rawlink::from(&mut new_head)).take(new_level).collect();
            self.level = new_level;

            new_head.as_mut().map(|n| n.promote_level(new_level, forward));
            self.head = new_head;

            Some(it)
        } else {
            unimplemented!()
        }
    }

    pub fn size(&self) -> usize {
        self.size
    }
}

impl<Key: PartialOrd + fmt::Display + fmt::Debug, E: fmt::Debug> fmt::Display for SkipList<Key,E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.head.is_none() {
            write!(f, "<empty skip list>")
        } else {
            write!(f, "\nlv0 ");
            let mut x = self.head.as_ref();
            while x.is_some() {
                write!(f, "{} --> ", x.as_ref().map_or_else(String::new, |n| format!("{}", n.key)));
                x = x.as_ref().map_or(None, |n| n.next.as_ref());
            }
            writeln!(f, "");
            for i in 0..self.level {
                write!(f, "lv{} ", i+1);
                let mut x = self.forward[i];
                while x.is_some() {
                    write!(f, "{} ..> ",
                           x.resolve().map_or_else(String::new, |n| format!("{}", n.key)));
                    if x.resolve().map_or(false, |n| n.level() <= i) {
                        break;
                    }
                    x = x.resolve().map_or_else(Rawlink::none, |n| n.forward[i]);
                }
                writeln!(f, "");
            }
            Ok(())
        }
    }
}

/// Rawlink is a type like Option<T> but for holding a raw mutable pointer.
impl<T> Rawlink<T> {
    /// Like `Option::None` for Rawlink.
    fn none() -> Rawlink<T> {
        Rawlink{p: ptr::null_mut()}
    }

    /// Like `Option::Some` for Rawlink
    fn some(n: &mut T) -> Rawlink<T> {
        Rawlink{p: n}
    }

    fn is_some(&self) -> bool {
        !self.is_none()
    }

    fn is_none(&self) -> bool {
        self.p.is_null()
    }

    fn take(&mut self) -> Rawlink<T> {
        mem::replace(self, Rawlink::none())
    }

    /// Convert the `Rawlink` into an immutable Option value.
    fn resolve<'a>(&self) -> Option<&'a T> {
        if self.p.is_null() {
            None
        } else {
            Some(unsafe { &*self.p })
        }
    }

    /// Convert the `Rawlink` into a mutable Option value.
    fn resolve_mut<'a>(&mut self) -> Option<&'a mut T> {
        if self.p.is_null() {
            None
        } else {
            Some(unsafe { &mut *self.p })
        }
    }
}

impl<'a, Key, E> From<&'a mut Link<SkipNode<Key, E>>> for Rawlink<SkipNode<Key, E>> {
    fn from(node: &'a mut Link<SkipNode<Key, E>>) -> Self {
        match node.as_mut() {
            None => Rawlink::none(),
            Some(ptr) => Rawlink::some(&mut **ptr),
        }
    }
}

impl<T> Clone for Rawlink<T> {
    #[inline]
    fn clone(&self) -> Rawlink<T> {
        Rawlink{p: self.p}
    }
}

#[test]
fn test_skip_list() {
    let mut list: SkipList<i32, ()> = SkipList::new();

    let mut rng = thread_rng();

    //let vals = vec![ -18130, 16865, -1813, 1686, -181, 168, -18, 16];
    for i in 0 .. 10 {
        let val = rng.gen_range(0, 2000);
        // let val = vals[i];
        println!("DEBUG {} insert => {}", i+1, val);
        list.insert(val, ());
    }

    println!("list => {}", list);
    println!("level => {}", list.level());

    list.insert(1000, ());
    println!("list => {}", list);
    println!("has(1000) => {}", list.contains_key(&1000));

    list.remove(&1000);
    println!("list => {}", list);
}
<|endoftext|>