@@ -468,13 +468,17 @@ class RBTree : public AbstractRBTree<K, RBNode<K, V>, COMPARATOR> {
468
468
469
469
RBNode<K, V>* allocate_node (const K& key) {
470
470
void * node_place = _allocator.allocate (sizeof (RBNode<K, V>));
471
- assert (node_place != nullptr , " rb-tree allocator must exit on failure" );
471
+ if (node_place == nullptr ) {
472
+ return nullptr ;
473
+ }
472
474
return new (node_place) RBNode<K, V>(key);
473
475
}
474
476
475
477
RBNode<K, V>* allocate_node (const K& key, const V& val) {
476
478
void * node_place = _allocator.allocate (sizeof (RBNode<K, V>));
477
- assert (node_place != nullptr , " rb-tree allocator must exit on failure" );
479
+ if (node_place == nullptr ) {
480
+ return nullptr ;
481
+ }
478
482
return new (node_place) RBNode<K, V>(key, val);
479
483
}
480
484
@@ -485,16 +489,21 @@ class RBTree : public AbstractRBTree<K, RBNode<K, V>, COMPARATOR> {
485
489
486
490
// Inserts a node with the given key/value into the tree,
487
491
// if the key already exist, the value is updated instead.
488
- void upsert (const K& key, const V& val, const RBNode<K, V>* hint_node = nullptr ) {
492
+ // Returns false if and only if allocation of a new node failed.
493
+ bool upsert (const K& key, const V& val, const RBNode<K, V>* hint_node = nullptr ) {
489
494
Cursor node_cursor = cursor (key, hint_node);
490
495
RBNode<K, V>* node = node_cursor.node ();
491
496
if (node != nullptr ) {
492
497
node->set_val (val);
493
- return ;
498
+ return true ;
494
499
}
495
500
496
501
node = allocate_node (key, val);
502
+ if (node == nullptr ) {
503
+ return false ;
504
+ }
497
505
insert_at_cursor (node, node_cursor);
506
+ return true ;
498
507
}
499
508
500
509
// Finds the value of the node associated with the given key.
@@ -545,12 +554,12 @@ class RBTree : public AbstractRBTree<K, RBNode<K, V>, COMPARATOR> {
545
554
}
546
555
};
547
556
548
- template <MemTag mem_tag>
557
+ template <MemTag mem_tag, AllocFailType strategy >
549
558
class RBTreeCHeapAllocator {
550
559
public:
551
560
void * allocate (size_t sz) {
552
561
void * allocation = os::malloc (sz, mem_tag);
553
- if (allocation == nullptr ) {
562
+ if (allocation == nullptr && strategy == AllocFailStrategy::EXIT_OOM ) {
554
563
vm_exit_out_of_memory (sz, OOM_MALLOC_ERROR,
555
564
" red-black tree failed allocation" );
556
565
}
@@ -560,8 +569,8 @@ class RBTreeCHeapAllocator {
560
569
void free (void * ptr) { os::free (ptr); }
561
570
};
562
571
563
- template <typename K, typename V, typename COMPARATOR, MemTag mem_tag>
564
- using RBTreeCHeap = RBTree<K, V, COMPARATOR, RBTreeCHeapAllocator<mem_tag>>;
572
+ template <typename K, typename V, typename COMPARATOR, MemTag mem_tag, AllocFailStrategy strategy = AllocFailStrategy::EXIT_OOM >
573
+ using RBTreeCHeap = RBTree<K, V, COMPARATOR, RBTreeCHeapAllocator<mem_tag, strategy >>;
565
574
566
575
template <typename K, typename COMPARATOR>
567
576
using IntrusiveRBTree = AbstractRBTree<K, IntrusiveRBNode, COMPARATOR>;
0 commit comments