xo-ordinaltree: RedBlackTree is gc-alloc-aware
This commit is contained in:
parent
908cd0dd0f
commit
113869342c
4 changed files with 88 additions and 9 deletions
|
|
@ -58,7 +58,7 @@ namespace xo {
|
||||||
typename Value,
|
typename Value,
|
||||||
typename Reduce,
|
typename Reduce,
|
||||||
typename Allocator>
|
typename Allocator>
|
||||||
class RedBlackTree {
|
class RedBlackTree : public xo::gc::gc_allocator_traits<Allocator>::template object_interface<Allocator> {
|
||||||
static_assert(ordered_key<Key>);
|
static_assert(ordered_key<Key>);
|
||||||
static_assert(valid_rbtree_reduce_functor<Reduce, Value>);
|
static_assert(valid_rbtree_reduce_functor<Reduce, Value>);
|
||||||
|
|
||||||
|
|
@ -87,6 +87,9 @@ namespace xo {
|
||||||
using iterator = detail::Iterator<Key, Value, Reduce, GcObjectInterface>;
|
using iterator = detail::Iterator<Key, Value, Reduce, GcObjectInterface>;
|
||||||
using const_iterator = detail::ConstIterator<Key, Value, Reduce, GcObjectInterface>;
|
using const_iterator = detail::ConstIterator<Key, Value, Reduce, GcObjectInterface>;
|
||||||
|
|
||||||
|
using Reflect = xo::reflect::Reflect;
|
||||||
|
using TaggedPtr = xo::reflect::TaggedPtr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit RedBlackTree(const allocator_type & alloc = allocator_type{},
|
explicit RedBlackTree(const allocator_type & alloc = allocator_type{},
|
||||||
bool debug_flag = false) :
|
bool debug_flag = false) :
|
||||||
|
|
@ -115,6 +118,21 @@ namespace xo {
|
||||||
{}
|
{}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static RedBlackTree * make(const allocator_type & alloc = allocator_type{},
|
||||||
|
bool debug_flag = false)
|
||||||
|
{
|
||||||
|
RedBlackTree * tree = allocator_traits::allocate(alloc, 1);
|
||||||
|
try {
|
||||||
|
// placement new
|
||||||
|
allocator_traits::construct(alloc, tree, alloc, debug_flag);
|
||||||
|
return tree;
|
||||||
|
} catch(...) {
|
||||||
|
allocator_traits::deallocate(alloc, tree, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool empty() const { return size_ == 0; }
|
bool empty() const { return size_ == 0; }
|
||||||
size_type size() const { return size_; }
|
size_type size() const { return size_; }
|
||||||
size_type max_size() const { return std::numeric_limits<difference_type>::max(); }
|
size_type max_size() const { return std::numeric_limits<difference_type>::max(); }
|
||||||
|
|
@ -551,23 +569,52 @@ namespace xo {
|
||||||
return true;
|
return true;
|
||||||
} /*verify_ok*/
|
} /*verify_ok*/
|
||||||
|
|
||||||
void display() const { RbUtil::display(this->root_, 0); } /*display*/
|
void display_to_log() const { RbUtil::display(this->root_, 0); } /*display*/
|
||||||
|
|
||||||
private:
|
// ----- Inherited from GcObjectInterface -----
|
||||||
|
|
||||||
|
virtual TaggedPtr self_tp() const {
|
||||||
|
return Reflect::make_tp(const_cast<RedBlackTree *>(this));
|
||||||
|
}
|
||||||
|
virtual void display(std::ostream & os) const {
|
||||||
|
os << "<RedBlackTree>";
|
||||||
|
}
|
||||||
|
virtual std::size_t _shallow_size() const { return sizeof(*this); }
|
||||||
|
virtual IObject * _shallow_copy(gc::IAlloc * gc) const {
|
||||||
|
if constexpr (GcObjectInterface::_requires_gc_hooks) {
|
||||||
|
xo::Cpof cpof(gc, this);
|
||||||
|
return new (cpof) RedBlackTree(*this);
|
||||||
|
} else {
|
||||||
|
assert(false && "_shallow_copy assumes gc enabled");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual std::size_t _forward_children(gc::IAlloc * gc) {
|
||||||
|
if constexpr (GcObjectInterface::_requires_gc_hooks) {
|
||||||
|
using xo::gc::ObjectVisitor;
|
||||||
|
|
||||||
|
ObjectVisitor<Reduce>::forward_children(reduce_fn_, gc);
|
||||||
|
gc->forward_inplace(reinterpret_cast<IObject **>(&root_));
|
||||||
|
|
||||||
|
return RedBlackTree::_shallow_size();
|
||||||
|
} else {
|
||||||
|
assert(false && "_forward_children assumes gc enabled");
|
||||||
|
return 0ul;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** allocator state **/
|
/** allocator state **/
|
||||||
node_allocator_type node_alloc_;
|
node_allocator_type node_alloc_;
|
||||||
/** number of nodes in this tree. Each node holds one (key,value) pair **/
|
/** number of nodes in this tree. Each node holds one (key,value) pair **/
|
||||||
size_t size_ = 0;
|
size_t size_ = 0;
|
||||||
/** root of red/black tree. Empty tree has null root. **/
|
|
||||||
RbNode * root_ = nullptr;
|
|
||||||
/** accumulates custom order statistics;
|
/** accumulates custom order statistics;
|
||||||
* for example partial sums of @tparam Values
|
* for example partial sums of @tparam Values
|
||||||
* reduce_fn_:: (Accumulator x Key) -> Accumulator
|
* reduce_fn_:: (Accumulator x Key) -> Accumulator
|
||||||
**/
|
**/
|
||||||
Reduce reduce_fn_;
|
Reduce reduce_fn_;
|
||||||
|
/** root of red/black tree. Empty tree has null root. **/
|
||||||
|
RbNode * root_ = nullptr;
|
||||||
/** true to enable debug logging **/
|
/** true to enable debug logging **/
|
||||||
bool debug_flag_ = false;
|
bool debug_flag_ = false;
|
||||||
}; /*RedBlackTree*/
|
}; /*RedBlackTree*/
|
||||||
|
|
@ -580,7 +627,7 @@ namespace xo {
|
||||||
operator<<(std::ostream & os,
|
operator<<(std::ostream & os,
|
||||||
RedBlackTree<Key, Value, Reduce, Allocator> const & tree)
|
RedBlackTree<Key, Value, Reduce, Allocator> const & tree)
|
||||||
{
|
{
|
||||||
tree.display();
|
tree.display(os);
|
||||||
return os;
|
return os;
|
||||||
} /*operator<<*/
|
} /*operator<<*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "xo/allocutil/ObjectVisitor.hpp"
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
|
|
@ -34,12 +35,22 @@ namespace xo {
|
||||||
}; /*NullReduce*/
|
}; /*NullReduce*/
|
||||||
|
|
||||||
inline std::ostream & operator<<(std::ostream & os,
|
inline std::ostream & operator<<(std::ostream & os,
|
||||||
null_reduce_value /*x*/)
|
null_reduce_value /*x*/)
|
||||||
{
|
{
|
||||||
os << "{}";
|
os << "{}";
|
||||||
return os;
|
return os;
|
||||||
} /*operator<<*/
|
} /*operator<<*/
|
||||||
} /*namespace tree*/
|
} /*namespace tree*/
|
||||||
|
|
||||||
|
namespace gc {
|
||||||
|
template <typename Value>
|
||||||
|
class ObjectVisitor<xo::tree::NullReduce<Value>> {
|
||||||
|
public:
|
||||||
|
static_assert(std::is_empty_v<xo::tree::NullReduce<Value>>);
|
||||||
|
|
||||||
|
static void forward_children(xo::tree::NullReduce<Value> &, xo::gc::IAlloc *) {}
|
||||||
|
};
|
||||||
|
} /*namespace gc*/
|
||||||
} /*namespace xo*/
|
} /*namespace xo*/
|
||||||
|
|
||||||
/* end NullReduce.hpp */
|
/* end NullReduce.hpp */
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,17 @@ namespace xo {
|
||||||
value_type combine(value_type x, value_type y) const { return x + y; }
|
value_type combine(value_type x, value_type y) const { return x + y; }
|
||||||
bool is_equal(value_type x, value_type y) const { return x == y; }
|
bool is_equal(value_type x, value_type y) const { return x == y; }
|
||||||
}; /*OrdinalReduce*/
|
}; /*OrdinalReduce*/
|
||||||
|
|
||||||
} /*namespace tree*/
|
} /*namespace tree*/
|
||||||
|
|
||||||
|
namespace gc {
|
||||||
|
template <typename Value>
|
||||||
|
class ObjectVisitor<xo::tree::OrdinalReduce<Value>> {
|
||||||
|
public:
|
||||||
|
static_assert(std::is_empty_v<xo::tree::OrdinalReduce<Value>>);
|
||||||
|
|
||||||
|
static void forward_children(xo::tree::OrdinalReduce<Value> &, xo::gc::IAlloc *) {}
|
||||||
|
};
|
||||||
|
} /*namespace gc*/
|
||||||
} /*namespace xo*/
|
} /*namespace xo*/
|
||||||
|
|
||||||
/* end OrdinalReduce.hpp */
|
/* end OrdinalReduce.hpp */
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "xo/allocutil/ObjectVisitor.hpp"
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
|
|
@ -48,7 +49,18 @@ namespace xo {
|
||||||
|
|
||||||
bool is_equal(value_type const & x, value_type const & y) const { return x == y; }
|
bool is_equal(value_type const & x, value_type const & y) const { return x == y; }
|
||||||
}; /*SumReduce*/
|
}; /*SumReduce*/
|
||||||
}
|
} /*namespace tree*/
|
||||||
|
|
||||||
|
namespace gc {
|
||||||
|
template <typename Value>
|
||||||
|
class ObjectVisitor<xo::tree::SumReduce<Value>> {
|
||||||
|
public:
|
||||||
|
static_assert(std::is_empty_v<xo::tree::SumReduce<Value>>);
|
||||||
|
|
||||||
|
/* trivial, since SumReduce<Value> is stateless */
|
||||||
|
static void forward_children(xo::tree::SumReduce<Value> &, xo::gc::IAlloc *) {}
|
||||||
|
};
|
||||||
|
} /*namespace gc*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* end SumReduce.hpp */
|
/* end SumReduce.hpp */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue