<commit_before>#![crate_name = "toy_aa"]
#![crate_type = "dylib"]

use std::fmt::{mod, Show};
use std::mem::{replace, swap};

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

struct Node<K, V> {
    key: K,
    value: V,
    left: Link<Node<K, V>>,
    right: Link<Node<K, V>>,
    level: uint
}

pub struct Tree<K, V> {
    root: Link<Node<K, V>>,
}

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

    fn is_bst(&self) -> bool {
        match self.root {
            None => true,
            Some(ref r) => r.is_bst()
        }
    }

    fn is_aa(&self) -> bool {
        match self.root {
            None => true,
            Some(ref r) => r.is_aa()
        }
    }

    pub fn find<'a>(&'a self, key: &K) -> Option<&'a V> {
        match self.root {
            None => None,
            Some(ref r) => r.find(key)
        }
    }

    pub fn insert(&mut self, key: K, value: V) -> Option<V> {
        match self.root {
            None => {
                self.root = Some(box Node::new(key, value));
                None
            },
            Some(ref mut r) => r.insert(key, value)
        }
    }
}

impl<K: Ord, V> Node<K, V> {
    pub fn new(key: K, value: V) -> Node<K, V> {
        Node { key: key, value: value, left: None, right: None, level: 1 }
    }

    fn max(&self) -> &K {
        match self.right {
            None => &self.key,
            Some(ref n) => n.max(),
        }
    }

    fn min(&self) -> &K {
        match self.left {
            None => &self.key,
            Some(ref n) => n.min(),
        }
    }

    pub fn is_bst(&self) -> bool {
        self.left.as_ref().map_or(true, |n| n.is_bst() && *n.max() < self.key)
        && self.right.as_ref().map_or(true, |n| n.is_bst() && *n.min() > self.key)
    }

    pub fn find<'a>(&'a self, key: &K) -> Option<&'a V> {
        let ch = match key.cmp(&self.key) {
            Equal => return Some(&self.value),
            Less => & self.left,
            Greater => & self.right,
        };

        match *ch {
            None => None,
            Some(ref b) => b.find(key),
        }
    }

    pub fn insert(&mut self, key: K, value: V) -> Option<V> {
        let replaced = match key.cmp(&self.key) {
            Equal => {
                self.key = key;
                return Some(replace(&mut self.value, value))
            },
            Less =>
                match self.left {
                    None => {
                        self.left = Some(box Node::new(key, value));
                        None
                    },
                    Some(ref mut b) => b.insert(key, value),
                },
            Greater =>
                match self.right {
                    None => {
                        self.right = Some(box Node::new(key, value));
                        None
                    },
                    Some(ref mut b) => b.insert(key, value),
                },
        };

        self.skew();
        self.split();
        replaced
    }

    // To be an AA tree, it must be a binary search tree and, for all nodes n:
    //   - if n is missing a child, its level must be 1
    //   - the left child must have a level one less than n's level
    //   - the right child must have a level equal to or one less than n's level
    //   - the right child's right child must not have the same level as n's level
    fn is_aa(&self) -> bool {
        let lvl = self.level;

        self.is_bst()
            && !((self.left.is_none() || self.right.is_none()) && self.level != 1)
            && self.left.as_ref().map_or(true, |n| n.is_aa())
            && self.no_red_left_child()
            && self.right.as_ref().map_or(true,
                |n| n.is_aa() && (n.level == lvl || n.level + 1 == lvl)
                    && !(n.level == lvl && !n.no_red_right_child()))
    }

    fn no_red_left_child(&self) -> bool {
        match self.left {
            None => true,
            Some(ref n) => n.level + 1 == self.level,
        }
    }

    fn no_red_right_child(&self) -> bool {
        match self.right {
            None => true,
            Some(ref n) => n.level + 1 == self.level,
        }
    }

    // Remove red left child by rotating right
    /*
         a      b
        /        \
       b    =>    a
        \        /
         c      c

      provided that a.level == b.level
    */
    fn skew(&mut self) {
        if self.left.is_some() && self.left.get_ref().level == self.level {
            let mut save = self.left.take_unwrap();
            swap(&mut self.left, &mut save.right); // save.right now None
            swap(self, &mut *save);
            self.right = Some(save);
        }
    }

    // Remove red right child of red right child by rotating left and increasing
    // level of the parent
    /*
        a            b
         \          / \
          b    =>  a   c
         / \        \
        d   c        d

      provided that a.level == c.level
    */
    fn split(&mut self) {
        if self.right.as_ref().map_or(false,
          |x| x.right.is_some() && x.right.get_ref().level == self.level) {
            let mut save = self.right.take_unwrap();
            swap(&mut self.right, &mut save.left); // save.left now None
            save.level += 1;
            swap(self, &mut *save);
            self.left = Some(save);
        }
    }

    /*

       In the below, 'o' represents black, '*' represents red.

       First, note that deleting a red leaf requires no rebalancing at all.

       ---

       There's only 1 possible AA tree of size 2:

       o
        \
         *

       Deleting the root or the leaf requires no rebalancing.

       ---

       For size 3 trees, we only have:

         o
        / \
       o   o

        - deleting left leaf means we have to decrease the level of root. this suffices to rebalance
        - deleting right leaf means we have to decrease level of root but then make left leaf the
          new root (and former root the child of new root)
        - deleting the root means right child is new root, left child becomes new root's right child

       ---

       For size 4 trees, we have either

         o       o
        / \     / \
       o   o   o   o
        \           \
         *           *

       There are 4 classes of deletion:

        - delete red leaf (see above)
        - delete red node's parent: make red a child of its former grandparent
        - delete root: in the first case, red needs to become root, so increase its level and make it
          the new root. in the second case, right child of root needs to become new root.
        - delete other child: in the first case, red needs to become root and the old root needs to
          be right child of new root. in the second case, decrease level of old root, increase level
          of right child and make old root the child of the right child (which is the new root)

       ---

       For size 5 trees, we have one of

         o        o
        / \      / \
       o   o    o   *
        \   \      / \
         *   *    o   o

       ===

       One fundamental operation we need is "promote the max from the left subtree (or min from right subtree!)
       this is used when we delete a root, for example. this seems essentially whenever we delete a node that
       has two children.

     */
}

impl<K: Show, V: Show> Show for Node<K, V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}:{}", self.key, self.value)
    }
}

fn print_node_depth<K: Show, V: Show>(node: &Link<Node<K,V>>, depth: uint) {
    let mut pre = "".to_string();
    if depth > 0 {
        for i in range(0, depth) {
            pre = pre + "   ";
        }
    }

    match *node {
        Some(ref n) => {
            println!("{}{}^{}", pre, n, n.level);
            print_node_depth(&n.left, depth + 1);
            print_node_depth(&n.right, depth + 1);
        },
        None => println!("{}-", pre),
    }
}

pub fn print_tree<K: Show + Ord, V: Show>(tree: &Tree<K, V>) {
    print_node_depth(&tree.root, 0);
    println!("Is AA: {}", tree.is_aa());
    println!("------------");
}

#[cfg(test)]
mod test {
    use super::Tree;
    use std::rand;
    use std::rand::distributions::{IndependentSample, Range};

    #[test]
    fn test_find() {
        let mut t = Tree::new();
        assert_eq!(t.find(&1u), None);
        t.insert(1u, 'j');
        assert_eq!(t.find(&1u), Some(&'j'));

    }

    // testing whether we can find all the things we inserted
    #[test]
    fn test_insert() {
        let mut t: Tree<uint, u8> = Tree::new();
        for (i, c) in range(0u, 10).zip(range(b'a', b'z')) {
            t.insert(i, c);
        }

        for (ref i, ref c) in range(0u, 10).zip(range(b'a', b'z')) {
            assert_eq!(t.find(i), Some(c));
        }

        assert_eq!(t.find(&10u), None);
    }

    fn insert_n_check_aa(n: uint, between: Range<uint>, rng: &mut rand::TaskRng) {
        let mut t = Tree::new();

        for _ in range(0u, n) {
            let a = between.ind_sample(rng);
            println!("{}", a);
            t.insert(a, ());
        }

        assert!(t.is_aa());
    }

    // testing whether, after inserting 20 random keys, is_aa() returns true
    #[test]
    fn test_insert_is_aa() {
        let mut rng = rand::task_rng();
        let between = Range::new(0u, 100_000);

        for _ in range(0u, 300) {
            insert_n_check_aa(20, between, &mut rng);
        }
    }

    // testing whether, after inserting 20 random keys, is_aa() returns true,
    // but this time some of the keys are repeated
    #[test]
    fn test_insert_dups_is_aa() {
        let mut rng = rand::task_rng();
        let between = Range::new(0u, 15);

        for _ in range(0u, 300) {
            insert_n_check_aa(20, between, &mut rng);
        }
    }
}
<commit_msg>I did something or other back in September but never committed here. Doing that now<commit_after>#![crate_name = "toy_aa"]
#![crate_type = "dylib"]

use std::fmt::{mod, Show};
use std::mem::{replace, swap};

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

struct Node<K, V> {
    key: K,
    value: V,
    left: Link<Node<K, V>>,
    right: Link<Node<K, V>>,
    level: uint
}

pub struct Tree<K, V> {
    root: Link<Node<K, V>>,
}

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

    fn is_bst(&self) -> bool {
        match self.root {
            None => true,
            Some(ref r) => r.is_bst()
        }
    }

    fn is_aa(&self) -> bool {
        match self.root {
            None => true,
            Some(ref r) => r.is_aa()
        }
    }

    pub fn find<'a>(&'a self, key: &K) -> Option<&'a V> {
        match self.root {
            None => None,
            Some(ref r) => r.find(key)
        }
    }

    pub fn insert(&mut self, key: K, value: V) -> Option<V> {
        match self.root {
            None => {
                self.root = Some(box Node::new(key, value));
                None
            },
            Some(ref mut r) => r.insert(key, value)
        }
    }
}

impl<K: Ord, V> Node<K, V> {
    pub fn new(key: K, value: V) -> Node<K, V> {
        Node { key: key, value: value, left: None, right: None, level: 1 }
    }

    fn max(&self) -> &K {
        match self.right {
            None => &self.key,
            Some(ref n) => n.max(),
        }
    }

    fn min(&self) -> &K {
        match self.left {
            None => &self.key,
            Some(ref n) => n.min(),
        }
    }

    pub fn is_bst(&self) -> bool {
        self.left.as_ref().map_or(true, |n| n.is_bst() && *n.max() < self.key)
        && self.right.as_ref().map_or(true, |n| n.is_bst() && *n.min() > self.key)
    }

    pub fn find<'a>(&'a self, key: &K) -> Option<&'a V> {
        let ch = match key.cmp(&self.key) {
            Equal => return Some(&self.value),
            Less => & self.left,
            Greater => & self.right,
        };

        match *ch {
            None => None,
            Some(ref b) => b.find(key),
        }
    }

    pub fn insert(&mut self, key: K, value: V) -> Option<V> {
        let replaced = match key.cmp(&self.key) {
            Equal => {
                self.key = key;
                return Some(replace(&mut self.value, value))
            },
            Less =>
                match self.left {
                    None => {
                        self.left = Some(box Node::new(key, value));
                        None
                    },
                    Some(ref mut b) => b.insert(key, value),
                },
            Greater =>
                match self.right {
                    None => {
                        self.right = Some(box Node::new(key, value));
                        None
                    },
                    Some(ref mut b) => b.insert(key, value),
                },
        };

        self.skew();
        self.split();
        replaced
    }

    pub fn remove(&mut self, key: &K) -> Option<V> {
        let removed = match key.cmp(&self.key) {
            Less =>
                match self.left {
                    None => return None,
                    Some(ref mut b) => b.remove(key),
                },
            Greater =>
                match self.right {
                    None => return None,
                    Some(ref mut b) => b.remove(key),
                },
            Equal => {
                // replace self with largest predecessor
                // delete the node (call it on the swapped key afte we switch?)
            },
        };

        self.skew();
        self.split();
        replaced
    }

    // To be an AA tree, it must be a binary search tree and, for all nodes n:
    //   - if n is missing a child, its level must be 1
    //   - the left child must have a level one less than n's level
    //   - the right child must have a level equal to or one less than n's level
    //   - the right child's right child must not have the same level as n's level
    fn is_aa(&self) -> bool {
        let lvl = self.level;

        self.is_bst()
            && !((self.left.is_none() || self.right.is_none()) && self.level != 1)
            && self.left.as_ref().map_or(true, |n| n.is_aa())
            && self.no_red_left_child()
            && self.right.as_ref().map_or(true,
                |n| n.is_aa() && (n.level == lvl || n.level + 1 == lvl)
                    && !(n.level == lvl && !n.no_red_right_child()))
    }

    fn no_red_left_child(&self) -> bool {
        match self.left {
            None => true,
            Some(ref n) => n.level + 1 == self.level,
        }
    }

    fn no_red_right_child(&self) -> bool {
        match self.right {
            None => true,
            Some(ref n) => n.level + 1 == self.level,
        }
    }

    // Remove red left child by rotating right
    /*
         a      b
        /        \
       b    =>    a
        \        /
         c      c

      provided that a.level == b.level
    */
    fn skew(&mut self) {
        if self.left.is_some() && self.left.get_ref().level == self.level {
            let mut save = self.left.take_unwrap();
            swap(&mut self.left, &mut save.right); // save.right now None
            swap(self, &mut *save);
            self.right = Some(save);
        }
    }

    // repeat [skew current node, follow right child] until no right child
    fn skew_subtree(&mut self) {
        self.skew();
        match self.right {
            None => {},
            Some(ref mut n) => n.skew_subtree(),
        }
    }

    // repeat [split current node, follow right child] until no right child
    fn split_subtree(&mut self) {
        self.split();
        match self.right {
            None => {},
            Some(ref mut n) => n.split_subtree(),
        }
    }

    // Remove red right child of red right child by rotating left and increasing
    // level of the parent
    /*
        a            b
         \          / \
          b    =>  a   c
         / \        \
        d   c        d

      provided that a.level == c.level
    */
    fn split(&mut self) {
        if self.right.as_ref().map_or(false,
          |x| x.right.is_some() && x.right.get_ref().level == self.level) {
            let mut save = self.right.take_unwrap();
            swap(&mut self.right, &mut save.left); // save.left now None
            save.level += 1;
            swap(self, &mut *save);
            self.left = Some(save);
        }
    }

    /*

       In the below, 'o' represents black, '*' represents red.

       First, note that deleting a red leaf requires no rebalancing at all.

       ---

       There's only 1 possible AA tree of size 2:

       o
        \
         *

       Deleting the root or the leaf requires no rebalancing.

       ---

       For size 3 trees, we only have:

         o
        / \
       o   o

        - deleting left leaf means we have to decrease the level of root. this suffices to rebalance
        - deleting right leaf means we have to decrease level of root but then make left leaf the
          new root (and former root the child of new root)
        - deleting the root means right child is new root, left child becomes new root's right child

       ---

       For size 4 trees, we have either

         o       o
        / \     / \
       o   o   o   o
        \           \
         *           *

       There are 4 classes of deletion:

        - delete red leaf (see above)
        - delete red node's parent: make red a child of its former grandparent
        - delete root: in the first case, red needs to become root, so increase its level and make it
          the new root. in the second case, right child of root needs to become new root.
        - delete other child: in the first case, red needs to become root and the old root needs to
          be right child of new root. in the second case, decrease level of old root, increase level
          of right child and make old root the child of the right child (which is the new root)

       ---

       For size 5 trees, we have one of

         o        o
        / \      / \
       o   o    o   *
        \   \      / \
         *   *    o   o

       ===

       One fundamental operation we need is "promote the max from the left subtree (or min from right subtree!)
       this is used when we delete a root, for example. this seems essentially whenever we delete a node that
       has two children.

     */
}

impl<K: Show, V: Show> Show for Node<K, V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}:{}", self.key, self.value)
    }
}

fn print_node_depth<K: Show, V: Show>(node: &Link<Node<K,V>>, depth: uint) {
    let mut pre = "".to_string();
    if depth > 0 {
        for i in range(0, depth) {
            pre = pre + "   ";
        }
    }

    match *node {
        Some(ref n) => {
            println!("{}{}^{}", pre, n, n.level);
            print_node_depth(&n.left, depth + 1);
            print_node_depth(&n.right, depth + 1);
        },
        None => println!("{}-", pre),
    }
}

pub fn print_tree<K: Show + Ord, V: Show>(tree: &Tree<K, V>) {
    print_node_depth(&tree.root, 0);
    println!("Is AA: {}", tree.is_aa());
    println!("------------");
}

#[cfg(test)]
mod test {
    use super::Tree;
    use std::rand;
    use std::rand::distributions::{IndependentSample, Range};

    #[test]
    fn test_find() {
        let mut t = Tree::new();
        assert_eq!(t.find(&1u), None);
        t.insert(1u, 'j');
        assert_eq!(t.find(&1u), Some(&'j'));

    }

    // testing whether we can find all the things we inserted
    #[test]
    fn test_insert() {
        let mut t: Tree<uint, u8> = Tree::new();
        for (i, c) in range(0u, 10).zip(range(b'a', b'z')) {
            t.insert(i, c);
        }

        for (ref i, ref c) in range(0u, 10).zip(range(b'a', b'z')) {
            assert_eq!(t.find(i), Some(c));
        }

        assert_eq!(t.find(&10u), None);
    }

    fn insert_n_check_aa(n: uint, between: Range<uint>, rng: &mut rand::TaskRng) {
        let mut t = Tree::new();

        for _ in range(0u, n) {
            let a = between.ind_sample(rng);
            println!("{}", a);
            t.insert(a, ());
        }

        assert!(t.is_aa());
    }

    // testing whether, after inserting 20 random keys, is_aa() returns true
    #[test]
    fn test_insert_is_aa() {
        let mut rng = rand::task_rng();
        let between = Range::new(0u, 100_000);

        for _ in range(0u, 300) {
            insert_n_check_aa(20, between, &mut rng);
        }
    }

    // testing whether, after inserting 20 random keys, is_aa() returns true,
    // but this time some of the keys are repeated
    #[test]
    fn test_insert_dups_is_aa() {
        let mut rng = rand::task_rng();
        let between = Range::new(0u, 15);

        for _ in range(0u, 300) {
            insert_n_check_aa(20, between, &mut rng);
        }
    }
}
<|endoftext|>


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

//! A generic backing store for caches.
//!
//! `FreeList` is a simple vector-backed data structure where each entry in the
//! vector contains an Option<T>. It maintains an index-based (rather than
//! pointer-based) free list to efficiently locate the next unused entry. If all
//! entries are occupied, insertion appends a new element to the vector.
//!
//! It also supports both strong and weak handle semantics. There is exactly one
//! (non-Clonable) strong handle per occupied entry, which must be passed by
//! value into `free()` to release an entry. Strong handles can produce an
//! unlimited number of (Clonable) weak handles, which are used to perform
//! lookups which may fail of the entry has been freed. A per-entry epoch ensures
//! that weak handle lookups properly fail even if the entry has been freed and
//! reused.
//!
//! TODO(gw): Add an occupied list head, for fast iteration of the occupied list
//! to implement retain() style functionality.

use std::{fmt, u32};
use std::marker::PhantomData;

#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct Epoch(u32);

impl Epoch {
    /// Mints a new epoch.
    ///
    /// We start at 1 so that 0 is always an invalid epoch.
    fn new() -> Self {
        Epoch(1)
    }

    /// Returns an always-invalid epoch.
    fn invalid() -> Self {
        Epoch(0)
    }
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct FreeListHandle<M> {
    index: u32,
    epoch: Epoch,
    _marker: PhantomData<M>,
}

/// More-compact textual representation for debug logging.
impl<M> fmt::Debug for FreeListHandle<M> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("StrongHandle")
            .field("index", &self.index)
            .field("epoch", &self.epoch.0)
            .finish()
    }
}

impl<M> FreeListHandle<M> {
    pub fn weak(&self) -> WeakFreeListHandle<M> {
        WeakFreeListHandle {
            index: self.index,
            epoch: self.epoch,
            _marker: PhantomData,
        }
    }

    pub fn invalid() -> Self {
        Self {
            index: 0,
            epoch: Epoch::invalid(),
            _marker: PhantomData,
        }
    }
}

impl<M> Clone for WeakFreeListHandle<M> {
    fn clone(&self) -> Self {
        WeakFreeListHandle {
            index: self.index,
            epoch: self.epoch,
            _marker: PhantomData,
        }
    }
}

impl<M> PartialEq for WeakFreeListHandle<M> {
    fn eq(&self, other: &Self) -> bool {
        self.index == other.index && self.epoch == other.epoch
    }
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(MallocSizeOf)]
pub struct WeakFreeListHandle<M> {
    index: u32,
    epoch: Epoch,
    _marker: PhantomData<M>,
}

/// More-compact textual representation for debug logging.
impl<M> fmt::Debug for WeakFreeListHandle<M> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("WeakHandle")
            .field("index", &self.index)
            .field("epoch", &self.epoch.0)
            .finish()
    }
}

impl<M> WeakFreeListHandle<M> {
    /// Returns an always-invalid handle.
    pub fn invalid() -> Self {
        Self {
            index: 0,
            epoch: Epoch::invalid(),
            _marker: PhantomData,
        }
    }
}

#[derive(Debug)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct Slot<T> {
    next: Option<u32>,
    epoch: Epoch,
    value: Option<T>,
}

#[derive(Debug)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct FreeList<T, M> {
    slots: Vec<Slot<T>>,
    free_list_head: Option<u32>,
    active_count: usize,
    _marker: PhantomData<M>,
}

pub enum UpsertResult<T, M> {
    Updated(T),
    Inserted(FreeListHandle<M>),
}

impl<T, M> FreeList<T, M> {
    /// Mints a new `FreeList` with no entries.
    ///
    /// Triggers a 1-entry allocation.
    pub fn new() -> Self {
        // We guarantee that we never have zero entries by starting with one
        // free entry. This allows WeakFreeListHandle::invalid() to work
        // without adding any additional branches.
        let first_slot = Slot {
            next: None,
            epoch: Epoch::new(),
            value: None,
        };
        FreeList {
            slots: vec![first_slot],
            free_list_head: Some(0),
            active_count: 0,
            _marker: PhantomData,
        }
    }

    pub fn clear(&mut self) {
        self.slots.clear();
        self.free_list_head = None;
        self.active_count = 0;
    }

    #[allow(dead_code)]
    pub fn get(&self, id: &FreeListHandle<M>) -> &T {
        self.slots[id.index as usize].value.as_ref().unwrap()
    }

    #[allow(dead_code)]
    pub fn get_mut(&mut self, id: &FreeListHandle<M>) -> &mut T {
        self.slots[id.index as usize].value.as_mut().unwrap()
    }

    pub fn get_opt(&self, id: &WeakFreeListHandle<M>) -> Option<&T> {
        let slot = &self.slots[id.index as usize];
        if slot.epoch == id.epoch {
            slot.value.as_ref()
        } else {
            None
        }
    }

    pub fn get_opt_mut(&mut self, id: &WeakFreeListHandle<M>) -> Option<&mut T> {
        let slot = &mut self.slots[id.index as usize];
        if slot.epoch == id.epoch {
            slot.value.as_mut()
        } else {
            None
        }
    }

    // Perform a database style UPSERT operation. If the provided
    // handle is a valid entry, update the value and return the
    // previous data. If the provided handle is invalid, then
    // insert the data into a new slot and return the new handle.
    pub fn upsert(&mut self, id: &WeakFreeListHandle<M>, data: T) -> UpsertResult<T, M> {
        if self.slots[id.index as usize].epoch == id.epoch {
            let slot = &mut self.slots[id.index as usize];
            let result = UpsertResult::Updated(slot.value.take().unwrap());
            slot.value = Some(data);
            result
        } else {
            UpsertResult::Inserted(self.insert(data))
        }
    }

    pub fn insert(&mut self, item: T) -> FreeListHandle<M> {
        self.active_count += 1;

        match self.free_list_head {
            Some(free_index) => {
                let slot = &mut self.slots[free_index as usize];

                // Remove from free list.
                self.free_list_head = slot.next;
                slot.next = None;
                slot.value = Some(item);

                FreeListHandle {
                    index: free_index,
                    epoch: slot.epoch,
                    _marker: PhantomData,
                }
            }
            None => {
                let index = self.slots.len() as u32;
                let epoch = Epoch::new();

                self.slots.push(Slot {
                    next: None,
                    epoch,
                    value: Some(item),
                });

                FreeListHandle {
                    index,
                    epoch,
                    _marker: PhantomData,
                }
            }
        }
    }

    pub fn free(&mut self, id: FreeListHandle<M>) -> T {
        self.active_count -= 1;
        let slot = &mut self.slots[id.index as usize];
        slot.next = self.free_list_head;
        slot.epoch = Epoch(slot.epoch.0 + 1);
        self.free_list_head = Some(id.index);
        slot.value.take().unwrap()
    }

    #[allow(dead_code)]
    pub fn len(&self) -> usize {
        self.active_count
    }
}
<commit_msg>Bug 1592225 - Don't break documented freelist invariant when clearing it. r=gw<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A generic backing store for caches.
//!
//! `FreeList` is a simple vector-backed data structure where each entry in the
//! vector contains an Option<T>. It maintains an index-based (rather than
//! pointer-based) free list to efficiently locate the next unused entry. If all
//! entries are occupied, insertion appends a new element to the vector.
//!
//! It also supports both strong and weak handle semantics. There is exactly one
//! (non-Clonable) strong handle per occupied entry, which must be passed by
//! value into `free()` to release an entry. Strong handles can produce an
//! unlimited number of (Clonable) weak handles, which are used to perform
//! lookups which may fail of the entry has been freed. A per-entry epoch ensures
//! that weak handle lookups properly fail even if the entry has been freed and
//! reused.
//!
//! TODO(gw): Add an occupied list head, for fast iteration of the occupied list
//! to implement retain() style functionality.

use std::{fmt, u32};
use std::marker::PhantomData;

#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct Epoch(u32);

impl Epoch {
    /// Mints a new epoch.
    ///
    /// We start at 1 so that 0 is always an invalid epoch.
    fn new() -> Self {
        Epoch(1)
    }

    /// Returns an always-invalid epoch.
    fn invalid() -> Self {
        Epoch(0)
    }
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct FreeListHandle<M> {
    index: u32,
    epoch: Epoch,
    _marker: PhantomData<M>,
}

/// More-compact textual representation for debug logging.
impl<M> fmt::Debug for FreeListHandle<M> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("StrongHandle")
            .field("index", &self.index)
            .field("epoch", &self.epoch.0)
            .finish()
    }
}

impl<M> FreeListHandle<M> {
    pub fn weak(&self) -> WeakFreeListHandle<M> {
        WeakFreeListHandle {
            index: self.index,
            epoch: self.epoch,
            _marker: PhantomData,
        }
    }

    pub fn invalid() -> Self {
        Self {
            index: 0,
            epoch: Epoch::invalid(),
            _marker: PhantomData,
        }
    }
}

impl<M> Clone for WeakFreeListHandle<M> {
    fn clone(&self) -> Self {
        WeakFreeListHandle {
            index: self.index,
            epoch: self.epoch,
            _marker: PhantomData,
        }
    }
}

impl<M> PartialEq for WeakFreeListHandle<M> {
    fn eq(&self, other: &Self) -> bool {
        self.index == other.index && self.epoch == other.epoch
    }
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(MallocSizeOf)]
pub struct WeakFreeListHandle<M> {
    index: u32,
    epoch: Epoch,
    _marker: PhantomData<M>,
}

/// More-compact textual representation for debug logging.
impl<M> fmt::Debug for WeakFreeListHandle<M> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("WeakHandle")
            .field("index", &self.index)
            .field("epoch", &self.epoch.0)
            .finish()
    }
}

impl<M> WeakFreeListHandle<M> {
    /// Returns an always-invalid handle.
    pub fn invalid() -> Self {
        Self {
            index: 0,
            epoch: Epoch::invalid(),
            _marker: PhantomData,
        }
    }
}

#[derive(Debug)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct Slot<T> {
    next: Option<u32>,
    epoch: Epoch,
    value: Option<T>,
}

#[derive(Debug)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct FreeList<T, M> {
    slots: Vec<Slot<T>>,
    free_list_head: Option<u32>,
    active_count: usize,
    _marker: PhantomData<M>,
}

pub enum UpsertResult<T, M> {
    Updated(T),
    Inserted(FreeListHandle<M>),
}

impl<T, M> FreeList<T, M> {
    /// Mints a new `FreeList` with no entries.
    ///
    /// Triggers a 1-entry allocation.
    pub fn new() -> Self {
        // We guarantee that we never have zero entries by starting with one
        // free entry. This allows WeakFreeListHandle::invalid() to work
        // without adding any additional branches.
        let first_slot = Slot {
            next: None,
            epoch: Epoch::new(),
            value: None,
        };
        FreeList {
            slots: vec![first_slot],
            free_list_head: Some(0),
            active_count: 0,
            _marker: PhantomData,
        }
    }

    pub fn clear(&mut self) {
        self.slots.truncate(1);
        self.slots[0] = Slot {
            next: None,
            epoch: Epoch::new(),
            value: None,
        };
        self.free_list_head = Some(0);
        self.active_count = 0;
    }

    #[allow(dead_code)]
    pub fn get(&self, id: &FreeListHandle<M>) -> &T {
        self.slots[id.index as usize].value.as_ref().unwrap()
    }

    #[allow(dead_code)]
    pub fn get_mut(&mut self, id: &FreeListHandle<M>) -> &mut T {
        self.slots[id.index as usize].value.as_mut().unwrap()
    }

    pub fn get_opt(&self, id: &WeakFreeListHandle<M>) -> Option<&T> {
        let slot = &self.slots[id.index as usize];
        if slot.epoch == id.epoch {
            slot.value.as_ref()
        } else {
            None
        }
    }

    pub fn get_opt_mut(&mut self, id: &WeakFreeListHandle<M>) -> Option<&mut T> {
        let slot = &mut self.slots[id.index as usize];
        if slot.epoch == id.epoch {
            slot.value.as_mut()
        } else {
            None
        }
    }

    // Perform a database style UPSERT operation. If the provided
    // handle is a valid entry, update the value and return the
    // previous data. If the provided handle is invalid, then
    // insert the data into a new slot and return the new handle.
    pub fn upsert(&mut self, id: &WeakFreeListHandle<M>, data: T) -> UpsertResult<T, M> {
        if self.slots[id.index as usize].epoch == id.epoch {
            let slot = &mut self.slots[id.index as usize];
            let result = UpsertResult::Updated(slot.value.take().unwrap());
            slot.value = Some(data);
            result
        } else {
            UpsertResult::Inserted(self.insert(data))
        }
    }

    pub fn insert(&mut self, item: T) -> FreeListHandle<M> {
        self.active_count += 1;

        match self.free_list_head {
            Some(free_index) => {
                let slot = &mut self.slots[free_index as usize];

                // Remove from free list.
                self.free_list_head = slot.next;
                slot.next = None;
                slot.value = Some(item);

                FreeListHandle {
                    index: free_index,
                    epoch: slot.epoch,
                    _marker: PhantomData,
                }
            }
            None => {
                let index = self.slots.len() as u32;
                let epoch = Epoch::new();

                self.slots.push(Slot {
                    next: None,
                    epoch,
                    value: Some(item),
                });

                FreeListHandle {
                    index,
                    epoch,
                    _marker: PhantomData,
                }
            }
        }
    }

    pub fn free(&mut self, id: FreeListHandle<M>) -> T {
        self.active_count -= 1;
        let slot = &mut self.slots[id.index as usize];
        slot.next = self.free_list_head;
        slot.epoch = Epoch(slot.epoch.0 + 1);
        self.free_list_head = Some(id.index);
        slot.value.take().unwrap()
    }

    #[allow(dead_code)]
    pub fn len(&self) -> usize {
        self.active_count
    }
}
<|endoftext|>


<commit_before>use parse::parse_recursive;
use state::ParseState;
use compile::{Instruction, compile_recursive};
use error::ParseError::*;

mod parse;
mod state;
mod compile;
mod error;

static PARSE_ERR: &'static str = "Parse Error: ";

struct Regexp {
  input: ~str
}

impl Regexp {
  pub fn new(s: &str) -> Regexp {
    Regexp { input: s.clone().to_owned() }
  }
}

impl Regexp {
  // we should hide the underlying parsing algorithm
  fn parse(&mut self) -> Result<state::Regexp, ParseCode> {
    let mut ps = ParseState::new();
    match parse_recursive(&mut self.input, &mut ps) {
      ParseOk => {
        ps.pop()
      }
      e => Err(e)
    }
  }
  fn compile(&mut self) {
    let mut stack: ~[Instruction] = ~[];
    match self.parse() {
      Ok(ref re) => {
        compile_recursive(re, &mut stack);
      }
      Err(e) => {
        println(Regexp::parse_err_to_str(e));
      }
    };
  }
}

impl Regexp {
  fn parse_err_to_str(code: ParseCode) -> ~str {
    match code {
      ParseOk => ~"Ok",
      _ => PARSE_ERR + "Error"
    }
  }
}

fn main() {
  println("--Case 0--");
  Regexp::new("abc").compile();

  println("--Case 1--");
  Regexp::new("a|b").compile();

  println("--Case 2--");
  Regexp::new("a|b|c").compile();

  println("--Case 3--");
  Regexp::new("a|Bcf|dez").compile();

  println("--Case 4--");
  //Regexp::new("abc*|d").parse();

  println("--Case 5--");
  //Regexp::new("io(ab|c)*zz|(bcd)*").parse();

  println("--Case 6--");
  //Regexp::new("あ(ab(cd|d)|e)|f").parse();

  println("--Case 7--");
  //Regexp::new("[[A-Z]0-9(fgh)]]]|[abc]").parse();
}
<commit_msg>filled error strings<commit_after>use parse::parse_recursive;
use state::ParseState;
use compile::{Instruction, compile_recursive};
use error::ParseError::*;

mod parse;
mod state;
mod compile;
mod error;

static PARSE_ERR: &'static str = "Parse Error: ";

struct Regexp {
  input: ~str
}

impl Regexp {
  pub fn new(s: &str) -> Regexp {
    Regexp { input: s.clone().to_owned() }
  }
}

impl Regexp {
  // we should hide the underlying parsing algorithm
  fn parse(&mut self) -> Result<state::Regexp, ParseCode> {
    let mut ps = ParseState::new();
    match parse_recursive(&mut self.input, &mut ps) {
      ParseOk => {
        ps.pop()
      }
      e => Err(e)
    }
  }
  fn compile(&mut self) {
    let mut stack: ~[Instruction] = ~[];
    match self.parse() {
      Ok(ref re) => {
        compile_recursive(re, &mut stack);
      }
      Err(e) => {
        println(Regexp::parse_err_to_str(e));
      }
    };
  }
}

impl Regexp {
  fn parse_err_to_str(code: ParseCode) -> ~str {
    match code {
      ParseOk                     => ~"Ok",
      ParseEmptyAlternate         => PARSE_ERR + "Nothing to alternate",
      ParseEmptyConcatenate       => PARSE_ERR + "Nothing to concatenate",
      ParseRepeatedRepetition     => PARSE_ERR + "Multiple repeat operations",
      ParseEmptyRepetition        => PARSE_ERR + "Nothing to repeat",
      ParseExpectedClosingParen   => PARSE_ERR + "Expected ')'",
      ParseExpectedClosingBracket => PARSE_ERR + "Expected ']'",
      ParseExpectedClosingBrace   => PARSE_ERR + "Expected '}'",
      ParseExpectedOperand        => PARSE_ERR + "Expected an operand on the stack",
      ParseUnexpectedOperand      => PARSE_ERR + "Unexpected operand was on the stack",
      ParseEmptyCharClassRange    => PARSE_ERR + "Empty character class",
      ParseInternalError |
      ParseUnknownError           => PARSE_ERR + "Unknown error",
      ParseEmptyStack             => PARSE_ERR + "Nothing on the stack"
    }
  }
}

fn main() {
  println("--Case 0--");
  Regexp::new("abc").compile();

  println("--Case 1--");
  Regexp::new("a|b").compile();

  println("--Case 2--");
  Regexp::new("a|b|c").compile();

  println("--Case 3--");
  Regexp::new("a|(Bcf)|dez").compile();

  println("--Case 4--");
  //Regexp::new("abc*|d").parse();

  println("--Case 5--");
  //Regexp::new("io(ab|c)*zz|(bcd)*").parse();

  println("--Case 6--");
  //Regexp::new("あ(ab(cd|d)|e)|f").parse();

  println("--Case 7--");
  //Regexp::new("[[A-Z]0-9(fgh)]]]|[abc]").parse();
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Buffer whose content is accessible to the CPU.
//!
//! The `CpuAccessibleBuffer` is a basic general-purpose buffer. It can be used in any situation
//! but may not perform as well as other buffer types.
//!
//! Each access from the CPU or from the GPU locks the whole buffer.

use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::ops::DerefMut;
use std::ops::Range;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;
use std::sync::Weak;
use std::time::Duration;
use smallvec::SmallVec;

use buffer::sys::UnsafeBuffer;
use buffer::sys::Usage;
use buffer::traits::AccessRange;
use buffer::traits::Buffer;
use buffer::traits::GpuAccessResult;
use buffer::traits::TypedBuffer;
use command_buffer::Submission;
use device::Device;
use instance::QueueFamily;
use memory::Content;
use memory::CpuAccess as MemCpuAccess;
use memory::pool::MemoryPool;
use memory::pool::MemoryPoolAlloc;
use memory::pool::StdMemoryPool;
use sync::FenceWaitError;
use sync::Sharing;

use OomError;

/// Buffer whose content is accessible by the CPU.
#[derive(Debug)]
pub struct CpuAccessibleBuffer<T: ?Sized, A = StdMemoryPool> where A: MemoryPool {
    // Inner content.
    inner: UnsafeBuffer,

    // The memory held by the buffer.
    memory: A::Alloc,

    // Queue families allowed to access this buffer.
    queue_families: SmallVec<[u32; 4]>,

    // Latest submission that uses this buffer.
    // Also used to block any attempt to submit this buffer while it is accessed by the CPU.
    latest_submission: Mutex<Option<Weak<Submission>>>,      // TODO: can use `Weak::new()` once it's stabilized

    // Necessary to make it compile.
    marker: PhantomData<Box<T>>,
}

impl<T> CpuAccessibleBuffer<T> {
    /// Builds a new buffer. Only allowed for sized data.
    #[inline]
    pub fn new<'a, I>(device: &Arc<Device>, usage: &Usage, queue_families: I)
                      -> Result<Arc<CpuAccessibleBuffer<T>>, OomError>
        where I: IntoIterator<Item = QueueFamily<'a>>
    {
        unsafe {
            CpuAccessibleBuffer::raw(device, mem::size_of::<T>(), usage, queue_families)
        }
    }
}

impl<T> CpuAccessibleBuffer<[T]> {
    /// Builds a new buffer. Can be used for arrays.
    #[inline]
    pub fn array<'a, I>(device: &Arc<Device>, len: usize, usage: &Usage, queue_families: I)
                      -> Result<Arc<CpuAccessibleBuffer<[T]>>, OomError>
        where I: IntoIterator<Item = QueueFamily<'a>>
    {
        unsafe {
            CpuAccessibleBuffer::raw(device, len * mem::size_of::<T>(), usage, queue_families)
        }
    }
}

impl<T: ?Sized> CpuAccessibleBuffer<T> {
    /// Builds a new buffer without checking the size.
    ///
    /// # Safety
    ///
    /// You must ensure that the size that you pass is correct for `T`.
    ///
    pub unsafe fn raw<'a, I>(device: &Arc<Device>, size: usize, usage: &Usage, queue_families: I)
                             -> Result<Arc<CpuAccessibleBuffer<T>>, OomError>
        where I: IntoIterator<Item = QueueFamily<'a>>
    {
        let queue_families = queue_families.into_iter().map(|f| f.id())
                                           .collect::<SmallVec<[u32; 4]>>();

        let (buffer, mem_reqs) = {
            let sharing = if queue_families.len() >= 2 {
                Sharing::Concurrent(queue_families.iter().cloned())
            } else {
                Sharing::Exclusive
            };

            try!(UnsafeBuffer::new(device, size, &usage, sharing))
        };

        let mem_ty = device.physical_device().memory_types()
                           .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0)
                           .filter(|t| t.is_host_visible())
                           .next().unwrap();    // Vk specs guarantee that this can't fail

        let mem = try!(MemoryPool::alloc(&device.standard_pool(), mem_ty,
                                         mem_reqs.size, mem_reqs.alignment));
        debug_assert!((mem.offset() % mem_reqs.alignment) == 0);
        debug_assert!(mem.mapped_memory().is_some());
        try!(buffer.bind_memory(mem.memory(), mem.offset()));

        Ok(Arc::new(CpuAccessibleBuffer {
            inner: buffer,
            memory: mem,
            queue_families: queue_families,
            latest_submission: Mutex::new(None),
            marker: PhantomData,
        }))
    }
}

impl<T: ?Sized, A> CpuAccessibleBuffer<T, A> where A: MemoryPool {
    /// Returns the device used to create this buffer.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }

    /// Returns the queue families this buffer can be used on.
    // TODO: use a custom iterator
    #[inline]
    pub fn queue_families(&self) -> Vec<QueueFamily> {
        self.queue_families.iter().map(|&num| {
            self.device().physical_device().queue_family_by_id(num).unwrap()
        }).collect()
    }
}

impl<T: ?Sized, A> CpuAccessibleBuffer<T, A> where T: Content + 'static, A: MemoryPool {
    /// Locks the buffer in order to write its content.
    ///
    /// If the buffer is currently in use by the GPU, this function will block until either the
    /// buffer is available or the timeout is reached. A value of `0` for the timeout is valid and
    /// means that the function should never block.
    ///
    /// After this function successfully locks the buffer, any attempt to submit a command buffer
    /// that uses it will block until you unlock it.
    // TODO: this could be misleading as there's no difference between `read` and `write`
    #[inline]
    pub fn read(&self, timeout: Duration) -> Result<CpuAccess<T>, FenceWaitError> {
        self.write(timeout)
    }

    /// Locks the buffer in order to write its content.
    ///
    /// If the buffer is currently in use by the GPU, this function will block until either the
    /// buffer is available or the timeout is reached. A value of `0` for the timeout is valid and
    /// means that the function should never block.
    ///
    /// After this function successfully locks the buffer, any attempt to submit a command buffer
    /// that uses it will block until you unlock it.
    #[inline]
    pub fn write(&self, timeout: Duration) -> Result<CpuAccess<T>, FenceWaitError> {
        let submission = self.latest_submission.lock().unwrap();

        if let Some(submission) = submission.as_ref().and_then(|s| s.upgrade()) {
            try!(submission.wait(timeout));
        }

        let offset = self.memory.offset();
        let range = offset .. offset + self.inner.size();

        Ok(CpuAccess {
            inner: unsafe { self.memory.mapped_memory().unwrap().read_write(range) },
            lock: submission,
        })
    }
}

unsafe impl<T: ?Sized, A> Buffer for CpuAccessibleBuffer<T, A>
    where T: 'static + Send + Sync, A: MemoryPool
{
    #[inline]
    fn inner_buffer(&self) -> &UnsafeBuffer {
        &self.inner
    }

    #[inline]
    fn blocks(&self, _: Range<usize>) -> Vec<usize> {
        vec![0]
    }

    #[inline]
    fn block_memory_range(&self, _: usize) -> Range<usize> {
        let offset = self.memory.offset();
        offset .. offset + self.size()
    }

    fn needs_fence(&self, _: bool, _: Range<usize>) -> Option<bool> {
        Some(true)
    }

    #[inline]
    fn host_accesses(&self, _: usize) -> bool {
        true
    }

    unsafe fn gpu_access(&self, _: &mut Iterator<Item = AccessRange>, submission: &Arc<Submission>)
                         -> GpuAccessResult
    {
        let queue_id = submission.queue().family().id();
        if self.queue_families.iter().find(|&&id| id == queue_id).is_none() {
            panic!("Trying to submit to family {} a buffer suitable for families {:?}",
                   queue_id, self.queue_families);
        }

        let dependency = {
            let mut latest_submission = self.latest_submission.lock().unwrap();
            mem::replace(&mut *latest_submission, Some(Arc::downgrade(submission)))
        };
        let dependency = dependency.and_then(|d| d.upgrade());

        GpuAccessResult {
            dependencies: if let Some(dependency) = dependency {
                vec![dependency]
            } else {
                vec![]
            },
            additional_wait_semaphore: None,
            additional_signal_semaphore: None,
        }
    }
}

