Commit 8ded09ad by Danila Klimenko

chromatic_tree: Bug fuxes, additional tests

parent 6ec6101f
......@@ -36,7 +36,7 @@ namespace internal {
template<typename Key, typename 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 & right)
: key_(key),
......@@ -47,10 +47,10 @@ ChromaticTreeNode(const Key& key, const Value& value, const int& weight,
template<typename Key, typename Value>
ChromaticTreeNode<Key, Value>::
ChromaticTreeNode(const Key& key, const Value& value)
ChromaticTreeNode(const Key& key, const Value& value, const int weight)
: key_(key),
value_(value),
weight_(1),
weight_(weight),
left_(NULL),
right_(NULL) {}
......@@ -74,7 +74,7 @@ const Value& ChromaticTreeNode<Key, Value>::GetValue() const {
}
template<typename Key, typename Value>
const int& ChromaticTreeNode<Key, Value>::GetWeight() const {
int ChromaticTreeNode<Key, Value>::GetWeight() const {
return weight_;
}
......@@ -150,19 +150,21 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
NodePtr new_parent;
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()) ||
compare_(leaf->GetKey(), key));
if (!IsSentinel(leaf) && keys_are_equal) {
old_value = leaf->GetValue();
new_parent = new_leaf;
new_parent = node_pool_.Allocate(key, value, leaf->GetWeight());
if (new_parent == NULL) {
return false;
}
} else {
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);
if (new_sibling == NULL) {
node_pool_.Free(new_leaf);
......@@ -679,6 +681,34 @@ GetHeight(const NodePtr& node) const {
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>
bool ChromaticTree<Key, Value, Compare, NodePool>::
......
......@@ -57,7 +57,7 @@ class ChromaticTreeNode {
* \param[IN] left Pointer to the left 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 & right);
......@@ -68,7 +68,7 @@ class ChromaticTreeNode {
* \param[IN] key Key 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.
......@@ -97,7 +97,7 @@ class ChromaticTreeNode {
*
* \return Weight of the node
*/
const int& GetWeight() const;
int GetWeight() const;
/**
* Accessor for the left child pointer.
......@@ -123,6 +123,14 @@ class ChromaticTreeNode {
} // namespace internal
namespace test {
/**
* Forward declaration of the test class
*/
template<typename Tree>
class TreeTest;
} // namespace test
/**
* Chromatic balanced binary search tree
......@@ -148,6 +156,15 @@ template<typename Key,
class ChromaticTree {
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.
*
* \memory Allocates <tt>(2 * capacity + 7)</tt> tree nodes each of size
......@@ -447,8 +464,15 @@ class ChromaticTree {
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.
*
* \notthreadsafe
*
* \param[IN] node Root of the subtree for which the height is requested
*
* \return The height of a subtree rooted at node \c node. (The height of a
......@@ -456,6 +480,9 @@ class ChromaticTree {
*/
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 Value undefined_value_; /**< A dummy value used by the tree */
const Compare compare_; /**< Comparator object for the keys */
......
......@@ -37,32 +37,52 @@ class TreeTest : public partest::TestCase {
TreeTest();
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 {
public:
Worker(Tree& tree, size_t thread_id, int num_elements);
void Run();
Worker(TreePtr tree, int thread_id);
void InsertReplaceDelete(int num_elements);
void PrepareElements(int num_elements);
void InsertAll();
void ReplaceHalf();
void DeleteAll();
void DeleteHalf();
private:
Tree& tree_;
size_t thread_id_;
int num_elements_;
};
Worker(const Worker&);
Worker& operator=(const Worker&);
typedef int Key;
typedef int Value;
typedef ::std::pair<Key, Value> Element;
typedef ::std::vector<Element> ElementVector;
typedef ElementVector::iterator ElementIterator;
TreePtr tree_;
int thread_id_;
ElementVector elements_;
};
static const int TREE_CAPACITY = 2000;
static const int NUM_TEST_THREADS = 3;
static const int TREE_CAPACITY = 100;
static const int NUM_TEST_THREADS = 4;
static const int NUM_ITERATIONS = 100;
void TreeTestSingleThreadInsertDelete_Pre();
void TreeTestSingleThreadInsertDelete_ThreadMethod();
void TreeTestMultiThreadInsertDelete_ThreadMethod();
void TreeTestSingleThreadInsertDelete_Post();
void TreeTestInsertDelete_Pre();
void TreeTestInsertDeleteSingleThread_ThreadMethod();
void TreeTestInsertDeleteMultiThread_ThreadMethod();
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
......
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