From d45494274440277b084bd39df8e175d91e3b1d24 Mon Sep 17 00:00:00 2001 From: Danila Klimenko Date: Wed, 2 Sep 2015 19:29:36 +0200 Subject: [PATCH] Restructured the dummy operation objects. --- containers_cpp/generator/chromatic_tree_generator.cc | 4 ++-- containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h | 83 ++++++++++++++++++++++++----------------------------------------------------------- containers_cpp/include/embb/containers/lock_free_chromatic_tree.h | 69 +++++++++++++++++++++++++++++++++++---------------------------------- 3 files changed, 61 insertions(+), 95 deletions(-) diff --git a/containers_cpp/generator/chromatic_tree_generator.cc b/containers_cpp/generator/chromatic_tree_generator.cc index b2101f9..5a0abe4 100644 --- a/containers_cpp/generator/chromatic_tree_generator.cc +++ b/containers_cpp/generator/chromatic_tree_generator.cc @@ -112,7 +112,7 @@ void PrintOperationSourceCode(FILE* file, const RebalancingOperation& op) { for (int i = 0; i < op.num_nodes; ++i) { fprintf(file, " %s = node_pool_.Allocate(\n" " %s->GetKey(), %s->GetValue(), %s,\n" - " %s, %s, Operation::INITIAL_DUMMY);\n" + " %s, %s, &initial_operation_dummy_);\n" " if (%s == NULL) break;\n", op.new_nodes[i].name, op.new_nodes[i].orig_node, op.new_nodes[i].orig_node, @@ -142,7 +142,7 @@ void PrintOperationSourceCode(FILE* file, const RebalancingOperation& op) { fprintf(file, "\n" " bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING),\n" " GetOperationGuard(HIDX_HELPING));\n" - " op->CleanUp();\n" + " op->CleanUp(&retired_operation_dummy_);\n" " \n" " if (!succeeded) {\n" " RetireOperation(op);\n" diff --git a/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h b/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h index fd02b65..931be27 100644 --- a/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h +++ b/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h @@ -152,8 +152,8 @@ ChromaticTreeNode::GetOperation() { template -ChromaticTreeOperation::ChromaticTreeOperation() - : state_(STATE_FREEZING), +ChromaticTreeOperation::ChromaticTreeOperation(bool is_dummy) + : state_(is_dummy ? STATE_COMMITTED : STATE_FREEZING), root_(NULL), root_operation_(NULL), num_old_nodes_(0), @@ -334,7 +334,7 @@ inline bool ChromaticTreeOperation::IsCommitted() { } template -void ChromaticTreeOperation::CleanUp() { +void ChromaticTreeOperation::CleanUp(Operation* retired_dummy) { #ifdef EMBB_DEBUG assert(!deleted_); #endif @@ -343,7 +343,7 @@ void ChromaticTreeOperation::CleanUp() { if (IsCommitted()) { for (size_t i = 0; i < num_old_nodes_; ++i) { assert(old_nodes_[i]->GetOperation() == this); - old_nodes_[i]->GetOperation() = RETIRED_DUMMY; + old_nodes_[i]->GetOperation() = retired_dummy; } } } @@ -356,40 +356,6 @@ void ChromaticTreeOperation::SetDeleted() { #endif template -typename ChromaticTreeOperation::Operation* -ChromaticTreeOperation::GetInitialDummmy() { -#ifdef EMBB_PLATFORM_COMPILER_MSVC -#pragma warning(push) -#pragma warning(disable:4640) -#endif - static ChromaticTreeOperation initial_dummy; -#ifdef EMBB_PLATFORM_COMPILER_MSVC -#pragma warning(pop) -#endif - - initial_dummy.state_ = STATE_COMMITTED; - - return &initial_dummy; -} - -template -typename ChromaticTreeOperation::Operation* -ChromaticTreeOperation::GetRetiredDummmy() { -#ifdef EMBB_PLATFORM_COMPILER_MSVC -#pragma warning(push) -#pragma warning(disable:4640) -#endif - static ChromaticTreeOperation retired_dummy; -#ifdef EMBB_PLATFORM_COMPILER_MSVC -#pragma warning(pop) -#endif - - retired_dummy.state_ = STATE_COMMITTED; - - return &retired_dummy; -} - -template bool ChromaticTreeOperation::IsRollingBack() { State state = state_.Load(); return (state == STATE_ROLLBACK || state == STATE_ABORTED); @@ -503,16 +469,6 @@ SwitchState(State old_state, State new_state) { return true; } -template -typename ChromaticTreeOperation::Operation* const - ChromaticTreeOperation::INITIAL_DUMMY = - ChromaticTreeOperation::GetInitialDummmy(); - -template -typename ChromaticTreeOperation::Operation* const - ChromaticTreeOperation::RETIRED_DUMMY = - ChromaticTreeOperation::GetRetiredDummmy(); - } // namespace internal @@ -544,13 +500,15 @@ ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value, operation_pool_(2 + 5 + 2 * capacity_ + operation_hazard_manager_.GetRetiredListMaxSize() * embb::base::Thread::GetThreadsMaxCount()), + initial_operation_dummy_(true), + retired_operation_dummy_(true), entry_(node_pool_.Allocate(undefined_key_, undefined_value_, -1, node_pool_.Allocate(undefined_key_, undefined_value_, -1, - Operation::INITIAL_DUMMY), + &initial_operation_dummy_), static_cast(NULL), - Operation::INITIAL_DUMMY)) { + &initial_operation_dummy_)) { assert(entry_ != NULL); assert(entry_->GetLeft() != NULL); } @@ -620,7 +578,7 @@ TryInsert(const Key& key, const Value& value, Value& old_value) { // Reached leaf has a matching key: replace it with a new copy old_value = leaf->GetValue(); new_parent = node_pool_.Allocate(key, value, leaf->GetWeight(), - Operation::INITIAL_DUMMY); + &initial_operation_dummy_); if (new_parent == NULL) break; // Reached leaf has a different key: add a new leaf @@ -628,10 +586,10 @@ TryInsert(const Key& key, const Value& value, Value& old_value) { old_value = undefined_value_; new_leaf = node_pool_.Allocate(key, value, 1, - Operation::INITIAL_DUMMY); + &initial_operation_dummy_); if (new_leaf == NULL) break; new_sibling = node_pool_.Allocate(leaf->GetKey(), leaf->GetValue(), 1, - Operation::INITIAL_DUMMY); + &initial_operation_dummy_); if (new_sibling == NULL) break; int new_weight = @@ -641,11 +599,11 @@ TryInsert(const Key& key, const Value& value, Value& old_value) { if (leaf->IsSentinel() || compare_(key, leaf->GetKey())) { new_parent = node_pool_.Allocate(leaf->GetKey(), undefined_value_, new_weight, new_leaf, new_sibling, - Operation::INITIAL_DUMMY); + &initial_operation_dummy_); } else { new_parent = node_pool_.Allocate(key, undefined_value_, new_weight, new_sibling, new_leaf, - Operation::INITIAL_DUMMY); + &initial_operation_dummy_); } if (new_parent == NULL) break; } @@ -661,7 +619,7 @@ TryInsert(const Key& key, const Value& value, Value& old_value) { // Execute operation insertion_succeeded = insert_op->Help(GetNodeGuard(HIDX_HELPING), GetOperationGuard(HIDX_HELPING)); - insert_op->CleanUp(); + insert_op->CleanUp(&retired_operation_dummy_); // If operation failed if (!insertion_succeeded) { @@ -761,7 +719,7 @@ TryDelete(const Key& key, Value& old_value) { new_leaf = node_pool_.Allocate( sibling->GetKey(), sibling->GetValue(), new_weight, - sibling->GetLeft(), sibling->GetRight(), Operation::INITIAL_DUMMY); + sibling->GetLeft(), sibling->GetRight(), &initial_operation_dummy_); if (new_leaf == NULL) break; old_value = leaf->GetValue(); @@ -777,7 +735,7 @@ TryDelete(const Key& key, Value& old_value) { // Execute operation deletion_succeeded = delete_op->Help(GetNodeGuard(HIDX_HELPING), GetOperationGuard(HIDX_HELPING)); - delete_op->CleanUp(); + delete_op->CleanUp(&retired_operation_dummy_); // If operation failed if (!deletion_succeeded) { @@ -926,6 +884,13 @@ IsBalanced(const Node* node) const { } template +bool ChromaticTree:: +IsDummyOperation(const Operation* operation) const { + return (operation == &initial_operation_dummy_ || + operation == &retired_operation_dummy_); +} + +template void ChromaticTree:: RetireNode(HazardNodePtr& node) { node_hazard_manager_.EnqueuePointerForDeletion(node.ReleaseHazard()); @@ -936,7 +901,7 @@ void ChromaticTree:: RetireOperation(HazardOperationPtr& operation) { Operation* op = operation.ReleaseHazard(); // Make sure we don't return the static dummy-operations to the pool - if (op != Operation::INITIAL_DUMMY && op != Operation::RETIRED_DUMMY) { + if (!IsDummyOperation(op)) { operation_hazard_manager_.EnqueuePointerForDeletion(op); } } diff --git a/containers_cpp/include/embb/containers/lock_free_chromatic_tree.h b/containers_cpp/include/embb/containers/lock_free_chromatic_tree.h index 871bd7f..544a5b1 100644 --- a/containers_cpp/include/embb/containers/lock_free_chromatic_tree.h +++ b/containers_cpp/include/embb/containers/lock_free_chromatic_tree.h @@ -222,16 +222,13 @@ class ChromaticTreeOperation { /** Hazard-protected pointer to a tree operation. */ typedef UniqueHazardPointer HazardOperationPtr; - /** Dummy operation used for newly created nodes. */ - static Operation* const INITIAL_DUMMY; - /** Dummy operation used for nodes removed from the tree after - * an operation commits. */ - static Operation* const RETIRED_DUMMY; - /** * Creates an empty operation object with an "in progress" state. + * + * \param is_dummy Boolean flag for creation of dummy operation objects. + * */ - ChromaticTreeOperation(); + ChromaticTreeOperation(bool is_dummy = false); /** * Set the root node of this operation together with its original operation @@ -332,8 +329,11 @@ class ChromaticTreeOperation { * operation commits, resets all the operation pointers of the nodes of the * removed operation window to point to the retired dummy-operation. Must be * called only once after the operation either commits or aborts. + * + * \param retired_dummy Dummy operation object used to reset operation + * pointers in the retired nodes. */ - void CleanUp(); + void CleanUp(Operation* retired_dummy); #ifdef EMBB_DEBUG /** @@ -359,24 +359,6 @@ class ChromaticTreeOperation { static const size_t MAX_NODES = 5; /** - * Initializes and returns the initial dummy operation. - * - * \return Pointer to the INITIAL_DUMMY operation - * - * \see INITIAL_DUMMY - */ - static Operation* GetInitialDummmy(); - - /** - * Initializes and returns the retired dummy operation. - * - * \return Pointer to the RETIRED_DUMMY operation - * - * \see RETIRED_DUMMY - */ - static Operation* GetRetiredDummmy(); - - /** * Check whether the operation is rolling back. * * \return \c true if operation is rolling back, \c false otherwise @@ -760,6 +742,15 @@ class ChromaticTree { bool IsBalanced(const Node* node) const; /** + * Checks whether a given operation is a dummy operation. + * + * \param[IN] operation Operation to be checked + * + * \return \c true if the given operation is a dummy, \c false otherwise + */ + bool IsDummyOperation(const Operation* operation) const; + + /** * Retire a hazardous node using the node hazard manager. * * \param node A hazardous node to be retired @@ -865,14 +856,24 @@ class ChromaticTree { /** Hazard pointer manager for protecting operation pointers. */ internal::HazardPointer operation_hazard_manager_; - 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. */ - size_t capacity_; /**< User-requested capacity of the tree. */ - NodePool node_pool_; /**< Pool of tree nodes. */ - OperationPool operation_pool_; /**< Pool of operation objects. */ - Node* const entry_; /**< Pointer to the sentinel node used as - * the entry point into the tree. */ + /** A dummy key used by the tree. */ + const Key undefined_key_; + /** A dummy value used by the tree. */ + const Value undefined_value_; + /** Comparator object for the keys. */ + const Compare compare_; + /** User-requested capacity of the tree. */ + size_t capacity_; + /** Pool of tree nodes. */ + NodePool node_pool_; + /** Pool of operation objects. */ + OperationPool operation_pool_; + /** Dummy operation used in newly created nodes. */ + Operation initial_operation_dummy_; + /** Dummy operation used in retired nodes. */ + Operation retired_operation_dummy_; + /** Pointer to the sentinel node used as the entry point into the tree. */ + Node* const entry_; /** * Friending the test class for white-box testing -- libgit2 0.26.0