unsafe impl<T: ?Sized, A> TypedBuffer for CpuAccessibleBuffer<T, A>
    where T: 'static + Send + Sync, A: MemoryPool
{
    type Content = T;
}

/// Object that can be used to read or write the content of a `CpuAccessBuffer`.
///
/// Note that this object holds a mutex guard on the chunk. If another thread tries to access
/// this buffer's content or tries to submit a GPU command that uses this buffer, it will block.
pub struct CpuAccess<'a, T: ?Sized + 'a> {
    inner: MemCpuAccess<'a, T>,
    lock: MutexGuard<'a, Option<Weak<Submission>>>,
}

impl<'a, T: ?Sized + 'a> CpuAccess<'a, T> {
    /// Makes a new `CpuAccess` to access a sub-part of the current `CpuAccess`.
    #[inline]
    pub fn map<U: ?Sized + 'a, F>(self, f: F) -> CpuAccess<'a, U>
        where F: FnOnce(&mut T) -> &mut U
    {
        CpuAccess {
            inner: self.inner.map(|ptr| unsafe { f(&mut *ptr) as *mut _ }),
            lock: self.lock,
        }
    }
}

impl<'a, T: ?Sized + 'a> Deref for CpuAccess<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.inner.deref()
    }
}

impl<'a, T: ?Sized + 'a> DerefMut for CpuAccess<'a, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        self.inner.deref_mut()
    }
}
<commit_msg>Differenciate reading and writing a CpuAccessBuffer<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Buffer whose content is accessible to the CPU.
//!
//! The `CpuAccessibleBuffer` is a basic general-purpose buffer. It can be used in any situation
//! but may not perform as well as other buffer types.
//!
//! Each access from the CPU or from the GPU locks the whole buffer for either reading or writing.
//! You can read the buffer multiple times simultaneously. Trying to read and write simultaneously,
//! or write and write simultaneously will block.

use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::ops::DerefMut;
use std::ops::Range;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::RwLock;
use std::sync::RwLockReadGuard;
use std::sync::RwLockWriteGuard;
use std::sync::Weak;
use std::time::Duration;
use smallvec::SmallVec;

use buffer::sys::UnsafeBuffer;
use buffer::sys::Usage;
use buffer::traits::AccessRange;
use buffer::traits::Buffer;
use buffer::traits::GpuAccessResult;
use buffer::traits::TypedBuffer;
use command_buffer::Submission;
use device::Device;
use instance::QueueFamily;
use memory::Content;
use memory::CpuAccess as MemCpuAccess;
use memory::pool::MemoryPool;
use memory::pool::MemoryPoolAlloc;
use memory::pool::StdMemoryPool;
use sync::FenceWaitError;
use sync::Sharing;

use OomError;

/// Buffer whose content is accessible by the CPU.
#[derive(Debug)]
pub struct CpuAccessibleBuffer<T: ?Sized, A = StdMemoryPool> where A: MemoryPool {
    // Inner content.
    inner: UnsafeBuffer,

    // The memory held by the buffer.
    memory: A::Alloc,

    // Queue families allowed to access this buffer.
    queue_families: SmallVec<[u32; 4]>,

    // Latest submission that uses this buffer.
    // Also used to block any attempt to submit this buffer while it is accessed by the CPU.
    latest_submission: RwLock<LatestSubmission>,

    // Necessary to make it compile.
    marker: PhantomData<Box<T>>,
}

#[derive(Debug)]
struct LatestSubmission {
    read_submissions: Mutex<Vec<Weak<Submission>>>,
    write_submission: Option<Weak<Submission>>,         // TODO: can use `Weak::new()` once it's stabilized
}

impl<T> CpuAccessibleBuffer<T> {
    /// Builds a new buffer. Only allowed for sized data.
    #[inline]
    pub fn new<'a, I>(device: &Arc<Device>, usage: &Usage, queue_families: I)
                      -> Result<Arc<CpuAccessibleBuffer<T>>, OomError>
        where I: IntoIterator<Item = QueueFamily<'a>>
    {
        unsafe {
            CpuAccessibleBuffer::raw(device, mem::size_of::<T>(), usage, queue_families)
        }
    }
}

impl<T> CpuAccessibleBuffer<[T]> {
    /// Builds a new buffer. Can be used for arrays.
    #[inline]
    pub fn array<'a, I>(device: &Arc<Device>, len: usize, usage: &Usage, queue_families: I)
                      -> Result<Arc<CpuAccessibleBuffer<[T]>>, OomError>
        where I: IntoIterator<Item = QueueFamily<'a>>
    {
        unsafe {
            CpuAccessibleBuffer::raw(device, len * mem::size_of::<T>(), usage, queue_families)
        }
    }
}

impl<T: ?Sized> CpuAccessibleBuffer<T> {
    /// Builds a new buffer without checking the size.
    ///
    /// # Safety
    ///
    /// You must ensure that the size that you pass is correct for `T`.
    ///
    pub unsafe fn raw<'a, I>(device: &Arc<Device>, size: usize, usage: &Usage, queue_families: I)
                             -> Result<Arc<CpuAccessibleBuffer<T>>, OomError>
        where I: IntoIterator<Item = QueueFamily<'a>>
    {
        let queue_families = queue_families.into_iter().map(|f| f.id())
                                           .collect::<SmallVec<[u32; 4]>>();

        let (buffer, mem_reqs) = {
            let sharing = if queue_families.len() >= 2 {
                Sharing::Concurrent(queue_families.iter().cloned())
            } else {
                Sharing::Exclusive
            };

            try!(UnsafeBuffer::new(device, size, &usage, sharing))
        };

        let mem_ty = device.physical_device().memory_types()
                           .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0)
                           .filter(|t| t.is_host_visible())
                           .next().unwrap();    // Vk specs guarantee that this can't fail

        let mem = try!(MemoryPool::alloc(&device.standard_pool(), mem_ty,
                                         mem_reqs.size, mem_reqs.alignment));
        debug_assert!((mem.offset() % mem_reqs.alignment) == 0);
        debug_assert!(mem.mapped_memory().is_some());
        try!(buffer.bind_memory(mem.memory(), mem.offset()));

        Ok(Arc::new(CpuAccessibleBuffer {
            inner: buffer,
            memory: mem,
            queue_families: queue_families,
            latest_submission: RwLock::new(LatestSubmission {
                read_submissions: Mutex::new(vec![]),
                write_submission: None,
            }),
            marker: PhantomData,
        }))
    }
}

impl<T: ?Sized, A> CpuAccessibleBuffer<T, A> where A: MemoryPool {
    /// Returns the device used to create this buffer.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }

    /// Returns the queue families this buffer can be used on.
    // TODO: use a custom iterator
    #[inline]
    pub fn queue_families(&self) -> Vec<QueueFamily> {
        self.queue_families.iter().map(|&num| {
            self.device().physical_device().queue_family_by_id(num).unwrap()
        }).collect()
    }
}

impl<T: ?Sized, A> CpuAccessibleBuffer<T, A> where T: Content + 'static, A: MemoryPool {
    /// Locks the buffer in order to write its content.
    ///
    /// If the buffer is currently in use by the GPU, this function will block until either the
    /// buffer is available or the timeout is reached. A value of `0` for the timeout is valid and
    /// means that the function should never block.
    ///
    /// After this function successfully locks the buffer, any attempt to submit a command buffer
    /// that uses it will block until you unlock it.
    // TODO: remove timeout parameter since CPU-side locking can't use it
    #[inline]
    pub fn read(&self, timeout: Duration) -> Result<ReadLock<T>, FenceWaitError> {
        let submission = self.latest_submission.read().unwrap();

        // TODO: should that set the write_submission to None?
        if let Some(submission) = submission.write_submission.clone().and_then(|s| s.upgrade()) {
            try!(submission.wait(timeout));
        }

        let offset = self.memory.offset();
        let range = offset .. offset + self.inner.size();

        Ok(ReadLock {
            inner: unsafe { self.memory.mapped_memory().unwrap().read_write(range) },
            lock: submission,
        })
    }

    /// Locks the buffer in order to write its content.
    ///
    /// If the buffer is currently in use by the GPU, this function will block until either the
    /// buffer is available or the timeout is reached. A value of `0` for the timeout is valid and
    /// means that the function should never block.
    ///
    /// After this function successfully locks the buffer, any attempt to submit a command buffer
    /// that uses it will block until you unlock it.
    // TODO: remove timeout parameter since CPU-side locking can't use it
    #[inline]
    pub fn write(&self, timeout: Duration) -> Result<WriteLock<T>, FenceWaitError> {
        let mut submission = self.latest_submission.write().unwrap();

        {
            let mut read_submissions = submission.read_submissions.get_mut().unwrap();
            for submission in read_submissions.drain(..) {
                if let Some(submission) = submission.upgrade() {
                    try!(submission.wait(timeout));
                }
            }
        }

        if let Some(submission) = submission.write_submission.take().and_then(|s| s.upgrade()) {
            try!(submission.wait(timeout));
        }

        let offset = self.memory.offset();
        let range = offset .. offset + self.inner.size();

        Ok(WriteLock {
            inner: unsafe { self.memory.mapped_memory().unwrap().read_write(range) },
            lock: submission,
        })
    }
}

unsafe impl<T: ?Sized, A> Buffer for CpuAccessibleBuffer<T, A>
    where T: 'static + Send + Sync, A: MemoryPool
{
    #[inline]
    fn inner_buffer(&self) -> &UnsafeBuffer {
        &self.inner
    }

    #[inline]
    fn blocks(&self, _: Range<usize>) -> Vec<usize> {
        vec![0]
    }

    #[inline]
    fn block_memory_range(&self, _: usize) -> Range<usize> {
        let offset = self.memory.offset();
        offset .. offset + self.size()
    }

    fn needs_fence(&self, _: bool, _: Range<usize>) -> Option<bool> {
        Some(true)
    }

    #[inline]
    fn host_accesses(&self, _: usize) -> bool {
        true
    }

    unsafe fn gpu_access(&self, ranges: &mut Iterator<Item = AccessRange>,
                         submission: &Arc<Submission>) -> GpuAccessResult
    {
        let queue_id = submission.queue().family().id();
        if self.queue_families.iter().find(|&&id| id == queue_id).is_none() {
            panic!("Trying to submit to family {} a buffer suitable for families {:?}",
                   queue_id, self.queue_families);
        }

        let is_written = {
            let mut written = false;
            while let Some(r) = ranges.next() { if r.write { written = true; break; } }
            written
        };

        let dependencies = if is_written {
            let mut submissions = self.latest_submission.write().unwrap();

            let write_dep = mem::replace(&mut submissions.write_submission,
                                         Some(Arc::downgrade(submission)));

            let mut read_submissions = submissions.read_submissions.get_mut().unwrap();
            let read_submissions = mem::replace(&mut *read_submissions, Vec::new());
            read_submissions.into_iter()
                            .chain(write_dep.into_iter())
                            .filter_map(|s| s.upgrade())
                            .collect::<Vec<_>>()

        } else {
            let submissions = self.latest_submission.read().unwrap();

            let mut read_submissions = submissions.read_submissions.lock().unwrap();
            read_submissions.push(Arc::downgrade(submission));

            submissions.write_submission.clone().and_then(|s| s.upgrade()).into_iter().collect()
        };

        GpuAccessResult {
            dependencies: dependencies,
            additional_wait_semaphore: None,
            additional_signal_semaphore: None,
        }
    }
}

unsafe impl<T: ?Sized, A> TypedBuffer for CpuAccessibleBuffer<T, A>
    where T: 'static + Send + Sync, A: MemoryPool
{
    type Content = T;
}

/// Object that can be used to read or write the content of a `CpuAccessBuffer`.
///
/// Note that this object holds a rwlock read guard on the chunk. If another thread tries to access
/// this buffer's content or tries to submit a GPU command that uses this buffer, it will block.
pub struct ReadLock<'a, T: ?Sized + 'a> {
    inner: MemCpuAccess<'a, T>,
    lock: RwLockReadGuard<'a, LatestSubmission>,
}

impl<'a, T: ?Sized + 'a> ReadLock<'a, T> {
    /// Makes a new `ReadLock` to access a sub-part of the current `ReadLock`.
    #[inline]
    pub fn map<U: ?Sized + 'a, F>(self, f: F) -> ReadLock<'a, U>
        where F: FnOnce(&mut T) -> &mut U
    {
        ReadLock {
            inner: self.inner.map(|ptr| unsafe { f(&mut *ptr) as *mut _ }),
            lock: self.lock,
        }
    }
}

impl<'a, T: ?Sized + 'a> Deref for ReadLock<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.inner.deref()
    }
}

/// Object that can be used to read or write the content of a `CpuAccessBuffer`.
///
/// Note that this object holds a rwlock write guard on the chunk. If another thread tries to access
/// this buffer's content or tries to submit a GPU command that uses this buffer, it will block.
pub struct WriteLock<'a, T: ?Sized + 'a> {
    inner: MemCpuAccess<'a, T>,
    lock: RwLockWriteGuard<'a, LatestSubmission>,
}

impl<'a, T: ?Sized + 'a> WriteLock<'a, T> {
    /// Makes a new `WriteLock` to access a sub-part of the current `WriteLock`.
    #[inline]
    pub fn map<U: ?Sized + 'a, F>(self, f: F) -> WriteLock<'a, U>
        where F: FnOnce(&mut T) -> &mut U
    {
        WriteLock {
            inner: self.inner.map(|ptr| unsafe { f(&mut *ptr) as *mut _ }),
            lock: self.lock,
        }
    }
}

impl<'a, T: ?Sized + 'a> Deref for WriteLock<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.inner.deref()
    }
}

impl<'a, T: ?Sized + 'a> DerefMut for WriteLock<'a, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        self.inner.deref_mut()
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Buffer whose content is accessible to the CPU.
//!
//! The `CpuAccessibleBuffer` is a basic general-purpose buffer. It can be used in any situation
//! but may not perform as well as other buffer types.
//!
//! Each access from the CPU or from the GPU locks the whole buffer.

use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::ops::DerefMut;
use std::ops::Range;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;
use std::sync::Weak;
use smallvec::SmallVec;

use buffer::sys::UnsafeBuffer;
use buffer::sys::Usage;
use buffer::traits::AccessRange;
use buffer::traits::Buffer;
use buffer::traits::GpuAccessResult;
use buffer::traits::TypedBuffer;
use command_buffer::Submission;
use device::Device;
use instance::QueueFamily;
use memory::Content;
use memory::CpuAccess as MemCpuAccess;
use memory::DeviceMemory;
use memory::MappedDeviceMemory;
use sync::FenceWaitError;
use sync::Sharing;

use OomError;

/// Buffer whose content is accessible by the CPU.
#[derive(Debug)]
pub struct CpuAccessibleBuffer<T: ?Sized> {
    // Inner content.
    inner: UnsafeBuffer,

    // The memory held by the buffer.
    memory: MappedDeviceMemory,

    // Queue families allowed to access this buffer.
    queue_families: SmallVec<[u32; 4]>,

    // Latest submission that uses this buffer.
    // Also used to block any attempt to submit this buffer while it is accessed by the CPU.
    latest_submission: Mutex<Option<Weak<Submission>>>,      // TODO: can use `Weak::new()` once it's stabilized

    // Necessary to make it compile.
    marker: PhantomData<*const T>,
}

impl<T> CpuAccessibleBuffer<T> {
    /// Builds a new buffer. Only allowed for sized data.
    #[inline]
    pub fn new<'a, I>(device: &Arc<Device>, usage: &Usage, queue_families: I)
                      -> Result<Arc<CpuAccessibleBuffer<T>>, OomError>
        where I: IntoIterator<Item = QueueFamily<'a>>
    {
        unsafe {
            CpuAccessibleBuffer::raw(device, mem::size_of::<T>(), usage, queue_families)
        }
    }
}

impl<T> CpuAccessibleBuffer<[T]> {
    /// Builds a new buffer. Can be used for arrays.
    #[inline]
    pub fn array<'a, I>(device: &Arc<Device>, len: usize, usage: &Usage, queue_families: I)
                      -> Result<Arc<CpuAccessibleBuffer<[T]>>, OomError>
        where I: IntoIterator<Item = QueueFamily<'a>>
    {
        unsafe {
            CpuAccessibleBuffer::raw(device, len * mem::size_of::<T>(), usage, queue_families)
        }
    }
}

impl<T: ?Sized> CpuAccessibleBuffer<T> {
    /// Builds a new buffer without checking the size.
    ///
    /// # Safety
    ///
    /// You must ensure that the size that you pass is correct for `T`.
    ///
    pub unsafe fn raw<'a, I>(device: &Arc<Device>, size: usize, usage: &Usage, queue_families: I)
                             -> Result<Arc<CpuAccessibleBuffer<T>>, OomError>
        where I: IntoIterator<Item = QueueFamily<'a>>
    {
        let queue_families = queue_families.into_iter().map(|f| f.id())
                                           .collect::<SmallVec<[u32; 4]>>();

        let (buffer, mem_reqs) = {
            let sharing = if queue_families.len() >= 2 {
                Sharing::Concurrent(queue_families.iter().cloned())
            } else {
                Sharing::Exclusive
            };

            try!(UnsafeBuffer::new(device, size, &usage, sharing))
        };

        let mem_ty = device.physical_device().memory_types()
                           .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0)
                           .filter(|t| t.is_host_visible())
                           .next().unwrap();    // Vk specs guarantee that this can't fail

        // note: alignment doesn't need to be checked because allocating memory is guaranteed to
        //       fulfill any alignment requirement

        let mem = try!(DeviceMemory::alloc_and_map(device, &mem_ty, mem_reqs.size));
        try!(buffer.bind_memory(mem.memory(), 0));

        Ok(Arc::new(CpuAccessibleBuffer {
            inner: buffer,
            memory: mem,
            queue_families: queue_families,
            latest_submission: Mutex::new(None),
            marker: PhantomData,
        }))
    }
}

impl<T: ?Sized> CpuAccessibleBuffer<T> where T: Content + 'static {
    /// Locks the buffer in order to write its content.
    ///
    /// If the buffer is currently in use by the GPU, this function will block until either the
    /// buffer is available or the timeout is reached. A value of `0` for the timeout is valid and
    /// means that the function should never block.
    ///
    /// After this function successfully locks the buffer, any attempt to submit a command buffer
    /// that uses it will block until you unlock it.
    // TODO: this could be misleading as there's no difference between `read` and `write`
    #[inline]
    pub fn read(&self, timeout_ns: u64) -> Result<CpuAccess<T>, FenceWaitError> {
        self.write(timeout_ns)
    }

    /// Locks the buffer in order to write its content.
    ///
    /// If the buffer is currently in use by the GPU, this function will block until either the
    /// buffer is available or the timeout is reached. A value of `0` for the timeout is valid and
    /// means that the function should never block.
    ///
    /// After this function successfully locks the buffer, any attempt to submit a command buffer
    /// that uses it will block until you unlock it.
    #[inline]
    pub fn write(&self, timeout_ns: u64) -> Result<CpuAccess<T>, FenceWaitError> {
        let submission = self.latest_submission.lock().unwrap();

        if let Some(submission) = submission.as_ref().and_then(|s| s.upgrade()) {
            try!(submission.wait(timeout_ns));
        }

        Ok(CpuAccess {
            inner: unsafe { self.memory.read_write() },
            lock: submission,
        })
    }
}

unsafe impl<T: ?Sized> Buffer for CpuAccessibleBuffer<T> {
    #[inline]
    fn inner_buffer(&self) -> &UnsafeBuffer {
        &self.inner
    }

    #[inline]
    fn blocks(&self, _: Range<usize>) -> Vec<usize> {
        vec![0]
    }

    #[inline]
    fn block_memory_range(&self, _: usize) -> Range<usize> {
        0 .. self.size()
    }

    fn needs_fence(&self, _: bool, _: Range<usize>) -> Option<bool> {
        Some(true)
    }

    #[inline]
    fn host_accesses(&self, _: usize) -> bool {
        true
    }

    unsafe fn gpu_access(&self, _: &mut Iterator<Item = AccessRange>, submission: &Arc<Submission>)
                         -> GpuAccessResult
    {
        let queue_id = submission.queue().family().id();
        if self.queue_families.iter().find(|&&id| id == queue_id).is_none() {
            panic!("Trying to submit to family {} a buffer suitable for families {:?}",
                   queue_id, self.queue_families);
        }

        let dependency = {
            let mut latest_submission = self.latest_submission.lock().unwrap();
            mem::replace(&mut *latest_submission, Some(Arc::downgrade(submission)))
        };
        let dependency = dependency.and_then(|d| d.upgrade());

        GpuAccessResult {
            dependencies: if let Some(dependency) = dependency {
                vec![dependency]
            } else {
                vec![]
            },
            additional_wait_semaphore: None,
            additional_signal_semaphore: None,
        }
    }
}

unsafe impl<T: ?Sized + 'static> TypedBuffer for CpuAccessibleBuffer<T> {
    type Content = T;
}

/// Object that can be used to read or write the content of a `CpuAccessBuffer`.
///
/// Note that this object holds a mutex guard on the chunk. If another thread tries to access
/// this buffer's content or tries to submit a GPU command that uses this buffer, it will block.
pub struct CpuAccess<'a, T: ?Sized + 'a> {
    inner: MemCpuAccess<'a, T>,
    lock: MutexGuard<'a, Option<Weak<Submission>>>,
}

