Commit d4549427 by Danila Klimenko

Restructured the dummy operation objects.

parent 2c905f00
...@@ -112,7 +112,7 @@ void PrintOperationSourceCode(FILE* file, const RebalancingOperation& op) { ...@@ -112,7 +112,7 @@ void PrintOperationSourceCode(FILE* file, const RebalancingOperation& op) {
for (int i = 0; i < op.num_nodes; ++i) { for (int i = 0; i < op.num_nodes; ++i) {
fprintf(file, " %s = node_pool_.Allocate(\n" fprintf(file, " %s = node_pool_.Allocate(\n"
" %s->GetKey(), %s->GetValue(), %s,\n" " %s->GetKey(), %s->GetValue(), %s,\n"
" %s, %s, Operation::INITIAL_DUMMY);\n" " %s, %s, &initial_operation_dummy_);\n"
" if (%s == NULL) break;\n", " if (%s == NULL) break;\n",
op.new_nodes[i].name, op.new_nodes[i].name,
op.new_nodes[i].orig_node, op.new_nodes[i].orig_node, op.new_nodes[i].orig_node, op.new_nodes[i].orig_node,
...@@ -142,7 +142,7 @@ void PrintOperationSourceCode(FILE* file, const RebalancingOperation& op) { ...@@ -142,7 +142,7 @@ void PrintOperationSourceCode(FILE* file, const RebalancingOperation& op) {
fprintf(file, "\n" fprintf(file, "\n"
" bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING),\n" " bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING),\n"
" GetOperationGuard(HIDX_HELPING));\n" " GetOperationGuard(HIDX_HELPING));\n"
" op->CleanUp();\n" " op->CleanUp(&retired_operation_dummy_);\n"
" \n" " \n"
" if (!succeeded) {\n" " if (!succeeded) {\n"
" RetireOperation(op);\n" " RetireOperation(op);\n"
......
...@@ -152,8 +152,8 @@ ChromaticTreeNode<Key, Value>::GetOperation() { ...@@ -152,8 +152,8 @@ ChromaticTreeNode<Key, Value>::GetOperation() {
template<typename Key, typename Value> template<typename Key, typename Value>
ChromaticTreeOperation<Key, Value>::ChromaticTreeOperation() ChromaticTreeOperation<Key, Value>::ChromaticTreeOperation(bool is_dummy)
: state_(STATE_FREEZING), : state_(is_dummy ? STATE_COMMITTED : STATE_FREEZING),
root_(NULL), root_(NULL),
root_operation_(NULL), root_operation_(NULL),
num_old_nodes_(0), num_old_nodes_(0),
...@@ -334,7 +334,7 @@ inline bool ChromaticTreeOperation<Key, Value>::IsCommitted() { ...@@ -334,7 +334,7 @@ inline bool ChromaticTreeOperation<Key, Value>::IsCommitted() {
} }
template<typename Key, typename Value> template<typename Key, typename Value>
void ChromaticTreeOperation<Key, Value>::CleanUp() { void ChromaticTreeOperation<Key, Value>::CleanUp(Operation* retired_dummy) {
#ifdef EMBB_DEBUG #ifdef EMBB_DEBUG
assert(!deleted_); assert(!deleted_);
#endif #endif
...@@ -343,7 +343,7 @@ void ChromaticTreeOperation<Key, Value>::CleanUp() { ...@@ -343,7 +343,7 @@ void ChromaticTreeOperation<Key, Value>::CleanUp() {
if (IsCommitted()) { if (IsCommitted()) {
for (size_t i = 0; i < num_old_nodes_; ++i) { for (size_t i = 0; i < num_old_nodes_; ++i) {
assert(old_nodes_[i]->GetOperation() == this); assert(old_nodes_[i]->GetOperation() == this);
old_nodes_[i]->GetOperation() = RETIRED_DUMMY; old_nodes_[i]->GetOperation() = retired_dummy;
} }
} }
} }
...@@ -356,40 +356,6 @@ void ChromaticTreeOperation<Key, Value>::SetDeleted() { ...@@ -356,40 +356,6 @@ void ChromaticTreeOperation<Key, Value>::SetDeleted() {
#endif #endif
template<typename Key, typename Value> template<typename Key, typename Value>
typename ChromaticTreeOperation<Key, Value>::Operation*
ChromaticTreeOperation<Key, Value>::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 Key, typename Value>
typename ChromaticTreeOperation<Key, Value>::Operation*
ChromaticTreeOperation<Key, Value>::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<typename Key, typename Value>
bool ChromaticTreeOperation<Key, Value>::IsRollingBack() { bool ChromaticTreeOperation<Key, Value>::IsRollingBack() {
State state = state_.Load(); State state = state_.Load();
return (state == STATE_ROLLBACK || state == STATE_ABORTED); return (state == STATE_ROLLBACK || state == STATE_ABORTED);
...@@ -503,16 +469,6 @@ SwitchState(State old_state, State new_state) { ...@@ -503,16 +469,6 @@ SwitchState(State old_state, State new_state) {
return true; return true;
} }
template<typename Key, typename Value>
typename ChromaticTreeOperation<Key, Value>::Operation* const
ChromaticTreeOperation<Key, Value>::INITIAL_DUMMY =
ChromaticTreeOperation::GetInitialDummmy();
template<typename Key, typename Value>
typename ChromaticTreeOperation<Key, Value>::Operation* const
ChromaticTreeOperation<Key, Value>::RETIRED_DUMMY =
ChromaticTreeOperation::GetRetiredDummmy();
} // namespace internal } // namespace internal
...@@ -544,13 +500,15 @@ ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value, ...@@ -544,13 +500,15 @@ ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value,
operation_pool_(2 + 5 + 2 * capacity_ + operation_pool_(2 + 5 + 2 * capacity_ +
operation_hazard_manager_.GetRetiredListMaxSize() * operation_hazard_manager_.GetRetiredListMaxSize() *
embb::base::Thread::GetThreadsMaxCount()), embb::base::Thread::GetThreadsMaxCount()),
initial_operation_dummy_(true),
retired_operation_dummy_(true),
entry_(node_pool_.Allocate(undefined_key_, undefined_value_, -1, entry_(node_pool_.Allocate(undefined_key_, undefined_value_, -1,
node_pool_.Allocate(undefined_key_, node_pool_.Allocate(undefined_key_,
undefined_value_, undefined_value_,
-1, -1,
Operation::INITIAL_DUMMY), &initial_operation_dummy_),
static_cast<Node*>(NULL), static_cast<Node*>(NULL),
Operation::INITIAL_DUMMY)) { &initial_operation_dummy_)) {
assert(entry_ != NULL); assert(entry_ != NULL);
assert(entry_->GetLeft() != NULL); assert(entry_->GetLeft() != NULL);
} }
...@@ -620,7 +578,7 @@ TryInsert(const Key& key, const Value& value, Value& old_value) { ...@@ -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 // Reached leaf has a matching key: replace it with a new copy
old_value = leaf->GetValue(); old_value = leaf->GetValue();
new_parent = node_pool_.Allocate(key, value, leaf->GetWeight(), new_parent = node_pool_.Allocate(key, value, leaf->GetWeight(),
Operation::INITIAL_DUMMY); &initial_operation_dummy_);
if (new_parent == NULL) break; if (new_parent == NULL) break;
// Reached leaf has a different key: add a new leaf // Reached leaf has a different key: add a new leaf
...@@ -628,10 +586,10 @@ TryInsert(const Key& key, const Value& value, Value& old_value) { ...@@ -628,10 +586,10 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
old_value = undefined_value_; old_value = undefined_value_;
new_leaf = node_pool_.Allocate(key, value, 1, new_leaf = node_pool_.Allocate(key, value, 1,
Operation::INITIAL_DUMMY); &initial_operation_dummy_);
if (new_leaf == NULL) break; if (new_leaf == NULL) break;
new_sibling = node_pool_.Allocate(leaf->GetKey(), leaf->GetValue(), 1, new_sibling = node_pool_.Allocate(leaf->GetKey(), leaf->GetValue(), 1,
Operation::INITIAL_DUMMY); &initial_operation_dummy_);
if (new_sibling == NULL) break; if (new_sibling == NULL) break;
int new_weight = int new_weight =
...@@ -641,11 +599,11 @@ TryInsert(const Key& key, const Value& value, Value& old_value) { ...@@ -641,11 +599,11 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
if (leaf->IsSentinel() || compare_(key, leaf->GetKey())) { if (leaf->IsSentinel() || compare_(key, leaf->GetKey())) {
new_parent = node_pool_.Allocate(leaf->GetKey(), undefined_value_, new_parent = node_pool_.Allocate(leaf->GetKey(), undefined_value_,
new_weight, new_leaf, new_sibling, new_weight, new_leaf, new_sibling,
Operation::INITIAL_DUMMY); &initial_operation_dummy_);
} else { } else {
new_parent = node_pool_.Allocate(key, undefined_value_, new_parent = node_pool_.Allocate(key, undefined_value_,
new_weight, new_sibling, new_leaf, new_weight, new_sibling, new_leaf,
Operation::INITIAL_DUMMY); &initial_operation_dummy_);
} }
if (new_parent == NULL) break; if (new_parent == NULL) break;
} }
...@@ -661,7 +619,7 @@ TryInsert(const Key& key, const Value& value, Value& old_value) { ...@@ -661,7 +619,7 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
// Execute operation // Execute operation
insertion_succeeded = insert_op->Help(GetNodeGuard(HIDX_HELPING), insertion_succeeded = insert_op->Help(GetNodeGuard(HIDX_HELPING),
GetOperationGuard(HIDX_HELPING)); GetOperationGuard(HIDX_HELPING));
insert_op->CleanUp(); insert_op->CleanUp(&retired_operation_dummy_);
// If operation failed // If operation failed
if (!insertion_succeeded) { if (!insertion_succeeded) {
...@@ -761,7 +719,7 @@ TryDelete(const Key& key, Value& old_value) { ...@@ -761,7 +719,7 @@ TryDelete(const Key& key, Value& old_value) {
new_leaf = node_pool_.Allocate( new_leaf = node_pool_.Allocate(
sibling->GetKey(), sibling->GetValue(), new_weight, 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; if (new_leaf == NULL) break;
old_value = leaf->GetValue(); old_value = leaf->GetValue();
...@@ -777,7 +735,7 @@ TryDelete(const Key& key, Value& old_value) { ...@@ -777,7 +735,7 @@ TryDelete(const Key& key, Value& old_value) {
// Execute operation // Execute operation
deletion_succeeded = delete_op->Help(GetNodeGuard(HIDX_HELPING), deletion_succeeded = delete_op->Help(GetNodeGuard(HIDX_HELPING),
GetOperationGuard(HIDX_HELPING)); GetOperationGuard(HIDX_HELPING));
delete_op->CleanUp(); delete_op->CleanUp(&retired_operation_dummy_);
// If operation failed // If operation failed
if (!deletion_succeeded) { if (!deletion_succeeded) {
...@@ -926,6 +884,13 @@ IsBalanced(const Node* node) const { ...@@ -926,6 +884,13 @@ IsBalanced(const Node* node) const {
} }
template<typename Key, typename Value, typename Compare, typename ValuePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
IsDummyOperation(const Operation* operation) const {
return (operation == &initial_operation_dummy_ ||
operation == &retired_operation_dummy_);
}
template<typename Key, typename Value, typename Compare, typename ValuePool>
void ChromaticTree<Key, Value, Compare, ValuePool>:: void ChromaticTree<Key, Value, Compare, ValuePool>::
RetireNode(HazardNodePtr& node) { RetireNode(HazardNodePtr& node) {
node_hazard_manager_.EnqueuePointerForDeletion(node.ReleaseHazard()); node_hazard_manager_.EnqueuePointerForDeletion(node.ReleaseHazard());
...@@ -936,7 +901,7 @@ void ChromaticTree<Key, Value, Compare, ValuePool>:: ...@@ -936,7 +901,7 @@ void ChromaticTree<Key, Value, Compare, ValuePool>::
RetireOperation(HazardOperationPtr& operation) { RetireOperation(HazardOperationPtr& operation) {
Operation* op = operation.ReleaseHazard(); Operation* op = operation.ReleaseHazard();
// Make sure we don't return the static dummy-operations to the pool // 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); operation_hazard_manager_.EnqueuePointerForDeletion(op);
} }
} }
......
...@@ -222,16 +222,13 @@ class ChromaticTreeOperation { ...@@ -222,16 +222,13 @@ class ChromaticTreeOperation {
/** Hazard-protected pointer to a tree operation. */ /** Hazard-protected pointer to a tree operation. */
typedef UniqueHazardPointer<Operation> HazardOperationPtr; typedef UniqueHazardPointer<Operation> 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. * 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 * Set the root node of this operation together with its original operation
...@@ -332,8 +329,11 @@ class ChromaticTreeOperation { ...@@ -332,8 +329,11 @@ class ChromaticTreeOperation {
* operation commits, resets all the operation pointers of the nodes of the * operation commits, resets all the operation pointers of the nodes of the
* removed operation window to point to the retired dummy-operation. Must be * removed operation window to point to the retired dummy-operation. Must be
* called only once after the operation either commits or aborts. * 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 #ifdef EMBB_DEBUG
/** /**
...@@ -359,24 +359,6 @@ class ChromaticTreeOperation { ...@@ -359,24 +359,6 @@ class ChromaticTreeOperation {
static const size_t MAX_NODES = 5; 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. * Check whether the operation is rolling back.
* *
* \return \c true if operation is rolling back, \c false otherwise * \return \c true if operation is rolling back, \c false otherwise
...@@ -760,6 +742,15 @@ class ChromaticTree { ...@@ -760,6 +742,15 @@ class ChromaticTree {
bool IsBalanced(const Node* node) const; 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. * Retire a hazardous node using the node hazard manager.
* *
* \param node A hazardous node to be retired * \param node A hazardous node to be retired
...@@ -865,14 +856,24 @@ class ChromaticTree { ...@@ -865,14 +856,24 @@ class ChromaticTree {
/** Hazard pointer manager for protecting operation pointers. */ /** Hazard pointer manager for protecting operation pointers. */
internal::HazardPointer<Operation*> operation_hazard_manager_; internal::HazardPointer<Operation*> operation_hazard_manager_;
const Key undefined_key_; /**< A dummy key used by the tree. */ /** A dummy key used by the tree. */
const Value undefined_value_; /**< A dummy value used by the tree. */ const Key undefined_key_;
const Compare compare_; /**< Comparator object for the keys. */ /** A dummy value used by the tree. */
size_t capacity_; /**< User-requested capacity of the tree. */ const Value undefined_value_;
NodePool node_pool_; /**< Pool of tree nodes. */ /** Comparator object for the keys. */
OperationPool operation_pool_; /**< Pool of operation objects. */ const Compare compare_;
Node* const entry_; /**< Pointer to the sentinel node used as /** User-requested capacity of the tree. */
* the entry point into 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 * Friending the test class for white-box testing
......
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