lock_free_chromatic_tree-inl.h 45.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*
 * Copyright (c) 2014-2015, Siemens AG. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_INL_H_
#define EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_INL_H_

#include <assert.h>
#include <algorithm>

33 34 35 36 37 38 39 40
#ifdef EMBB_DEBUG
static const size_t INVALID_POINTER = static_cast<size_t>(-1);
# define VERIFY_ADDRESS(addr) assert(reinterpret_cast<size_t>((addr)) != \
                                     INVALID_POINTER)
#else
# define VERIFY_ADDRESS(address) ((void)0)
#endif

41 42 43 44 45 46
namespace embb {
namespace containers {
namespace internal {

template<typename Key, typename Value>
ChromaticTreeNode<Key, Value>::
47
ChromaticTreeNode(const Key& key, const Value& value, int weight,
48
                  Node* left, Node* right, Operation* operation)
49 50
    : key_(key),
      value_(value),
51 52 53
      weight_(weight < 0 ? -weight : weight),
      is_leaf_(left == NULL),
      is_sentinel_(weight < 0),
54
      left_(left),
55
      right_(right),
56 57
      retired_(false),
      operation_(operation) {}
58 59 60

template<typename Key, typename Value>
ChromaticTreeNode<Key, Value>::
61 62
ChromaticTreeNode(const Key& key, const Value& value, int weight,
                  Operation* operation)
63 64
    : key_(key),
      value_(value),
65 66 67
      weight_(weight < 0 ? -weight : weight),
      is_leaf_(true),
      is_sentinel_(weight < 0),
68
      left_(NULL),
69
      right_(NULL),
70 71
      retired_(false),
      operation_(operation) {}
72 73

template<typename Key, typename Value>
74
inline const Key& ChromaticTreeNode<Key, Value>::GetKey() const {
75 76 77 78
  return key_;
}

template<typename Key, typename Value>
79
inline const Value& ChromaticTreeNode<Key, Value>::GetValue() const {
80 81 82 83
  return value_;
}

template<typename Key, typename Value>
84
inline int ChromaticTreeNode<Key, Value>::GetWeight() const {
85 86 87 88
  return weight_;
}

template<typename Key, typename Value>
89
inline typename ChromaticTreeNode<Key, Value>::AtomicNodePtr&
90
ChromaticTreeNode<Key, Value>::GetLeft() {
91 92 93 94
  return left_;
}

template<typename Key, typename Value>
95
inline typename ChromaticTreeNode<Key, Value>::Node*
96 97 98 99 100
ChromaticTreeNode<Key, Value>::GetLeft() const {
  return left_.Load();
}

template<typename Key, typename Value>
101
inline typename ChromaticTreeNode<Key, Value>::AtomicNodePtr&
102
ChromaticTreeNode<Key, Value>::GetRight() {
103 104 105
  return right_;
}

106
template<typename Key, typename Value>
107
inline typename ChromaticTreeNode<Key, Value>::Node*
108 109 110 111 112
ChromaticTreeNode<Key, Value>::GetRight() const {
  return right_.Load();
}

template<typename Key, typename Value>
113 114 115 116 117 118 119 120 121 122
inline bool ChromaticTreeNode<Key, Value>::IsLeaf() const {
  return is_leaf_;
}

template<typename Key, typename Value>
inline bool ChromaticTreeNode<Key, Value>::IsSentinel() const {
  return is_sentinel_;
}

template<typename Key, typename Value>
123 124 125 126 127 128 129 130 131 132 133 134 135 136
bool ChromaticTreeNode<Key, Value>::
ReplaceChild(Node* old_child, Node* new_child) {
  bool replaced = false;

  if (left_ == old_child) {
    replaced = left_.CompareAndSwap(old_child, new_child);
  } else if (right_ == old_child) {
    replaced = right_.CompareAndSwap(old_child, new_child);
  }

  return replaced;
}

template<typename Key, typename Value>
137
inline void ChromaticTreeNode<Key, Value>::Retire() {
138 139 140 141
  retired_ = true;
}

template<typename Key, typename Value>
142
inline bool ChromaticTreeNode<Key, Value>::IsRetired() const {
143 144 145
  return retired_;
}

146
template<typename Key, typename Value>
147
inline typename ChromaticTreeNode<Key, Value>::AtomicOperationPtr&
148 149 150 151 152 153 154
ChromaticTreeNode<Key, Value>::GetOperation() {
  return operation_;
}



template<typename Key, typename Value>
155 156
ChromaticTreeOperation<Key, Value>::ChromaticTreeOperation(bool is_dummy)
    : state_(is_dummy ? STATE_COMMITTED : STATE_FREEZING),
157 158 159 160 161 162 163
      root_(NULL),
      root_operation_(NULL),
      num_old_nodes_(0),
      new_child_(NULL)
#ifdef EMBB_DEBUG
      , deleted_(false)
#endif
164 165 166 167 168 169
{
  for (size_t i = 0; i < MAX_NODES; ++i) {
    old_nodes_[i] = NULL;
    old_operations_[i] = NULL;
  }
}
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311

template<typename Key, typename Value>
void ChromaticTreeOperation<Key, Value>::
SetRoot(Node* root, Operation* root_operation) {
  root_ = root;
  root_operation_ = root_operation;
}

template<typename Key, typename Value>
void ChromaticTreeOperation<Key, Value>::
SetOldNodes(Node* node1, Operation* operation1) {
  num_old_nodes_ = 1;
  old_nodes_[0]      = node1;
  old_operations_[0] = operation1;
}

template<typename Key, typename Value>
void ChromaticTreeOperation<Key, Value>::
SetOldNodes(Node* node1, Operation* operation1,
            Node* node2, Operation* operation2) {
  num_old_nodes_ = 2;
  old_nodes_[0]      = node1;
  old_operations_[0] = operation1;
  old_nodes_[1]      = node2;
  old_operations_[1] = operation2;
}

template<typename Key, typename Value>
void ChromaticTreeOperation<Key, Value>::
SetOldNodes(Node* node1, Operation* operation1,
            Node* node2, Operation* operation2,
            Node* node3, Operation* operation3) {
  num_old_nodes_ = 3;
  old_nodes_[0]      = node1;
  old_operations_[0] = operation1;
  old_nodes_[1]      = node2;
  old_operations_[1] = operation2;
  old_nodes_[2]      = node3;
  old_operations_[2] = operation3;
}

template<typename Key, typename Value>
void ChromaticTreeOperation<Key, Value>::
SetOldNodes(Node* node1, Operation* operation1,
            Node* node2, Operation* operation2,
            Node* node3, Operation* operation3,
            Node* node4, Operation* operation4) {
  num_old_nodes_ = 4;
  old_nodes_[0]      = node1;
  old_operations_[0] = operation1;
  old_nodes_[1]      = node2;
  old_operations_[1] = operation2;
  old_nodes_[2]      = node3;
  old_operations_[2] = operation3;
  old_nodes_[3]      = node4;
  old_operations_[3] = operation4;
}

template<typename Key, typename Value>
void ChromaticTreeOperation<Key, Value>::
SetOldNodes(Node* node1, Operation* operation1,
            Node* node2, Operation* operation2,
            Node* node3, Operation* operation3,
            Node* node4, Operation* operation4,
            Node* node5, Operation* operation5) {
  num_old_nodes_ = 5;
  old_nodes_[0]      = node1;
  old_operations_[0] = operation1;
  old_nodes_[1]      = node2;
  old_operations_[1] = operation2;
  old_nodes_[2]      = node3;
  old_operations_[2] = operation3;
  old_nodes_[3]      = node4;
  old_operations_[3] = operation4;
  old_nodes_[4]      = node5;
  old_operations_[4] = operation5;
}

template<typename Key, typename Value>
void ChromaticTreeOperation<Key, Value>::SetNewChild(Node* new_child) {
  new_child_ = new_child;
}

template<typename Key, typename Value>
bool ChromaticTreeOperation<Key, Value>::
Help(AtomicNodePtr& node_guard, AtomicOperationPtr& oper_guard) {
#ifdef EMBB_DEBUG
  assert(!deleted_);
#endif
  // Freezing step
  if (!FreezeAll(node_guard, oper_guard)) {
    return IsCommitted();
  }

  // All frozen step
  if (!SwitchState(STATE_FREEZING, STATE_ALL_FROZEN)) {
    return IsCommitted();
  }

  // At this point operation may no longer fail - complete it
  HelpCommit(node_guard);

  return true;
}

template<typename Key, typename Value>
void ChromaticTreeOperation<Key, Value>::HelpCommit(AtomicNodePtr& node_guard) {
#ifdef EMBB_DEBUG
  assert(!deleted_);
#endif
  HazardNodePtr node_hp(node_guard);

  // Mark step (retire old nodes)
  for (size_t i = 0; i < num_old_nodes_; ++i) {
    node_hp.ProtectSafe(old_nodes_[i]);
    if (IsCommitted()) return;
    old_nodes_[i]->Retire();
  }

  // Update step
  node_hp.ProtectSafe(root_);
  if (IsCommitted()) return;
  root_->ReplaceChild(old_nodes_[0], new_child_);

  // Commit step
  SwitchState(STATE_ALL_FROZEN, STATE_COMMITTED);
}

template<typename Key, typename Value>
void ChromaticTreeOperation<Key, Value>::HelpAbort(Node* node) {
#ifdef EMBB_DEBUG
  assert(!deleted_);
#endif
  for (size_t i = 0; i < num_old_nodes_; ++i) {
    if (old_nodes_[i] == node) {
      Unfreeze(old_nodes_[i], old_operations_[i]);
      break;
    }
  }
}

template<typename Key, typename Value>
312
inline bool ChromaticTreeOperation<Key, Value>::IsAborted() {
313 314 315 316 317 318 319
#ifdef EMBB_DEBUG
  assert(!deleted_);
#endif
  return state_ == STATE_ABORTED;
}

template<typename Key, typename Value>
320
inline bool ChromaticTreeOperation<Key, Value>::IsInProgress() {
321 322 323 324 325 326 327 328
#ifdef EMBB_DEBUG
  assert(!deleted_);
#endif
  State state = state_.Load();
  return (state != STATE_ABORTED && state != STATE_COMMITTED);
}

template<typename Key, typename Value>
329
inline bool ChromaticTreeOperation<Key, Value>::IsCommitted() {
330 331 332 333 334 335 336
#ifdef EMBB_DEBUG
  assert(!deleted_);
#endif
  return state_ == STATE_COMMITTED;
}

template<typename Key, typename Value>
337
void ChromaticTreeOperation<Key, Value>::CleanUp(Operation* retired_dummy) {
338 339 340 341 342 343 344 345
#ifdef EMBB_DEBUG
  assert(!deleted_);
#endif
  assert(!IsInProgress());

  if (IsCommitted()) {
    for (size_t i = 0; i < num_old_nodes_; ++i) {
      assert(old_nodes_[i]->GetOperation() == this);
346
      old_nodes_[i]->GetOperation() = retired_dummy;
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
    }
  }
}

#ifdef EMBB_DEBUG
template<typename Key, typename Value>
void ChromaticTreeOperation<Key, Value>::SetDeleted() {
  deleted_ = true;
}
#endif

template<typename Key, typename Value>
bool ChromaticTreeOperation<Key, Value>::IsRollingBack() {
  State state = state_.Load();
  return (state == STATE_ROLLBACK || state == STATE_ABORTED);
}

template<typename Key, typename Value>
bool ChromaticTreeOperation<Key, Value>::IsFreezing() {
  return state_ == STATE_FREEZING;
}

template<typename Key, typename Value>
bool ChromaticTreeOperation<Key, Value>::IsAllFrozen() {
  State state = state_.Load();
  return (state == STATE_ALL_FROZEN || state == STATE_COMMITTED);
}

template<typename Key, typename Value>
bool ChromaticTreeOperation<Key, Value>::
FreezeAll(AtomicNodePtr& node_guard, AtomicOperationPtr& oper_guard) {
  if (IsFreezing()) {
    HazardNodePtr      node_hp(node_guard);
    HazardOperationPtr oper_hp(oper_guard);

    node_hp.ProtectSafe(root_);
    oper_hp.ProtectSafe(root_operation_);

    if (IsFreezing()) {
      Freeze(root_, root_operation_);
    }

    for (size_t i = 0; i < num_old_nodes_; ++i) {
      node_hp.ProtectSafe(old_nodes_[i]);
      oper_hp.ProtectSafe(old_operations_[i]);
      if (!IsFreezing()) break;

      Freeze(old_nodes_[i], old_operations_[i]);
    }
  }

  if (IsRollingBack()) {
    UnfreezeAll(node_guard);
    return false;
  }

  return true;
}

template<typename Key, typename Value>
bool ChromaticTreeOperation<Key, Value>::
Freeze(Node* node, Operation* operation) {
  bool freezed = node->GetOperation().CompareAndSwap(operation, this);

  if (!freezed && operation != this && !IsAllFrozen()) {
    // Node is frozen for another operation - abort "this"
    SwitchState(STATE_FREEZING, STATE_ROLLBACK);

    // If the "operation" was aborted and rolled back, some other thread could
    // have helped "this" to freeze all nodes, and the previous "SwitchState"
    // would fail
    return IsAllFrozen();
  }

  if (freezed && IsRollingBack()) {
    // "False-positive" CAS: "this" was aborted and the "operation" might have
    // been rolled back; While "node" is hazard protected, unfreeze it again
    Unfreeze(node, operation);
    return false;
  }

  return true;
}

template<typename Key, typename Value>
void ChromaticTreeOperation<Key, Value>::
UnfreezeAll(AtomicNodePtr& node_guard) {
  HazardNodePtr node_hp(node_guard);

  node_hp.ProtectSafe(root_);
  if (IsAborted()) return;

  Unfreeze(root_, root_operation_);

  for (size_t i = 0; i < num_old_nodes_; ++i) {
    node_hp.ProtectSafe(old_nodes_[i]);
    if (IsAborted()) return;

    Unfreeze(old_nodes_[i], old_operations_[i]);
  }

  SwitchState(STATE_ROLLBACK, STATE_ABORTED);
}

template<typename Key, typename Value>
void ChromaticTreeOperation<Key, Value>::
Unfreeze(Node* node, Operation* operation) {
  Operation* expected = this;
  node->GetOperation().CompareAndSwap(expected, operation);
}

template<typename Key, typename Value>
bool ChromaticTreeOperation<Key, Value>::
SwitchState(State old_state, State new_state) {
  if (state_ != new_state) {
    bool switched = state_.CompareAndSwap(old_state, new_state);

    if (!switched && old_state != new_state) {
      return false;
    }
  }

  return true;
}

472 473 474
} // namespace internal


475 476
template<typename Key, typename Value, typename Compare, typename ValuePool>
ChromaticTree<Key, Value, Compare, ValuePool>::
477 478
ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value,
              Compare compare)
479 480 481 482
#ifdef EMBB_PLATFORM_COMPILER_MSVC
#pragma warning(push)
#pragma warning(disable:4355)
#endif
483 484
    : node_hazard_manager_(
          embb::base::Function<void, Node*>(*this, &ChromaticTree::FreeNode),
485 486 487 488 489
          NULL, HIDX_MAX),
      operation_hazard_manager_(
          embb::base::Function<void, Operation*>(*this,
                                                 &ChromaticTree::FreeOperation),
          NULL, HIDX_MAX),
490 491 492 493
#ifdef EMBB_PLATFORM_COMPILER_MSVC
#pragma warning(pop)
#endif
      undefined_key_(undefined_key),
494 495 496
      undefined_value_(undefined_value),
      compare_(compare),
      capacity_(capacity),
497 498
      node_pool_(2 + 5 + 2 * capacity_ +
                 node_hazard_manager_.GetRetiredListMaxSize() *
499
                 embb::base::Thread::GetThreadsMaxCount()),
500 501 502
      operation_pool_(2 + 5 + 2 * capacity_ +
                      operation_hazard_manager_.GetRetiredListMaxSize() *
                      embb::base::Thread::GetThreadsMaxCount()),
503 504
      initial_operation_dummy_(true),
      retired_operation_dummy_(true),
505
      entry_(node_pool_.Allocate(undefined_key_, undefined_value_, -1,
506
                                 node_pool_.Allocate(undefined_key_,
507
                                                     undefined_value_,
508
                                                     -1,
509
                                                     &initial_operation_dummy_),
510
                                 static_cast<Node*>(NULL),
511
                                 &initial_operation_dummy_)) {
512
  assert(entry_ != NULL);
513
  assert(entry_->GetLeft() != NULL);
514 515
}

516 517
template<typename Key, typename Value, typename Compare, typename ValuePool>
ChromaticTree<Key, Value, Compare, ValuePool>::
518 519
~ChromaticTree() {
  Destruct(entry_->GetLeft());
520
  FreeNode(entry_);
521 522
}

523 524
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
525
Get(const Key& key, Value& value) {
526 527 528 529
  HazardNodePtr grandparent(GetNodeGuard(HIDX_GRANDPARENT));
  HazardNodePtr parent(GetNodeGuard(HIDX_PARENT));
  HazardNodePtr leaf(GetNodeGuard(HIDX_LEAF));
  Search(key, leaf, parent, grandparent);
530

531
  bool keys_are_equal = !leaf->IsSentinel() &&
532
                        !(compare_(key, leaf->GetKey()) ||
533
                          compare_(leaf->GetKey(), key));
534 535

  if (keys_are_equal) {
536 537
    value = leaf->GetValue();
  }
538 539

  return keys_are_equal;
540 541
}

542 543
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
544 545 546 547 548
TryInsert(const Key& key, const Value& value) {
  Value old_value;
  return TryInsert(key, value, old_value);
}

549 550
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
551
TryInsert(const Key& key, const Value& value, Value& old_value) {
552 553 554
  Node* new_leaf = NULL;
  Node* new_sibling = NULL;
  Node* new_parent = NULL;
555
  bool insertion_succeeded = false;
556
  bool added_violation = false;
557 558

  while (!insertion_succeeded) {
559 560 561 562
    HazardNodePtr grandparent(GetNodeGuard(HIDX_GRANDPARENT));
    HazardNodePtr parent(GetNodeGuard(HIDX_PARENT));
    HazardNodePtr leaf(GetNodeGuard(HIDX_LEAF));
    Search(key, leaf, parent, grandparent);
563

564 565 566
    // Protect the parent
    HazardOperationPtr parent_op(GetOperationGuard(HIDX_PARENT));
    if (!WeakLLX(parent, parent_op)) continue;
567 568 569
    // Verify that the leaf is still the parent's child
    if (!HasChild(parent, leaf)) continue;

570 571 572
    // Protect the leaf
    HazardOperationPtr leaf_op(GetOperationGuard(HIDX_LEAF));
    if (!WeakLLX(leaf, leaf_op)) continue;
573

574
    bool keys_are_equal = !leaf->IsSentinel() &&
575 576 577 578
                          !(compare_(key, leaf->GetKey()) ||
                            compare_(leaf->GetKey(), key));
    if (keys_are_equal) {
      // Reached leaf has a matching key: replace it with a new copy
579
      old_value = leaf->GetValue();
580
      new_parent = node_pool_.Allocate(key, value, leaf->GetWeight(),
581
                                       &initial_operation_dummy_);
582 583 584 585 586
      if (new_parent == NULL) break;

    // Reached leaf has a different key: add a new leaf
    } else {
      old_value = undefined_value_;
587

588
      new_leaf = node_pool_.Allocate(key, value, 1,
589
                                     &initial_operation_dummy_);
590
      if (new_leaf == NULL) break;
591
      new_sibling = node_pool_.Allocate(leaf->GetKey(), leaf->GetValue(), 1,
592
                                        &initial_operation_dummy_);
593
      if (new_sibling == NULL) break;
594

595 596 597 598 599
      int new_weight =
          leaf->IsSentinel() ? -1 :
            parent->IsSentinel() ? 1 :
              (leaf->GetWeight() - 1);
      if (leaf->IsSentinel() || compare_(key, leaf->GetKey())) {
600
        new_parent = node_pool_.Allocate(leaf->GetKey(), undefined_value_,
601
                                         new_weight, new_leaf, new_sibling,
602
                                         &initial_operation_dummy_);
603 604
      } else {
        new_parent = node_pool_.Allocate(key, undefined_value_,
605
                                         new_weight, new_sibling, new_leaf,
606
                                         &initial_operation_dummy_);
607 608
      }
      if (new_parent == NULL) break;
609
    }
610

611 612 613 614 615 616 617 618 619 620 621
    // Create and fill the operation object
    HazardOperationPtr insert_op(GetOperationGuard(HIDX_CURRENT_OP));
    insert_op.ProtectSafe(operation_pool_.Allocate());
    if (insert_op == NULL) break;
    insert_op->SetRoot(parent, parent_op);
    insert_op->SetOldNodes(leaf, leaf_op);
    insert_op->SetNewChild(new_parent);

    // Execute operation
    insertion_succeeded = insert_op->Help(GetNodeGuard(HIDX_HELPING),
                                          GetOperationGuard(HIDX_HELPING));
622
    insert_op->CleanUp(&retired_operation_dummy_);
623 624 625 626 627 628 629 630 631 632 633 634 635 636

    // If operation failed
    if (!insertion_succeeded) {
      // Retire failed operation
      RetireOperation(insert_op);
      // Delete new nodes
      FreeNode(new_parent); new_parent = NULL;
      if (!keys_are_equal) {
        FreeNode(new_leaf); new_leaf = NULL;
        FreeNode(new_sibling); new_sibling = NULL;
      }
      // Restart from scratch
      continue;
    }
637

638 639 640 641 642
    // Retire old operation objects
    RetireOperation(parent_op);
    RetireOperation(leaf_op);
    // Retire old nodes
    RetireNode(leaf);
643

644 645
    added_violation = (parent->GetWeight() == 0 &&
                       new_parent->GetWeight() == 0);
646 647
  }

648 649 650
  if (insertion_succeeded) {
    if (added_violation) CleanUp(key);
  } else {
651 652 653
    if (new_leaf != NULL)    FreeNode(new_leaf);
    if (new_sibling != NULL) FreeNode(new_sibling);
    if (new_parent != NULL)  FreeNode(new_parent);
654 655
  }

656
  return insertion_succeeded;
657 658
}

659 660
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
661 662 663 664 665
TryDelete(const Key& key) {
  Value old_value;
  return TryDelete(key, old_value);
}

666 667
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
668
TryDelete(const Key& key, Value& old_value) {
669
  Node* new_leaf = NULL;
670
  bool deletion_succeeded = false;
671
  bool added_violation = false;
672 673

  while (!deletion_succeeded) {
674 675 676
    HazardNodePtr grandparent(GetNodeGuard(HIDX_GRANDPARENT));
    HazardNodePtr parent(GetNodeGuard(HIDX_PARENT));
    HazardNodePtr leaf(GetNodeGuard(HIDX_LEAF));
677 678 679
    Search(key, leaf, parent, grandparent);

    // Reached leaf has a different key - nothing to delete
680
    if (leaf->IsSentinel() || (compare_(key, leaf->GetKey()) ||
681 682 683 684 685
                             compare_(leaf->GetKey(), key))) {
      old_value = undefined_value_;
      deletion_succeeded = true;
      break;
    }
686

687 688 689 690
    // Protect the grandparent
    HazardOperationPtr grandparent_op(GetOperationGuard(HIDX_GRANDPARENT));
    if (!WeakLLX(grandparent, grandparent_op)) continue;
    // Verify that the parent is still the child of grandparent
691 692
    if (!HasChild(grandparent, parent)) continue;

693 694 695
    // Protect the parent
    HazardOperationPtr parent_op(GetOperationGuard(HIDX_PARENT));
    if (!WeakLLX(parent, parent_op)) continue;
696 697

    // Get the sibling (and protect it with hazard pointer)
698
    HazardNodePtr sibling(GetNodeGuard(HIDX_SIBLING));
699 700 701
    sibling.ProtectHazard((parent->GetLeft() == leaf) ?
                          parent->GetRight() : parent->GetLeft());
    if (parent->IsRetired() || !sibling.IsActive()) continue;
702
    VERIFY_ADDRESS(static_cast<Node*>(sibling));
703

704 705 706
    // Verify that the leaf is still the parent's child
    if (!HasChild(parent, leaf)) continue;

707 708 709
    // Protect the sibling
    HazardOperationPtr sibling_op(GetOperationGuard(HIDX_SIBLING));
    if (!WeakLLX(sibling, sibling_op)) continue;
710

711 712 713
    // Protect the leaf
    HazardOperationPtr leaf_op(GetOperationGuard(HIDX_LEAF));
    if (!WeakLLX(leaf, leaf_op)) continue;
714

715 716 717 718
    int new_weight =
        parent->IsSentinel() ? -1 :
          grandparent->IsSentinel() ? 1 :
            (parent->GetWeight() + sibling->GetWeight());
719 720 721

    new_leaf = node_pool_.Allocate(
        sibling->GetKey(), sibling->GetValue(), new_weight,
722
        sibling->GetLeft(), sibling->GetRight(), &initial_operation_dummy_);
723
    if (new_leaf == NULL) break;
724

725
    old_value = leaf->GetValue();
726

727 728 729 730 731 732 733 734 735 736 737
    // Create and fill the operation object
    HazardOperationPtr delete_op(GetOperationGuard(HIDX_CURRENT_OP));
    delete_op.ProtectSafe(operation_pool_.Allocate());
    if (delete_op == NULL) break;
    delete_op->SetRoot(grandparent, grandparent_op);
    delete_op->SetOldNodes(parent, parent_op, leaf, leaf_op, sibling, sibling_op);
    delete_op->SetNewChild(new_leaf);

    // Execute operation
    deletion_succeeded = delete_op->Help(GetNodeGuard(HIDX_HELPING),
                                         GetOperationGuard(HIDX_HELPING));
738
    delete_op->CleanUp(&retired_operation_dummy_);
739 740 741 742 743 744 745 746 747 748

    // If operation failed
    if (!deletion_succeeded) {
      // Retire failed operation
      RetireOperation(delete_op);
      // Delete new nodes
      FreeNode(new_leaf);
      // Restart from scratch
      continue;
    }
749

750 751 752 753 754 755 756 757 758
    // Retire old operation objects
    RetireOperation(grandparent_op);
    RetireOperation(parent_op);
    RetireOperation(leaf_op);
    RetireOperation(sibling_op);
    // Retire old nodes
    RetireNode(parent);
    RetireNode(leaf);
    RetireNode(sibling);
759 760

    added_violation =  (new_weight > 1);
761
  }
762

763 764 765
  if (deletion_succeeded) {
    if (added_violation) CleanUp(key);
  } else {
766
    if (new_leaf != NULL)    FreeNode(new_leaf);
767 768
  }

769
  return deletion_succeeded;
770 771
}

772 773
template<typename Key, typename Value, typename Compare, typename ValuePool>
size_t ChromaticTree<Key, Value, Compare, ValuePool>::
774
GetCapacity() const {
775 776 777
  return capacity_;
}

778 779 780
template<typename Key, typename Value, typename Compare, typename ValuePool>
const Value& ChromaticTree<Key, Value, Compare, ValuePool>::
GetUndefinedValue() const {
781 782 783
  return undefined_value_;
}

784
template<typename Key, typename Value, typename Compare, typename ValuePool>
785
inline bool ChromaticTree<Key, Value, Compare, ValuePool>::
786
IsEmpty() const {
787
  return entry_->GetLeft()->IsLeaf();
788 789
}

790 791
template<typename Key, typename Value, typename Compare, typename ValuePool>
void ChromaticTree<Key, Value, Compare, ValuePool>::
792 793
Search(const Key& key, HazardNodePtr& leaf, HazardNodePtr& parent,
       HazardNodePtr& grandparent) {
794 795 796
  bool reached_leaf = false;

  while (!reached_leaf) {
797 798
    grandparent.ProtectSafe(entry_);
    parent.ProtectSafe(entry_);
799
    leaf.ProtectSafe(entry_);
800

801
    reached_leaf = leaf->IsLeaf();
802
    while (!reached_leaf) {
803 804 805 806
      grandparent.AdoptHazard(parent);
      parent.AdoptHazard(leaf);

      AtomicNodePtr& next_leaf =
807
          (leaf->IsSentinel() || compare_(key, leaf->GetKey())) ?
808 809 810 811 812 813 814 815 816 817 818 819 820 821 822
            leaf->GetLeft() : leaf->GetRight();

      // Parent is protected, so we can tolerate a changing child pointer
      while(!leaf.ProtectHazard(next_leaf));

      // Parent is retired - make sure it is actually removed from the tree
      if (parent->IsRetired()) {
        HazardOperationPtr op(GetOperationGuard(HIDX_HELPING));
        if (op.ProtectHazard(parent->GetOperation())) {
          op->HelpCommit(GetNodeGuard(HIDX_HELPING));
        }
        // Can't follow a child pointer in a retired node - restart from root
        break;
      }

823
      VERIFY_ADDRESS(static_cast<Node*>(leaf));
824

825
      reached_leaf = leaf->IsLeaf();
826
    }
827 828 829
  }
}

830
template<typename Key, typename Value, typename Compare, typename ValuePool>
831
inline bool ChromaticTree<Key, Value, Compare, ValuePool>::
832
HasChild(const Node* parent, const Node* child) const {
833 834 835
  return (parent->GetLeft() == child || parent->GetRight() == child);
}

836 837 838
template<typename Key, typename Value, typename Compare, typename ValuePool>
void ChromaticTree<Key, Value, Compare, ValuePool>::
Destruct(Node* node) {
839
  if (!node->IsLeaf()) {
840 841 842
    Destruct(node->GetLeft());
    Destruct(node->GetRight());
  }
843 844 845
  FreeNode(node);
}

846 847 848
template<typename Key, typename Value, typename Compare, typename ValuePool>
int ChromaticTree<Key, Value, Compare, ValuePool>::
GetHeight(const Node* node) const {
849 850 851 852 853 854 855 856
  int height = 0;
  if (node != NULL) {
    height = 1 + ::std::max(GetHeight(node->GetLeft()),
                            GetHeight(node->GetRight()));
  }
  return height;
}

857 858
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
859
IsBalanced() const {
860
  return IsBalanced(entry_->GetLeft());
861 862
}

863 864 865
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
IsBalanced(const Node* node) const {
866 867 868
  // Overweight violation
  bool has_violation = node->GetWeight() > 1;

869
  if (!has_violation && !node->IsLeaf()) {
870 871
    const Node* left  = node->GetLeft();
    const Node* right = node->GetRight();
872 873 874 875 876 877 878 879 880 881 882 883 884 885

    // 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;
}

886
template<typename Key, typename Value, typename Compare, typename ValuePool>
887 888 889 890 891 892 893
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>
894
void ChromaticTree<Key, Value, Compare, ValuePool>::
895 896
RetireNode(HazardNodePtr& node) {
  node_hazard_manager_.EnqueuePointerForDeletion(node.ReleaseHazard());
897 898
}

899 900
template<typename Key, typename Value, typename Compare, typename ValuePool>
void ChromaticTree<Key, Value, Compare, ValuePool>::
901 902
RetireOperation(HazardOperationPtr& operation) {
  Operation* op = operation.ReleaseHazard();
903
  // Make sure we don't return the static dummy-operations to the pool
904
  if (!IsDummyOperation(op)) {
905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920
    operation_hazard_manager_.EnqueuePointerForDeletion(op);
  }
}

template<typename Key, typename Value, typename Compare, typename ValuePool>
typename ChromaticTree<Key, Value, Compare, ValuePool>::AtomicNodePtr&
ChromaticTree<Key, Value, Compare, ValuePool>::
GetNodeGuard(HazardIndex index) {
  return node_hazard_manager_.GetGuardedPointer(static_cast<int>(index));
}

template<typename Key, typename Value, typename Compare, typename ValuePool>
typename ChromaticTree<Key, Value, Compare, ValuePool>::AtomicOperationPtr&
ChromaticTree<Key, Value, Compare, ValuePool>::
GetOperationGuard(HazardIndex index) {
  return operation_hazard_manager_.GetGuardedPointer(static_cast<int>(index));
921 922
}

923 924
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
925 926 927
WeakLLX(HazardNodePtr& node, HazardOperationPtr& operation) {
  // Make sure we have a protected operation pointer
  while (!operation.ProtectHazard(node->GetOperation()));
928

929 930 931 932
  // Node is not retired and operation is committed - node is available
  if (!node->IsRetired() && operation->IsCommitted()) {
    return true;
  }
933

934 935 936
  if (operation->IsAborted()) {
    // Operation is aborted, but the node is still frozen - unfreeze it
    operation->HelpAbort(node);
937

938 939 940 941 942
  } else if (operation->IsInProgress()) {
    // Operation is still in progress - help it
    operation->Help(GetNodeGuard(HIDX_HELPING),
                    GetOperationGuard(HIDX_HELPING));
  }
943

944 945
  // LLX failed - operation pointer should not be exposed
  operation.ReleaseHazard();
946

947 948
  return false;
}
949

950 951 952 953 954 955 956 957 958
template<typename Key, typename Value, typename Compare, typename ValuePool>
void ChromaticTree<Key, Value, Compare, ValuePool>::
FreeNode(Node* node) {
#ifdef EMBB_DEBUG
  node->GetLeft()  = reinterpret_cast<Node*>(INVALID_POINTER);
  node->GetRight() = reinterpret_cast<Node*>(INVALID_POINTER);
#endif
  node_pool_.Free(node);
}
959

960 961 962 963 964 965 966 967
template<typename Key, typename Value, typename Compare, typename ValuePool>
void ChromaticTree<Key, Value, Compare, ValuePool>::
FreeOperation(Operation* operation) {
#ifdef EMBB_DEBUG
  operation->SetDeleted();
#endif
  operation_pool_.Free(operation);
}
968

969 970 971
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
CleanUp(const Key& key) {
972 973 974 975 976 977 978 979 980 981 982 983 984 985
  HazardNodePtr grandgrandparent(GetNodeGuard(HIDX_GRANDGRANDPARENT));
  HazardNodePtr grandparent(GetNodeGuard(HIDX_GRANDPARENT));
  HazardNodePtr parent(GetNodeGuard(HIDX_PARENT));
  HazardNodePtr leaf(GetNodeGuard(HIDX_LEAF));
  bool reached_leaf = false;

  while (!reached_leaf) {
    bool found_violation = false;

    grandgrandparent.ProtectSafe(entry_);
    grandparent.ProtectSafe(entry_);
    parent.ProtectSafe(entry_);
    leaf.ProtectSafe(entry_);

986
    reached_leaf = leaf->IsLeaf();
987 988 989 990 991 992
    while (!reached_leaf && !found_violation) {
      grandgrandparent.AdoptHazard(grandparent);
      grandparent.AdoptHazard(parent);
      parent.AdoptHazard(leaf);

      AtomicNodePtr& next_leaf =
993
          (leaf->IsSentinel() || compare_(key, leaf->GetKey())) ?
994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
            leaf->GetLeft() : leaf->GetRight();

      // Parent is protected, so we can tolerate a changing child pointer
      while(!leaf.ProtectHazard(next_leaf));

      // Parent is retired - make sure it is actually removed from the tree
      if (parent->IsRetired()) {
        HazardOperationPtr op(GetOperationGuard(HIDX_HELPING));
        if (op.ProtectHazard(parent->GetOperation())) {
          op->HelpCommit(GetNodeGuard(HIDX_HELPING));
        }
        // Can't follow a child pointer in a retired node - restart from root
        break;
      }

      VERIFY_ADDRESS(static_cast<Node*>(leaf));

      // Check for violations
      if ((leaf->GetWeight() > 1) || (leaf->GetWeight() == 0 &&
                                      parent->GetWeight() == 0)) {
        if (Rebalance(grandgrandparent, grandparent, parent, leaf) ==
            EMBB_NOMEM) {
          assert(false && "No memory for rebalancing!");
          return false;
        }
        break;
      }

1022
      reached_leaf = leaf->IsLeaf();
1023 1024 1025
    }
  }

1026 1027 1028
  return true;
}

1029 1030 1031
#define PROTECT_NODE_WITH_LLX(h_idx, node, op_name) \
    HazardOperationPtr op_name(GetOperationGuard(h_idx)); \
    if (!WeakLLX(node, op_name)) return EMBB_BUSY
1032

1033 1034
#define DEFINE_HAZARDOUS_NODE(h_idx, node, parent, method) \
    HazardNodePtr node(GetNodeGuard(h_idx)); \
1035 1036
    node.ProtectHazard(parent->method()); \
    if (parent->IsRetired() || !node.IsActive()) return EMBB_BUSY; \
1037
    VERIFY_ADDRESS(static_cast<Node*>(node))
1038

1039 1040
template<typename Key, typename Value, typename Compare, typename ValuePool>
embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>::
1041 1042 1043
Rebalance(HazardNodePtr& u, HazardNodePtr& ux, HazardNodePtr& uxx,
          HazardNodePtr& uxxx) {
  // Protect node 'u'
1044
  PROTECT_NODE_WITH_LLX(HIDX_U, u, u_op);
1045 1046 1047 1048
  // Verify that ux is still a child of u
  if (!HasChild(u, ux)) return EMBB_BUSY;

  // Protect node 'ux'
1049
  PROTECT_NODE_WITH_LLX(HIDX_UX, ux, ux_op);
1050
  // Get children of 'ux'
1051 1052
  DEFINE_HAZARDOUS_NODE(HIDX_UXL, uxl, ux, GetLeft);
  DEFINE_HAZARDOUS_NODE(HIDX_UXR, uxr, ux, GetRight);
1053 1054 1055 1056 1057
  // Verify that 'uxx' is still a child of 'ux'
  bool uxx_is_left = (uxx == uxl); (void)uxx_is_left;
  if (!HasChild(ux, uxx)) return EMBB_BUSY;

  // Protect node 'uxx'
1058
  PROTECT_NODE_WITH_LLX(HIDX_UXX, uxx, uxx_op);
1059
  // Get children of 'uxx'
1060 1061
  DEFINE_HAZARDOUS_NODE(HIDX_UXXL, uxxl, uxx, GetLeft);
  DEFINE_HAZARDOUS_NODE(HIDX_UXXR, uxxr, uxx, GetRight);
1062
  // Verify that 'uxxx' is still a child of 'uxx'
1063
  bool uxxx_is_left = (uxxx == uxxl);
1064
  if (!HasChild(uxx, uxxx)) return EMBB_BUSY;
1065 1066 1067

  if (uxxx->GetWeight() > 1) {
    if (uxxx_is_left) {
1068
      // Protect node 'uxxl'
1069 1070 1071
      PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op);
      return OverweightLeft(u, u_op, ux, ux_op, uxx, uxx_op, uxl, uxr,
                            uxxl, uxxl_op, uxxr, uxx_is_left);
1072
    } else {
1073
      // Protect node 'uxxr'
1074 1075 1076
      PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op);
      return OverweightRight(u, u_op, ux, ux_op, uxx, uxx_op, uxl, uxr,
                             uxxl, uxxr, uxxr_op, !uxx_is_left);
1077 1078
    }
  } else {
1079
    assert(uxxx->GetWeight() == 0 && uxx->GetWeight() == 0); //Red-red violation
1080 1081
    if (uxx_is_left) {
      if (uxr->GetWeight() == 0) {
1082
        // Protect node 'uxr'
1083 1084
        PROTECT_NODE_WITH_LLX(HIDX_UXR, uxr, uxr_op);
        return BLK(u, u_op, ux, ux_op, uxx, uxx_op, uxr, uxr_op);
1085
      } else if (uxxx_is_left) {
1086
        return RB1_L(u, u_op, ux, ux_op, uxx, uxx_op);
1087
      } else {
1088
        // Protect node 'uxxr'
1089 1090
        PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op);
        return RB2_L(u, u_op, ux, ux_op, uxx, uxx_op, uxxr, uxxr_op);
1091 1092 1093
      }
    } else {
      if (uxl->GetWeight() == 0) {
1094
        // Protect node 'uxl'
1095 1096
        PROTECT_NODE_WITH_LLX(HIDX_UXL, uxl, uxl_op);
        return BLK(u, u_op, ux, ux_op, uxl, uxl_op, uxx, uxx_op);
1097
      } else if (!uxxx_is_left) {
1098
        return RB1_R(u, u_op, ux, ux_op, uxx, uxx_op);
1099
      } else {
1100
        // Protect node 'uxxl'
1101 1102
        PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op);
        return RB2_R(u, u_op, ux, ux_op, uxx, uxx_op, uxxl, uxxl_op);
1103 1104 1105 1106 1107
      }
    }
  }
}

1108 1109
template<typename Key, typename Value, typename Compare, typename ValuePool>
embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>::
1110 1111 1112
OverweightLeft(HazardNodePtr& u, HazardOperationPtr& u_op,
               HazardNodePtr& ux, HazardOperationPtr& ux_op,
               HazardNodePtr& uxx, HazardOperationPtr& uxx_op,
1113
               HazardNodePtr& uxl, HazardNodePtr& uxr,
1114
               HazardNodePtr& uxxl, HazardOperationPtr& uxxl_op,
1115
               HazardNodePtr& uxxr, bool uxx_is_left) {
1116 1117 1118 1119 1120 1121 1122 1123 1124
  // Let "Root" be the top of the overweight violation decision tree (see p.30)
  // Root -> Middle
  if (uxxr->GetWeight() == 0) {
    // Root -> Middle -> Left
    if (uxx->GetWeight() == 0) {
      // Root -> Middle -> Left -> Left
      if (uxx_is_left) {
        // Root -> Middle -> Left -> Left -> Left
        if (uxr->GetWeight() == 0) {
1125
          // Protect node 'uxr'
1126 1127
          PROTECT_NODE_WITH_LLX(HIDX_UXR, uxr, uxr_op);
          return BLK(u, u_op, ux, ux_op, uxx, uxx_op, uxr, uxr_op);
1128 1129 1130 1131

        // Root -> Middle -> Left -> Left -> Right
        } else {
          assert(uxr->GetWeight() > 0);
1132
          // Protect node 'uxxr'
1133 1134
          PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op);
          return RB2_L(u, u_op, ux, ux_op, uxx, uxx_op, uxxr, uxxr_op);
1135 1136 1137 1138 1139 1140 1141
        }

      // Root -> Middle -> Left -> Right
      } else {
        assert(!uxx_is_left);
        // Root -> Middle -> Left -> Right -> Left
        if (uxl->GetWeight() == 0) {
1142
          // Protect node 'uxl'
1143 1144
          PROTECT_NODE_WITH_LLX(HIDX_UXL, uxl, uxl_op);
          return BLK(u, u_op, ux, ux_op, uxl, uxl_op, uxx, uxx_op);
1145 1146 1147 1148

        // Root -> Middle -> Left -> Right -> Right
        } else {
          assert(uxl->GetWeight() > 0);
1149
          return RB1_R(u, u_op, ux, ux_op, uxx, uxx_op);
1150 1151 1152 1153 1154 1155
        }
      }

    // Root -> Middle -> Right
    } else {
      assert(uxx->GetWeight() > 0);
1156
      // Protect node 'uxxr'
1157
      PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op);
1158 1159

      // Get left child of 'uxxr'
1160
      // Note: we know that 'uxxr' is not a leaf because it has weight 0.
1161
      DEFINE_HAZARDOUS_NODE(HIDX_UXXRL, uxxrl, uxxr, GetLeft);
1162 1163

      // Protect node 'uxxrl'
1164
      PROTECT_NODE_WITH_LLX(HIDX_UXXRL, uxxrl, uxxrl_op);
1165 1166 1167

      // Root -> Middle -> Right -> Left
      if (uxxrl->GetWeight() == 0) {
1168 1169
        return RB2_R(ux, ux_op, uxx, uxx_op,
                     uxxr, uxxr_op, uxxrl, uxxrl_op);
1170 1171 1172

      // Root -> Middle -> Right -> Middle
      } else if (uxxrl->GetWeight() == 1) {
1173
        DEFINE_HAZARDOUS_NODE(HIDX_UXXRLR, uxxrlr, uxxrl, GetRight);
1174
        if (uxxrlr == NULL) return EMBB_BUSY;
1175 1176 1177

        // Root -> Middle -> Right -> Middle -> Left
        if (uxxrlr->GetWeight() == 0) {
1178
          // Protect node 'uxxrlr'
1179 1180 1181
          PROTECT_NODE_WITH_LLX(HIDX_UXXRLR, uxxrlr, uxxrlr_op);
          return W4_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
                      uxxr, uxxr_op, uxxrl, uxxrl_op, uxxrlr, uxxrlr_op);
1182 1183 1184 1185 1186

        // Root -> Middle -> Right -> Middle -> Right
        } else {
          assert(uxxrlr->GetWeight() > 0);
          // Root -> Middle -> Right -> Middle -> Right -> Left
1187
          // Node: reusing hazard of node 'uxxrlr' as it is no longer used
1188
          DEFINE_HAZARDOUS_NODE(HIDX_UXXRLL, uxxrll, uxxrl, GetLeft);
1189
          if (uxxrll->GetWeight() == 0) {
1190
            // Protect node 'uxxrll'
1191 1192 1193
            PROTECT_NODE_WITH_LLX(HIDX_UXXRLL, uxxrll, uxxrll_op);
            return W3_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, uxxr,
                        uxxr_op, uxxrl, uxxrl_op, uxxrll, uxxrll_op);
1194 1195 1196 1197

          // Root -> Middle -> Right -> Middle -> Right -> Right
          } else {
            assert(uxxrll->GetWeight() > 0);
1198 1199
            return W2_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
                        uxxr, uxxr_op, uxxrl, uxxrl_op);
1200 1201 1202 1203 1204 1205
          }
        }

      // Root -> Middle -> Right -> Right
      } else {
        assert(uxxrl->GetWeight() > 1);
1206 1207
        return W1_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
                    uxxr, uxxr_op, uxxrl, uxxrl_op);
1208 1209 1210 1211 1212
      }
    }

  // Root -> Right
  } else if (uxxr->GetWeight() == 1) {
1213
    // Protect node 'uxxr'
1214
    PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op);
1215
    // Get children of 'uxxr'
1216 1217
    DEFINE_HAZARDOUS_NODE(HIDX_UXXRL, uxxrl, uxxr, GetLeft);
    DEFINE_HAZARDOUS_NODE(HIDX_UXXRR, uxxrr, uxxr, GetRight);
1218
    if (uxxrl == NULL) return EMBB_BUSY;
1219 1220 1221

    // Root -> Right -> Left
    if (uxxrr->GetWeight() == 0) {
1222
      // Protect node 'uxxrr'
1223 1224 1225
      PROTECT_NODE_WITH_LLX(HIDX_UXXRR, uxxrr, uxxrr_op);
      return W5_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
                  uxxr, uxxr_op, uxxrr, uxxrr_op);
1226 1227 1228 1229 1230 1231

    // Root -> Right -> Right
    } else {
      assert(uxxrr->GetWeight() > 0);
      // Root -> Right -> Right -> Left
      if (uxxrl->GetWeight() == 0) {
1232
        // Protect node 'uxxrl'
1233 1234 1235
        PROTECT_NODE_WITH_LLX(HIDX_UXXRL, uxxrl, uxxrl_op);
        return W6_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
                    uxxr, uxxr_op, uxxrl, uxxrl_op);
1236 1237 1238 1239

      // Root -> Right -> Right -> Right
      } else {
        assert(uxxrl->GetWeight() > 0);
1240 1241
        return PUSH_L(ux, ux_op, uxx, uxx_op,
                      uxxl, uxxl_op, uxxr, uxxr_op);
1242 1243 1244 1245 1246 1247
      }
    }

  // Root -> Left
  } else {
    assert(uxxr->GetWeight() > 1);
1248
    // Protect node 'uxxr'
1249 1250
    PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op);
    return W7(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, uxxr, uxxr_op);
1251 1252 1253
  }
}

1254 1255
template<typename Key, typename Value, typename Compare, typename ValuePool>
embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>::
1256 1257 1258
OverweightRight(HazardNodePtr& u, HazardOperationPtr& u_op,
                HazardNodePtr& ux, HazardOperationPtr& ux_op,
                HazardNodePtr& uxx, HazardOperationPtr& uxx_op,
1259 1260
                HazardNodePtr& uxl, HazardNodePtr& uxr,
                HazardNodePtr& uxxl, HazardNodePtr& uxxr,
1261
                HazardOperationPtr& uxxr_op, bool uxx_is_right) {
1262 1263 1264 1265 1266 1267 1268 1269 1270
  // Let "Root" be the top of the overweight violation decision tree (see p.30)
  // Root -> Middle
  if (uxxl->GetWeight() == 0) {
    // Root -> Middle -> Left
    if (uxx->GetWeight() == 0) {
      // Root -> Middle -> Left -> Left
      if (uxx_is_right) {
        // Root -> Middle -> Left -> Left -> Left
        if (uxl->GetWeight() == 0) {
1271
          // Protect node 'uxl'
1272 1273
          PROTECT_NODE_WITH_LLX(HIDX_UXL, uxl, uxl_op);
          return BLK(u, u_op, ux, ux_op, uxl, uxl_op, uxx, uxx_op);
1274 1275 1276 1277

        // Root -> Middle -> Left -> Left -> Right
        } else {
          assert(uxl->GetWeight() > 0);
1278
          // Protect node 'uxxl'
1279 1280
          PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op);
          return RB2_R(u, u_op, ux, ux_op, uxx, uxx_op, uxxl, uxxl_op);
1281 1282 1283 1284 1285 1286 1287
        }

      // Root -> Middle -> Left -> Right
      } else {
        assert(!uxx_is_right);
        // Root -> Middle -> Left -> Right -> Left
        if (uxr->GetWeight() == 0) {
1288
          // Protect node 'uxr'
1289 1290
          PROTECT_NODE_WITH_LLX(HIDX_UXR, uxr, uxr_op);
          return BLK(u, u_op, ux, ux_op, uxx, uxx_op, uxr, uxr_op);
1291 1292 1293 1294

        // Root -> Middle -> Left -> Right -> Right
        } else {
          assert(uxr->GetWeight() > 0);
1295
          return RB1_L(u, u_op, ux, ux_op, uxx, uxx_op);
1296 1297 1298 1299 1300 1301
        }
      }

    // Root -> Middle -> Right
    } else {
      assert(uxx->GetWeight() > 0);
1302
      // Protect node 'uxxl'
1303
      PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op);
1304 1305

      // Get left child of 'uxxl'
1306
      // Note: we know that 'uxxl' is not a leaf because it has weight 0.
1307
      DEFINE_HAZARDOUS_NODE(HIDX_UXXLR, uxxlr, uxxl, GetRight);
1308 1309

      // Protect node 'uxxlr'
1310
      PROTECT_NODE_WITH_LLX(HIDX_UXXLR, uxxlr, uxxlr_op);
1311 1312 1313

      // Root -> Middle -> Right -> Left
      if (uxxlr->GetWeight() == 0) {
1314 1315
        return RB2_L(ux, ux_op, uxx, uxx_op,
                     uxxl, uxxl_op, uxxlr, uxxlr_op);
1316 1317 1318

      // Root -> Middle -> Right -> Middle
      } else if (uxxlr->GetWeight() == 1) {
1319
        DEFINE_HAZARDOUS_NODE(HIDX_UXXLRL, uxxlrl, uxxlr, GetLeft);
1320
        if (uxxlrl == NULL) return EMBB_BUSY;
1321 1322 1323

        // Root -> Middle -> Right -> Middle -> Left
        if (uxxlrl->GetWeight() == 0) {
1324
          // Protect node 'uxxlrl'
1325 1326 1327
          PROTECT_NODE_WITH_LLX(HIDX_UXXLRL, uxxlrl, uxxlrl_op);
          return W4_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
                      uxxr, uxxr_op, uxxlr, uxxlr_op, uxxlrl, uxxlrl_op);
1328 1329 1330 1331 1332

        // Root -> Middle -> Right -> Middle -> Right
        } else {
          assert(uxxlrl->GetWeight() > 0);
          // Root -> Middle -> Right -> Middle -> Right -> Left
1333
          // Node: reusing hazard of node 'uxxlrl' as it is no longer used
1334
          DEFINE_HAZARDOUS_NODE(HIDX_UXXLRR, uxxlrr, uxxlr, GetRight);
1335
          if (uxxlrr->GetWeight() == 0) {
1336
            // Protect node 'uxxlrr'
1337 1338 1339
            PROTECT_NODE_WITH_LLX(HIDX_UXXLRR, uxxlrr, uxxlrr_op);
            return W3_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, uxxr,
                        uxxr_op, uxxlr, uxxlr_op, uxxlrr, uxxlrr_op);
1340 1341 1342 1343

          // Root -> Middle -> Right -> Middle -> Right -> Right
          } else {
            assert(uxxlrr->GetWeight() > 0);
1344 1345
            return W2_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
                        uxxr, uxxr_op, uxxlr, uxxlr_op);
1346 1347 1348 1349 1350 1351
          }
        }

      // Root -> Middle -> Right -> Right
      } else {
        assert(uxxlr->GetWeight() > 1);
1352 1353
        return W1_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
                    uxxr, uxxr_op, uxxlr, uxxlr_op);