impl<'a, T: ?Sized + 'a> Deref for CpuAccess<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.inner.deref()
    }
}

impl<'a, T: ?Sized + 'a> DerefMut for CpuAccess<'a, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        self.inner.deref_mut()
    }
}
<commit_msg>Add some getters on CpuAccessBuffer<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Buffer whose content is accessible to the CPU.
//!
//! The `CpuAccessibleBuffer` is a basic general-purpose buffer. It can be used in any situation
//! but may not perform as well as other buffer types.
//!
//! Each access from the CPU or from the GPU locks the whole buffer.

use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::ops::DerefMut;
use std::ops::Range;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;
use std::sync::Weak;
use smallvec::SmallVec;

use buffer::sys::UnsafeBuffer;
use buffer::sys::Usage;
use buffer::traits::AccessRange;
use buffer::traits::Buffer;
use buffer::traits::GpuAccessResult;
use buffer::traits::TypedBuffer;
use command_buffer::Submission;
use device::Device;
use instance::QueueFamily;
use memory::Content;
use memory::CpuAccess as MemCpuAccess;
use memory::DeviceMemory;
use memory::MappedDeviceMemory;
use sync::FenceWaitError;
use sync::Sharing;

use OomError;

/// Buffer whose content is accessible by the CPU.
#[derive(Debug)]
pub struct CpuAccessibleBuffer<T: ?Sized> {
    // Inner content.
    inner: UnsafeBuffer,

    // The memory held by the buffer.
    memory: MappedDeviceMemory,

    // Queue families allowed to access this buffer.
    queue_families: SmallVec<[u32; 4]>,

    // Latest submission that uses this buffer.
    // Also used to block any attempt to submit this buffer while it is accessed by the CPU.
    latest_submission: Mutex<Option<Weak<Submission>>>,      // TODO: can use `Weak::new()` once it's stabilized

    // Necessary to make it compile.
    marker: PhantomData<*const T>,
}

impl<T> CpuAccessibleBuffer<T> {
    /// Builds a new buffer. Only allowed for sized data.
    #[inline]
    pub fn new<'a, I>(device: &Arc<Device>, usage: &Usage, queue_families: I)
                      -> Result<Arc<CpuAccessibleBuffer<T>>, OomError>
        where I: IntoIterator<Item = QueueFamily<'a>>
    {
        unsafe {
            CpuAccessibleBuffer::raw(device, mem::size_of::<T>(), usage, queue_families)
        }
    }
}

impl<T> CpuAccessibleBuffer<[T]> {
    /// Builds a new buffer. Can be used for arrays.
    #[inline]
    pub fn array<'a, I>(device: &Arc<Device>, len: usize, usage: &Usage, queue_families: I)
                      -> Result<Arc<CpuAccessibleBuffer<[T]>>, OomError>
        where I: IntoIterator<Item = QueueFamily<'a>>
    {
        unsafe {
            CpuAccessibleBuffer::raw(device, len * mem::size_of::<T>(), usage, queue_families)
        }
    }
}

impl<T: ?Sized> CpuAccessibleBuffer<T> {
    /// Builds a new buffer without checking the size.
    ///
    /// # Safety
    ///
    /// You must ensure that the size that you pass is correct for `T`.
    ///
    pub unsafe fn raw<'a, I>(device: &Arc<Device>, size: usize, usage: &Usage, queue_families: I)
                             -> Result<Arc<CpuAccessibleBuffer<T>>, OomError>
        where I: IntoIterator<Item = QueueFamily<'a>>
    {
        let queue_families = queue_families.into_iter().map(|f| f.id())
                                           .collect::<SmallVec<[u32; 4]>>();

        let (buffer, mem_reqs) = {
            let sharing = if queue_families.len() >= 2 {
                Sharing::Concurrent(queue_families.iter().cloned())
            } else {
                Sharing::Exclusive
            };

            try!(UnsafeBuffer::new(device, size, &usage, sharing))
        };

        let mem_ty = device.physical_device().memory_types()
                           .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0)
                           .filter(|t| t.is_host_visible())
                           .next().unwrap();    // Vk specs guarantee that this can't fail

        // note: alignment doesn't need to be checked because allocating memory is guaranteed to
        //       fulfill any alignment requirement

        let mem = try!(DeviceMemory::alloc_and_map(device, &mem_ty, mem_reqs.size));
        try!(buffer.bind_memory(mem.memory(), 0));

        Ok(Arc::new(CpuAccessibleBuffer {
            inner: buffer,
            memory: mem,
            queue_families: queue_families,
            latest_submission: Mutex::new(None),
            marker: PhantomData,
        }))
    }
}

impl<T: ?Sized> CpuAccessibleBuffer<T> where T: Content + 'static {
    /// Locks the buffer in order to write its content.
    ///
    /// If the buffer is currently in use by the GPU, this function will block until either the
    /// buffer is available or the timeout is reached. A value of `0` for the timeout is valid and
    /// means that the function should never block.
    ///
    /// After this function successfully locks the buffer, any attempt to submit a command buffer
    /// that uses it will block until you unlock it.
    // TODO: this could be misleading as there's no difference between `read` and `write`
    #[inline]
    pub fn read(&self, timeout_ns: u64) -> Result<CpuAccess<T>, FenceWaitError> {
        self.write(timeout_ns)
    }

    /// Locks the buffer in order to write its content.
    ///
    /// If the buffer is currently in use by the GPU, this function will block until either the
    /// buffer is available or the timeout is reached. A value of `0` for the timeout is valid and
    /// means that the function should never block.
    ///
    /// After this function successfully locks the buffer, any attempt to submit a command buffer
    /// that uses it will block until you unlock it.
    #[inline]
    pub fn write(&self, timeout_ns: u64) -> Result<CpuAccess<T>, FenceWaitError> {
        let submission = self.latest_submission.lock().unwrap();

        if let Some(submission) = submission.as_ref().and_then(|s| s.upgrade()) {
            try!(submission.wait(timeout_ns));
        }

        Ok(CpuAccess {
            inner: unsafe { self.memory.read_write() },
            lock: submission,
        })
    }

    /// Returns the device used to create this buffer.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }

    /// Returns the queue families this buffer can be used on.
    // TODO: use a custom iterator
    #[inline]
    pub fn queue_families(&self) -> Vec<QueueFamily> {
        self.queue_families.iter().map(|&num| {
            self.device().physical_device().queue_family_by_id(num).unwrap()
        }).collect()
    }
}

unsafe impl<T: ?Sized> Buffer for CpuAccessibleBuffer<T> {
    #[inline]
    fn inner_buffer(&self) -> &UnsafeBuffer {
        &self.inner
    }

    #[inline]
    fn blocks(&self, _: Range<usize>) -> Vec<usize> {
        vec![0]
    }

    #[inline]
    fn block_memory_range(&self, _: usize) -> Range<usize> {
        0 .. self.size()
    }

    fn needs_fence(&self, _: bool, _: Range<usize>) -> Option<bool> {
        Some(true)
    }

    #[inline]
    fn host_accesses(&self, _: usize) -> bool {
        true
    }

    unsafe fn gpu_access(&self, _: &mut Iterator<Item = AccessRange>, submission: &Arc<Submission>)
                         -> GpuAccessResult
    {
        let queue_id = submission.queue().family().id();
        if self.queue_families.iter().find(|&&id| id == queue_id).is_none() {
            panic!("Trying to submit to family {} a buffer suitable for families {:?}",
                   queue_id, self.queue_families);
        }

        let dependency = {
            let mut latest_submission = self.latest_submission.lock().unwrap();
            mem::replace(&mut *latest_submission, Some(Arc::downgrade(submission)))
        };
        let dependency = dependency.and_then(|d| d.upgrade());

        GpuAccessResult {
            dependencies: if let Some(dependency) = dependency {
                vec![dependency]
            } else {
                vec![]
            },
            additional_wait_semaphore: None,
            additional_signal_semaphore: None,
        }
    }
}

unsafe impl<T: ?Sized + 'static> TypedBuffer for CpuAccessibleBuffer<T> {
    type Content = T;
}

/// Object that can be used to read or write the content of a `CpuAccessBuffer`.
///
/// Note that this object holds a mutex guard on the chunk. If another thread tries to access
/// this buffer's content or tries to submit a GPU command that uses this buffer, it will block.
pub struct CpuAccess<'a, T: ?Sized + 'a> {
    inner: MemCpuAccess<'a, T>,
    lock: MutexGuard<'a, Option<Weak<Submission>>>,
}

impl<'a, T: ?Sized + 'a> Deref for CpuAccess<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.inner.deref()
    }
}

impl<'a, T: ?Sized + 'a> DerefMut for CpuAccess<'a, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        self.inner.deref_mut()
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::iter;
use format::ClearValue;
use framebuffer::RenderPassDesc;
use framebuffer::RenderPassDescClearValues;
use framebuffer::LayoutAttachmentDescription;
use framebuffer::LayoutPassDescription;
use framebuffer::LayoutPassDependencyDescription;

/// Description of an empty render pass.
///
/// Can be used to create a render pass with one subpass and no attachment.
///
/// # Example
///
/// ```
/// use vulkano::framebuffer::EmptySinglePassRenderPassDesc;
/// use vulkano::framebuffer::RenderPassDesc;
///
/// # let device: std::sync::Arc<vulkano::device::Device> = return;
/// let rp = EmptySinglePassRenderPassDesc.build_render_pass(device.clone());
/// ```
///
/// # Clear value and attachments list
///
/// A render pass created from an `EmptySinglePassRenderPassDesc` accepts `()` for both the list
/// of attachments and the clear colors.
///
#[derive(Debug, Copy, Clone)]
pub struct EmptySinglePassRenderPassDesc;

unsafe impl RenderPassDesc for EmptySinglePassRenderPassDesc {
    #[inline]
    fn num_attachments(&self) -> usize {
        0
    }

    #[inline]
    fn attachment_desc(&self, num: usize) -> Option<LayoutAttachmentDescription> {
        None
    }

    #[inline]
    fn num_subpasses(&self) -> usize {
        1
    }

    #[inline]
    fn subpass_desc(&self, num: usize) -> Option<LayoutPassDescription> {
        if num == 0 {
            Some(LayoutPassDescription {
                color_attachments: vec![],
                depth_stencil: None,
                input_attachments: vec![],
                resolve_attachments: vec![],
                preserve_attachments: vec![],
            })
        } else {
            None
        }
    }

    #[inline]
    fn num_dependencies(&self) -> usize {
        0
    }

    #[inline]
    fn dependency_desc(&self, num: usize) -> Option<LayoutPassDependencyDescription> {
        None
    }

    #[inline]
    fn num_color_attachments(&self, subpass: u32) -> Option<u32> {
        if subpass == 0 {
            Some(0)
        } else {
            None
        }
    }

    #[inline]
    fn num_samples(&self, _: u32) -> Option<u32> {
        None
    }

    #[inline]
    fn has_depth_stencil_attachment(&self, subpass: u32) -> Option<(bool, bool)> {
        if subpass == 0 {
            Some((false, false))
        } else {
            None
        }
    }

