From 28e5511722905a173b3ccdb439d6578b6a34d8a1 Mon Sep 17 00:00:00 2001 From: critiqjo Date: Fri, 20 May 2016 03:00:12 +0530 Subject: [PATCH 1/3] count: Use unbox instead of Box's special case --- src/count.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/count.rs b/src/count.rs index cf792dc..c048202 100644 --- a/src/count.rs +++ b/src/count.rs @@ -24,6 +24,7 @@ use BinaryTree; use WalkAction; use iter::Iter as GenIter; use iter::IntoIter as GenIntoIter; +use unbox::Unbox; pub type NodePtr = Box>; @@ -220,6 +221,7 @@ impl CountTree { *ret = node.try_remove(|node, _| node.rebalance()); }, |node, _| node.rebalance()) + .map(|p| p.unbox()) .unwrap() .into_value() } else if index + 1 == len { @@ -234,7 +236,7 @@ impl CountTree { if self.is_empty() { None } else if self.len() == 1 { - Some(self.0.take().unwrap().into_value()) + Some(self.0.take().map(|p| p.unbox()).unwrap().into_value()) } else { let root = self.root_must(); Some(root.walk_extract(|_| WalkAction::Left, @@ -245,6 +247,7 @@ impl CountTree { } }, |node, _| node.rebalance()) + .map(|p| p.unbox()) .unwrap() .into_value()) } @@ -256,7 +259,7 @@ impl CountTree { if self.is_empty() { None } else if self.len() == 1 { - Some(self.0.take().unwrap().into_value()) + Some(self.0.take().map(|p| p.unbox()).unwrap().into_value()) } else { let root = self.root_must(); Some(root.walk_extract(|_| WalkAction::Right, @@ -267,6 +270,7 @@ impl CountTree { } }, |node, _| node.rebalance()) + .map(|p| p.unbox()) .unwrap() .into_value()) } From 230f5087dcdc98e9c58f839665df79d07f270ce3 Mon Sep 17 00:00:00 2001 From: critiqjo Date: Fri, 20 May 2016 02:58:35 +0530 Subject: [PATCH 2/3] cow: impl Unbox, Debug for *rcCow --- src/cow.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/cow.rs b/src/cow.rs index 0841774..fbda551 100644 --- a/src/cow.rs +++ b/src/cow.rs @@ -3,11 +3,14 @@ //! Thin wrappers around the standard library ref-counted pointers that clones //! on `DerefMut` if reference count is greater than 1. +use std::fmt; use std::ops::Deref; use std::ops::DerefMut; use std::rc::Rc; use std::sync::Arc; +use unbox::Unbox; + pub struct RcCow(pub Rc); impl RcCow { @@ -36,6 +39,20 @@ impl DerefMut for RcCow { } } +impl Unbox for RcCow { + type Target = T; + + fn unbox(self) -> T { + self.0.unbox() + } +} + +impl fmt::Debug for RcCow { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + pub struct ArcCow(pub Arc); impl ArcCow { @@ -63,3 +80,17 @@ impl DerefMut for ArcCow { Arc::make_mut(&mut self.0) } } + +impl Unbox for ArcCow { + type Target = T; + + fn unbox(self) -> T { + self.0.unbox() + } +} + +impl fmt::Debug for ArcCow { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} From fcd7a51190dc040ea63be6bd85133929a1eb2d30 Mon Sep 17 00:00:00 2001 From: critiqjo Date: Fri, 20 May 2016 03:22:09 +0530 Subject: [PATCH 3/3] count: thread-shareable --- src/count.rs | 76 +++++++++++++++++++--------------------------------- 1 file changed, 28 insertions(+), 48 deletions(-) diff --git a/src/count.rs b/src/count.rs index c048202..9ac171b 100644 --- a/src/count.rs +++ b/src/count.rs @@ -22,11 +22,12 @@ use Node; use NodeMut; use BinaryTree; use WalkAction; +use cow::ArcCow; use iter::Iter as GenIter; use iter::IntoIter as GenIntoIter; use unbox::Unbox; -pub type NodePtr = Box>; +pub type NodePtr = ArcCow>; macro_rules! index_walker { ($index:ident, $node:ident, $up_count:ident, $stop:block) => { @@ -79,9 +80,10 @@ macro_rules! index_walker { /// assert_eq!(ct.remove(32), 32); /// # } /// ``` -pub struct CountTree(Option>); +#[derive(Clone)] +pub struct CountTree(Option>); -impl CountTree { +impl CountTree { fn root_must(&mut self) -> &mut CountNode { &mut **self.0.as_mut().unwrap() } @@ -158,7 +160,7 @@ impl CountTree { if index == 0 { self.push_front(value); } else if index < len { - let new_node = Box::new(CountNode::new(value)); + let new_node = ArcCow::new(CountNode::new(value)); let mut up_count = 0; let root = self.root_must(); root.walk_reshape(|node| index_walker!(index, node, up_count, {}), @@ -176,7 +178,7 @@ impl CountTree { /// Prepends an element at the beginning. pub fn push_front(&mut self, value: T) { - let new_node = Box::new(CountNode::new(value)); + let new_node = ArcCow::new(CountNode::new(value)); if self.is_empty() { self.0 = Some(new_node); } else { @@ -190,7 +192,7 @@ impl CountTree { /// Appends an element at the end. pub fn push_back(&mut self, value: T) { - let new_node = Box::new(CountNode::new(value)); + let new_node = ArcCow::new(CountNode::new(value)); if self.is_empty() { self.0 = Some(new_node); } else { @@ -280,7 +282,7 @@ impl CountTree { // TODO { O(n) } truncate, append, split_off, retain } -impl BinaryTree for CountTree { +impl BinaryTree for CountTree { type Node = CountNode; fn root(&self) -> Option<&Self::Node> { @@ -288,7 +290,7 @@ impl BinaryTree for CountTree { } } -impl Debug for CountTree +impl Debug for CountTree where T: Debug { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { @@ -306,7 +308,7 @@ impl Debug for CountTree } } -impl Drop for CountTree { +impl Drop for CountTree { fn drop(&mut self) { self.clear(); } @@ -335,7 +337,7 @@ fn exp_floor_log(v: u32) -> u32 { } } -impl FromIterator for CountTree { +impl FromIterator for CountTree { /// Time complexity: Θ(n + log2(n)) fn from_iter(iterable: I) -> Self where I: IntoIterator @@ -344,10 +346,10 @@ impl FromIterator for CountTree { let mut iter = iterable.into_iter(); if let Some(item) = iter.next() { - let mut node = Box::new(CountNode::new(item)); + let mut node = ArcCow::new(CountNode::new(item)); let mut count = 1; for item in iter { - let mut new_node = Box::new(CountNode::new(item)); + let mut new_node = ArcCow::new(CountNode::new(item)); new_node.insert_left(Some(node)); node = new_node; count += 1; @@ -389,7 +391,7 @@ impl FromIterator for CountTree { } } -impl<'a, T> IntoIterator for &'a CountTree { +impl<'a, T: Clone> IntoIterator for &'a CountTree { type Item = &'a T; type IntoIter = Iter<'a, T>; @@ -423,7 +425,7 @@ impl<'a, T> Iterator for Iter<'a, T> { impl<'a, T> ExactSizeIterator for Iter<'a, T> {} -impl IntoIterator for CountTree { +impl IntoIterator for CountTree { type Item = T; type IntoIter = IntoIter; @@ -438,12 +440,12 @@ impl IntoIterator for CountTree { } } -pub struct IntoIter { +pub struct IntoIter { inner: GenIntoIter>, remaining: usize, } -impl Iterator for IntoIter { +impl Iterator for IntoIter { type Item = T; fn next(&mut self) -> Option { @@ -458,7 +460,7 @@ impl Iterator for IntoIter { } } -impl ExactSizeIterator for IntoIter {} +impl ExactSizeIterator for IntoIter {} /// Node of a `CountTree`. /// @@ -466,6 +468,7 @@ impl ExactSizeIterator for IntoIter {} /// [`CountTree::root()`](struct.CountTree.html#method.root) method which /// returns a shared reference to its root. Thus `NodeMut` methods are not /// accessible to users. +#[derive(Clone)] pub struct CountNode { val: T, left: Option>, @@ -474,7 +477,7 @@ pub struct CountNode { height: u16, } -impl CountNode { +impl CountNode { fn new(val: T) -> CountNode { CountNode { val: val, @@ -550,7 +553,7 @@ impl Node for CountNode { } } -impl NodeMut for CountNode { +impl NodeMut for CountNode { type NodePtr = NodePtr; fn detach_left(&mut self) -> Option { @@ -637,30 +640,6 @@ impl Arbitrary for CountTree { } } -#[cfg(feature="quickcheck")] -impl Clone for CountTree - where T: Clone -{ - fn clone(&self) -> Self { - CountTree(self.0.clone()) - } -} - -#[cfg(feature="quickcheck")] -impl Clone for CountNode - where T: Clone -{ - fn clone(&self) -> Self { - CountNode { - val: self.val.clone(), - left: self.left.clone(), - right: self.right.clone(), - count: self.count, - height: self.height, - } - } -} - #[cfg(feature="quickcheck")] pub mod quickcheck { use super::CountTree; @@ -731,14 +710,15 @@ mod tests { use NodeMut; use super::CountNode; use super::CountTree; + use cow::ArcCow; use test::compute_level; use test::Level; - fn test_nodes() -> Box> { - let mut cn = Box::new(CountNode::new(7)); - cn.insert_before(Box::new(CountNode::new(8)), |_, _| ()); - cn.insert_before(Box::new(CountNode::new(12)), |_, _| ()); - cn.insert_right(Some(Box::new(CountNode::new(5)))); + fn test_nodes() -> ArcCow> { + let mut cn = ArcCow::new(CountNode::new(7)); + cn.insert_before(ArcCow::new(CountNode::new(8)), |_, _| ()); + cn.insert_before(ArcCow::new(CountNode::new(12)), |_, _| ()); + cn.insert_right(Some(ArcCow::new(CountNode::new(5)))); cn }