1354 1355 1356 1357 1358
      }
    }

  // Root -> Right
  } else if (uxxl->GetWeight() == 1) {
1359
    // Protect node 'uxxl'
1360
    PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op);
1361
    // Get children of 'uxxl'
1362 1363
    DEFINE_HAZARDOUS_NODE(HIDX_UXXLL, uxxll, uxxl, GetLeft);
    DEFINE_HAZARDOUS_NODE(HIDX_UXXLR, uxxlr, uxxl, GetRight);
1364
    if (uxxll == NULL) return EMBB_BUSY;
1365 1366 1367

    // Root -> Right -> Left
    if (uxxll->GetWeight() == 0) {
1368
      // Protect node 'uxxll'
1369 1370 1371
      PROTECT_NODE_WITH_LLX(HIDX_UXXLL, uxxll, uxxll_op);
      return W5_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
                  uxxr, uxxr_op, uxxll, uxxll_op);
1372 1373 1374 1375 1376 1377

    // Root -> Right -> Right
    } else {
      assert(uxxll->GetWeight() > 0);
      // Root -> Right -> Right -> Left
      if (uxxlr->GetWeight() == 0) {
1378
        // Protect node 'uxxlr'
1379 1380 1381
        PROTECT_NODE_WITH_LLX(HIDX_UXXLR, uxxlr, uxxlr_op);
        return W6_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
                    uxxr, uxxr_op, uxxlr, uxxlr_op);
1382 1383 1384 1385

      // Root -> Right -> Right -> Right
      } else {
        assert(uxxlr->GetWeight() > 0);
1386 1387
        return PUSH_R(ux, ux_op, uxx, uxx_op,
                      uxxl, uxxl_op, uxxr, uxxr_op);
1388 1389 1390 1391 1392 1393
      }
    }

  // Root -> Left
  } else {
    assert(uxxl->GetWeight() > 1);
1394
    // Protect node 'uxxl'
1395 1396
    PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op);
    return W7(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, uxxr, uxxr_op);
1397 1398 1399 1400 1401 1402 1403
  }
}

} // namespace containers
} // namespace embb

#endif // EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_INL_H_