    #[inline]
    fn has_depth(&self, subpass: u32) -> Option<bool> {
        if subpass == 0 {
            Some(false)
        } else {
            None
        }
    }

    #[inline]
    fn has_writable_depth(&self, subpass: u32) -> Option<bool> {
        if subpass == 0 {
            Some(false)
        } else {
            None
        }
    }

    #[inline]
    fn has_stencil(&self, subpass: u32) -> Option<bool> {
        if subpass == 0 {
            Some(false)
        } else {
            None
        }
    }

    #[inline]
    fn has_writable_stencil(&self, subpass: u32) -> Option<bool> {
        if subpass == 0 {
            Some(false)
        } else {
            None
        }
    }
}

unsafe impl RenderPassDescClearValues<Vec<ClearValue>> for EmptySinglePassRenderPassDesc {
    #[inline]
    fn convert_clear_values(&self, values: Vec<ClearValue>) -> Box<Iterator<Item = ClearValue>> {
        assert!(values.is_empty());     // TODO: error instead
        Box::new(iter::empty())
    }
}

unsafe impl RenderPassDescClearValues<()> for EmptySinglePassRenderPassDesc {
    #[inline]
    fn convert_clear_values(&self, values: ()) -> Box<Iterator<Item = ClearValue>> {
        Box::new(iter::empty())
    }
}
<commit_msg>Remove obsolete comment<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::iter;
use format::ClearValue;
use framebuffer::RenderPassDesc;
use framebuffer::RenderPassDescClearValues;
use framebuffer::LayoutAttachmentDescription;
use framebuffer::LayoutPassDescription;
use framebuffer::LayoutPassDependencyDescription;

/// Description of an empty render pass.
///
/// Can be used to create a render pass with one subpass and no attachment.
///
/// # Example
///
/// ```
/// use vulkano::framebuffer::EmptySinglePassRenderPassDesc;
/// use vulkano::framebuffer::RenderPassDesc;
///
/// # let device: std::sync::Arc<vulkano::device::Device> = return;
/// let rp = EmptySinglePassRenderPassDesc.build_render_pass(device.clone());
/// ```
///
#[derive(Debug, Copy, Clone)]
pub struct EmptySinglePassRenderPassDesc;

unsafe impl RenderPassDesc for EmptySinglePassRenderPassDesc {
    #[inline]
    fn num_attachments(&self) -> usize {
        0
    }

    #[inline]
    fn attachment_desc(&self, num: usize) -> Option<LayoutAttachmentDescription> {
        None
    }

    #[inline]
    fn num_subpasses(&self) -> usize {
        1
    }

    #[inline]
    fn subpass_desc(&self, num: usize) -> Option<LayoutPassDescription> {
        if num == 0 {
            Some(LayoutPassDescription {
                color_attachments: vec![],
                depth_stencil: None,
                input_attachments: vec![],
                resolve_attachments: vec![],
                preserve_attachments: vec![],
            })
        } else {
            None
        }
    }

    #[inline]
    fn num_dependencies(&self) -> usize {
        0
    }

    #[inline]
    fn dependency_desc(&self, num: usize) -> Option<LayoutPassDependencyDescription> {
        None
    }

    #[inline]
    fn num_color_attachments(&self, subpass: u32) -> Option<u32> {
        if subpass == 0 {
            Some(0)
        } else {
            None
        }
    }

    #[inline]
    fn num_samples(&self, _: u32) -> Option<u32> {
        None
    }

    #[inline]
    fn has_depth_stencil_attachment(&self, subpass: u32) -> Option<(bool, bool)> {
        if subpass == 0 {
            Some((false, false))
        } else {
            None
        }
    }

    #[inline]
    fn has_depth(&self, subpass: u32) -> Option<bool> {
        if subpass == 0 {
            Some(false)
        } else {
            None
        }
    }

    #[inline]
    fn has_writable_depth(&self, subpass: u32) -> Option<bool> {
        if subpass == 0 {
            Some(false)
        } else {
            None
        }
    }

    #[inline]
    fn has_stencil(&self, subpass: u32) -> Option<bool> {
        if subpass == 0 {
            Some(false)
        } else {
            None
        }
    }

    #[inline]
    fn has_writable_stencil(&self, subpass: u32) -> Option<bool> {
        if subpass == 0 {
            Some(false)
        } else {
            None
        }
    }
}

unsafe impl RenderPassDescClearValues<Vec<ClearValue>> for EmptySinglePassRenderPassDesc {
    #[inline]
    fn convert_clear_values(&self, values: Vec<ClearValue>) -> Box<Iterator<Item = ClearValue>> {
        assert!(values.is_empty());     // TODO: error instead
        Box::new(iter::empty())
    }
}

unsafe impl RenderPassDescClearValues<()> for EmptySinglePassRenderPassDesc {
    #[inline]
    fn convert_clear_values(&self, values: ()) -> Box<Iterator<Item = ClearValue>> {
        Box::new(iter::empty())
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate djinn;

use rand::Rng;
use djinn::ext::qlearning::{QLearner, QLearnerParams};

#[derive(Debug, Hash, PartialEq, Eq, Clone)]
struct State {
    x: usize,
    y: usize
}

#[derive(Debug, Hash, PartialEq, Eq, Clone)]
enum Action {
    Left,
    Right,
    Up,
    Down
}

struct Environment {
    map: Vec<Vec<f64>>
}

struct Explorer {
    state: State,
    env: Environment,
    qlp: QLearnerParams<State, Action>,
}

impl Explorer {
    fn reset(&mut self) {
        self.state.x = self.qlp.rng.gen_range(0, self.env.map[0].len() - 1);
        self.state.y = self.qlp.rng.gen_range(0, self.env.map.len() - 1);
    }
}

impl QLearner for Explorer {
    type State = State;
    type Action = Action;

    fn reward(&self, state: &State) -> f64 {
        // -1 so each step is a penalty
        self.env.map[state.y][state.x] - 1.
    }

    fn actions(&self, state: &State) -> Vec<Action> {
        let mut actions = Vec::new();
        if state.x > 0 {
            actions.push(Action::Left);
        }
        if state.x < self.env.map[0].len() - 1 {
            actions.push(Action::Right);
        }
        if state.y > 0 {
            actions.push(Action::Up);
        }
        if state.y < self.env.map.len() - 1 {
            actions.push(Action::Down);
        }
        actions
    }

    fn params(&mut self) -> &mut QLearnerParams<State, Action> {
        &mut self.qlp
    }
}

fn main() {
    let map = vec![
        vec![ 0., 0., 1.,-1.],
        vec![-1., 0.,-1., 0.],
        vec![ 0., 0.,-1., 0.],
        vec![ 0., 0., 0., 0.]
    ];

    let env = Environment {
        map: map
    };

    let mut explorer = Explorer {
        state: State {x: 0, y: 0},
        env: env,
        qlp: QLearnerParams::new(0.5, 0.5, 0.5)
    };

    let n_episodes = 100;
    for _ in 0..n_episodes {
        explorer.reset();
        let mut i = 0;
        let mut reward = 0.;
        loop {
            println!("----STEP: {:?}", i);
            let s = explorer.state.clone();
            println!("state: {:?}", s);
            let r = explorer.reward(&s);
            println!("reward: {:?}", r);
            let action = explorer.choose_action(&s);
            println!("action: {:?}", action);
            reward += r;
            if r >= 0. {
                break;
            } else {
                match action {
                    Action::Up => explorer.state.y -= 1,
                    Action::Down => explorer.state.y += 1,
                    Action::Right => explorer.state.x += 1,
                    Action::Left => explorer.state.x -= 1
                }
            }
            i += 1;
        }
        println!("----DONE EPISODE: {:?}", reward);
        println!("Q: {:?}", explorer.qlp.q);
    }
}
<commit_msg>documented qlearning example better<commit_after>//! # Q-Learning example
//! A simple demonstration of using Djinn's Q-learner.
//! Creates a Q-learning agent in a small grid world that
//! learns to find the fastest and safest path to a reward.

extern crate rand;
extern crate djinn;

use rand::Rng;
use djinn::ext::qlearning::{QLearner, QLearnerParams};

/// Explorer state is just its x, y position.
#[derive(Debug, Hash, PartialEq, Eq, Clone)]
struct State {
    x: usize,
    y: usize,
}

#[derive(Debug, Hash, PartialEq, Eq, Clone)]
enum Action {
    Left,
    Right,
    Up,
    Down,
}

struct Environment {
    map: Vec<Vec<f64>>,
}

struct Explorer {
    state: State,
    env: Environment,
    qlp: QLearnerParams<State, Action>,
}

impl Explorer {
    /// Reset the explorer's state.
    fn reset(&mut self) {
        self.state.x = self.qlp.rng.gen_range(0, self.env.map[0].len() - 1);
        self.state.y = self.qlp.rng.gen_range(0, self.env.map.len() - 1);
    }
}

impl QLearner for Explorer {
    type State = State;
    type Action = Action;

    /// Reward for a given state.
    fn reward(&self, state: &State) -> f64 {
        // -1 so each step is a penalty
        self.env.map[state.y][state.x] - 1.
    }

    /// Actions are limited by the bounds of the map;
    /// i.e. this is a non-toroidal space.
    /// So just check to see which moves are valid.
    fn actions(&self, state: &State) -> Vec<Action> {
        let mut actions = Vec::new();
        if state.x > 0 {
            actions.push(Action::Left);
        }
        if state.x < self.env.map[0].len() - 1 {
            actions.push(Action::Right);
        }
        if state.y > 0 {
            actions.push(Action::Up);
        }
        if state.y < self.env.map.len() - 1 {
            actions.push(Action::Down);
        }
        actions
    }

    fn params(&mut self) -> &mut QLearnerParams<State, Action> {
        &mut self.qlp
    }
}

fn main() {
    let map = vec![vec![0., 0., 1., -1.],
                   vec![-1., 0., -1., 0.],
                   vec![0., 0., -1., 0.],
                   vec![0., 0., 0., 0.]];

    let env = Environment { map: map };

    let mut explorer = Explorer {
        state: State { x: 0, y: 0 },
        env: env,
        qlp: QLearnerParams::new(0.5, 0.5, 0.5),
    };

    let n_episodes = 100;
    for _ in 0..n_episodes {
        explorer.reset();
        let mut i = 0;
        let mut reward = 0.;
        loop {
            println!("----STEP: {:?}", i);
            let s = explorer.state.clone();
            println!("state: {:?}", s);
            let r = explorer.reward(&s);
            println!("reward: {:?}", r);
            let action = explorer.choose_action(&s);
            println!("action: {:?}", action);
            reward += r;

            // episode is done when the explorer
            // finds the positive reward
            if r >= 0. {
                break;
            } else {
                // update state based on action;
                // i.e. move
                match action {
                    Action::Up => explorer.state.y -= 1,
                    Action::Down => explorer.state.y += 1,
                    Action::Right => explorer.state.x += 1,
                    Action::Left => explorer.state.x -= 1,
                }
            }
            i += 1;
        }
        println!("----DONE EPISODE: {:?}", reward);
        println!("Q: {:?}", explorer.qlp.q);
    }
}
<|endoftext|>