Commit 8ded09ad by Danila Klimenko

chromatic_tree: Bug fuxes, additional tests

parent 6ec6101f
...@@ -36,7 +36,7 @@ namespace internal { ...@@ -36,7 +36,7 @@ namespace internal {
template<typename Key, typename Value> template<typename Key, typename Value>
ChromaticTreeNode<Key, Value>:: ChromaticTreeNode<Key, Value>::
ChromaticTreeNode(const Key& key, const Value& value, const int& weight, ChromaticTreeNode(const Key& key, const Value& value, const int weight,
ChromaticTreeNode<Key, Value>* const & left, ChromaticTreeNode<Key, Value>* const & left,
ChromaticTreeNode<Key, Value>* const & right) ChromaticTreeNode<Key, Value>* const & right)
: key_(key), : key_(key),
...@@ -47,10 +47,10 @@ ChromaticTreeNode(const Key& key, const Value& value, const int& weight, ...@@ -47,10 +47,10 @@ ChromaticTreeNode(const Key& key, const Value& value, const int& weight,
template<typename Key, typename Value> template<typename Key, typename Value>
ChromaticTreeNode<Key, Value>:: ChromaticTreeNode<Key, Value>::
ChromaticTreeNode(const Key& key, const Value& value) ChromaticTreeNode(const Key& key, const Value& value, const int weight)
: key_(key), : key_(key),
value_(value), value_(value),
weight_(1), weight_(weight),
left_(NULL), left_(NULL),
right_(NULL) {} right_(NULL) {}
...@@ -74,7 +74,7 @@ const Value& ChromaticTreeNode<Key, Value>::GetValue() const { ...@@ -74,7 +74,7 @@ const Value& ChromaticTreeNode<Key, Value>::GetValue() const {
} }
template<typename Key, typename Value> template<typename Key, typename Value>
const int& ChromaticTreeNode<Key, Value>::GetWeight() const { int ChromaticTreeNode<Key, Value>::GetWeight() const {
return weight_; return weight_;
} }
...@@ -150,19 +150,21 @@ TryInsert(const Key& key, const Value& value, Value& old_value) { ...@@ -150,19 +150,21 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
NodePtr new_parent; NodePtr new_parent;
bool added_violation = false; bool added_violation = false;
NodePtr new_leaf = node_pool_.Allocate(key, value);
if (new_leaf == NULL) {
return false;
}
bool keys_are_equal = !(compare_(key, leaf->GetKey()) || bool keys_are_equal = !(compare_(key, leaf->GetKey()) ||
compare_(leaf->GetKey(), key)); compare_(leaf->GetKey(), key));
if (!IsSentinel(leaf) && keys_are_equal) { if (!IsSentinel(leaf) && keys_are_equal) {
old_value = leaf->GetValue(); old_value = leaf->GetValue();
new_parent = new_leaf; new_parent = node_pool_.Allocate(key, value, leaf->GetWeight());
if (new_parent == NULL) {
return false;
}
} else { } else {
old_value = undefined_value_; old_value = undefined_value_;
NodePtr new_leaf = node_pool_.Allocate(key, value);
if (new_leaf == NULL) {
return false;
}
NodePtr new_sibling = node_pool_.Allocate(*leaf); NodePtr new_sibling = node_pool_.Allocate(*leaf);
if (new_sibling == NULL) { if (new_sibling == NULL) {
node_pool_.Free(new_leaf); node_pool_.Free(new_leaf);
...@@ -679,6 +681,34 @@ GetHeight(const NodePtr& node) const { ...@@ -679,6 +681,34 @@ GetHeight(const NodePtr& node) const {
return height; return height;
} }
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
IsBalanced() const {
return IsBalanced(entry_->GetLeft());
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
IsBalanced(const NodePtr& node) const {
// Overweight violation
bool has_violation = node->GetWeight() > 1;
if (!has_violation && !IsLeaf(node)) {
NodePtr left = node->GetLeft();
NodePtr right = node->GetRight();
// Red-red violation
has_violation = node->GetWeight() == 0 &&
(left->GetWeight() == 0 || right->GetWeight() == 0);
// Check children
if (!has_violation) {
has_violation = !IsBalanced(left) || !IsBalanced(right);
}
}
return !has_violation;
}
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, NodePool>::
......
...@@ -57,7 +57,7 @@ class ChromaticTreeNode { ...@@ -57,7 +57,7 @@ class ChromaticTreeNode {
* \param[IN] left Pointer to the left child node * \param[IN] left Pointer to the left child node
* \param[IN] right Pointer to the right child node * \param[IN] right Pointer to the right child node
*/ */
ChromaticTreeNode(const Key& key, const Value& value, const int& weight, ChromaticTreeNode(const Key& key, const Value& value, const int weight,
ChromaticTreeNode<Key, Value>* const & left, ChromaticTreeNode<Key, Value>* const & left,
ChromaticTreeNode<Key, Value>* const & right); ChromaticTreeNode<Key, Value>* const & right);
...@@ -68,7 +68,7 @@ class ChromaticTreeNode { ...@@ -68,7 +68,7 @@ class ChromaticTreeNode {
* \param[IN] key Key of the new node * \param[IN] key Key of the new node
* \param[IN] value Value of the new node * \param[IN] value Value of the new node
*/ */
ChromaticTreeNode(const Key& key, const Value& value); ChromaticTreeNode(const Key& key, const Value& value, const int weight = 1);
/** /**
* Creates a copy of a given node. * Creates a copy of a given node.
...@@ -97,7 +97,7 @@ class ChromaticTreeNode { ...@@ -97,7 +97,7 @@ class ChromaticTreeNode {
* *
* \return Weight of the node * \return Weight of the node
*/ */
const int& GetWeight() const; int GetWeight() const;
/** /**
* Accessor for the left child pointer. * Accessor for the left child pointer.
...@@ -123,6 +123,14 @@ class ChromaticTreeNode { ...@@ -123,6 +123,14 @@ class ChromaticTreeNode {
} // namespace internal } // namespace internal
namespace test {
/**
* Forward declaration of the test class
*/
template<typename Tree>
class TreeTest;
} // namespace test
/** /**
* Chromatic balanced binary search tree * Chromatic balanced binary search tree
...@@ -148,6 +156,15 @@ template<typename Key, ...@@ -148,6 +156,15 @@ template<typename Key,
class ChromaticTree { class ChromaticTree {
public: public:
/** /**
* Exposing the \c Key template parameter back to the user
*/
typedef Key KeyType;
/**
* Exposing the \c Value template parameter back to the user
*/
typedef Value ValueType;
/**
* Creates a new tree with given capacity. * Creates a new tree with given capacity.
* *
* \memory Allocates <tt>(2 * capacity + 7)</tt> tree nodes each of size * \memory Allocates <tt>(2 * capacity + 7)</tt> tree nodes each of size
...@@ -447,7 +464,14 @@ class ChromaticTree { ...@@ -447,7 +464,14 @@ class ChromaticTree {
const NodePtr& uxl, const NodePtr& uxr); const NodePtr& uxl, const NodePtr& uxr);
/** /**
* Friending the test class for white-box testing
*/
friend class test::TreeTest<ChromaticTree<Key, Value, Compare, NodePool> >;
/**
* Computes the hight of the subtree rooted at the given node. * Computes the hight of the subtree rooted at the given node.
*
* \notthreadsafe
* *
* \param[IN] node Root of the subtree for which the height is requested * \param[IN] node Root of the subtree for which the height is requested
* *
...@@ -456,6 +480,9 @@ class ChromaticTree { ...@@ -456,6 +480,9 @@ class ChromaticTree {
*/ */
int GetHeight(const NodePtr& node) const; int GetHeight(const NodePtr& node) const;
bool IsBalanced() const;
bool IsBalanced(const NodePtr& node) const;
const Key undefined_key_; /**< A dummy key used by the tree */ const Key undefined_key_; /**< A dummy key used by the tree */
const Value undefined_value_; /**< A dummy value used by the tree */ const Value undefined_value_; /**< A dummy value used by the tree */
const Compare compare_; /**< Comparator object for the keys */ const Compare compare_; /**< Comparator object for the keys */
......
...@@ -37,32 +37,52 @@ class TreeTest : public partest::TestCase { ...@@ -37,32 +37,52 @@ class TreeTest : public partest::TestCase {
TreeTest(); TreeTest();
private: private:
typedef Tree* TreePtr;
typedef typename Tree::KeyType Key;
typedef typename Tree::ValueType Value;
typedef ::std::pair<Key, Value> Element;
typedef ::std::vector<Element> ElementVector;
typedef typename ElementVector::iterator ElementIterator;
class Worker { class Worker {
public: public:
Worker(Tree& tree, size_t thread_id, int num_elements); Worker(TreePtr tree, int thread_id);
void Run(); void InsertReplaceDelete(int num_elements);
void PrepareElements(int num_elements);
void InsertAll();
void ReplaceHalf();
void DeleteAll();
void DeleteHalf();
private: private:
Tree& tree_; Worker(const Worker&);
size_t thread_id_; Worker& operator=(const Worker&);
int num_elements_;
};
typedef int Key; TreePtr tree_;
typedef int Value; int thread_id_;
typedef ::std::pair<Key, Value> Element; ElementVector elements_;
typedef ::std::vector<Element> ElementVector; };
typedef ElementVector::iterator ElementIterator;
static const int TREE_CAPACITY = 2000; static const int TREE_CAPACITY = 100;
static const int NUM_TEST_THREADS = 3; static const int NUM_TEST_THREADS = 4;
static const int NUM_ITERATIONS = 100;
void TreeTestSingleThreadInsertDelete_Pre(); void TreeTestInsertDelete_Pre();
void TreeTestSingleThreadInsertDelete_ThreadMethod(); void TreeTestInsertDeleteSingleThread_ThreadMethod();
void TreeTestMultiThreadInsertDelete_ThreadMethod(); void TreeTestInsertDeleteMultiThread_ThreadMethod();
void TreeTestSingleThreadInsertDelete_Post(); void TreeTestInsertDelete_Post();
void TreeTestConcurrentGet_Pre();
void TreeTestConcurrentGetMinimal_Pre();
void TreeTestConcurrentGet_WriterMethod();
void TreeTestConcurrentGet_ReaderMethod();
void TreeTestConcurrentGet_Post();
void TreeTestBalance_Pre();
void TreeTestBalance_ThreadMethod();
void TreeTestBalance_Post();
Tree *tree_; TreePtr tree_;
Key bad_key_;
Value bad_value_;
}; };
} // namespace test } // namespace test
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment