Commit d4549427 by Danila Klimenko

Restructured the dummy operation objects.

parent 2c905f00
......@@ -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"
......
......@@ -152,8 +152,8 @@ ChromaticTreeNode<Key, Value>::GetOperation() {
template<typename Key, typename Value>
ChromaticTreeOperation<Key, Value>::ChromaticTreeOperation()
: state_(STATE_FREEZING),
ChromaticTreeOperation<Key, Value>::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<Key, Value>::IsCommitted() {
}
template<typename Key, typename Value>
void ChromaticTreeOperation<Key, Value>::CleanUp() {
void ChromaticTreeOperation<Key, Value>::CleanUp(Operation* retired_dummy) {
#ifdef EMBB_DEBUG
assert(!deleted_);
#endif
......@@ -343,7 +343,7 @@ void ChromaticTreeOperation<Key, Value>::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<Key, Value>::SetDeleted() {
#endif
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() {
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 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
......@@ -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<Node*>(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<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>::
RetireNode(HazardNodePtr& node) {
node_hazard_manager_.EnqueuePointerForDeletion(node.ReleaseHazard());
......@@ -936,7 +901,7 @@ void ChromaticTree<Key, Value, Compare, ValuePool>::
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);
}
}
......
......@@ -222,16 +222,13 @@ class ChromaticTreeOperation {
/** Hazard-protected pointer to a tree operation. */
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.
*
* \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*> 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
......
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