xo-alloc - compile-time property for trivial deallocate
This commit is contained in:
parent
f9c3a4807a
commit
b5d70d0f1b
3 changed files with 84 additions and 20 deletions
|
|
@ -42,6 +42,7 @@ namespace xo {
|
|||
**/
|
||||
using gc_object_interface = xo::Object;
|
||||
using has_incremental_gc_interface = std::true_type;
|
||||
using has_trivial_deallocate = std::true_type;
|
||||
|
||||
public:
|
||||
virtual ~IAlloc() {}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,20 @@ namespace xo {
|
|||
struct has_incremental_gc_interface<A, std::void_t<typename A::has_incremental_gc_interface>> :
|
||||
A::has_incremental_gc_interface {};
|
||||
|
||||
// default: allocate A fallback to standard non-GC allocator behavior
|
||||
template <typename A, typename = void>
|
||||
struct has_trivial_deallocate : std::false_type {};
|
||||
|
||||
// opt-in: A provides nested type 'has_trivial_deallocate':
|
||||
// struct A {
|
||||
// using has_trivial_deallocate = std::true_type;
|
||||
// };
|
||||
template <typename A>
|
||||
struct has_trivial_deallocate<A, std::void_t<typename A::has_trivial_deallocate>> :
|
||||
A::has_trivial_deallocate {};
|
||||
|
||||
// default: empty object interface.
|
||||
//
|
||||
// classes that want to conditionally support GC
|
||||
// (e.g. see xo::tree::RedBlackTree, xo::tree::Node
|
||||
// in xo-ordinal-tree)
|
||||
|
|
@ -85,13 +98,24 @@ namespace xo {
|
|||
struct object_interface {
|
||||
/** see also IObject::_requires_gc_hooks **/
|
||||
static constexpr bool _requires_gc_hooks = false;
|
||||
/** see also IObject::_requires_write_barrier **/
|
||||
static constexpr bool _requires_write_barrier = false;
|
||||
|
||||
/** see also IObject::_gc_assign_member **/
|
||||
template <typename T>
|
||||
void _gc_assign_member(T ** lhs,
|
||||
T * rhs,
|
||||
A & alloc)
|
||||
{
|
||||
*lhs = rhs;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// specialization when A provides gc_object_interface
|
||||
template <typename A>
|
||||
struct object_interface<A, std::void_t<typename A::gc_object_interface>>
|
||||
: public A::gc_object_interface {
|
||||
};
|
||||
: public A::gc_object_interface {};
|
||||
|
||||
// classes that want to conditionally support GC
|
||||
// (e.g. see xo::tree::RedBlackTree, xo::tree::Node
|
||||
|
|
@ -101,14 +125,23 @@ namespace xo {
|
|||
//
|
||||
using object_interface_type = object_interface<Allocator>;
|
||||
|
||||
/** true iff this allocator advertises itself as an incremental collector
|
||||
* allocator will include:
|
||||
/** true iff this allocator advertises itself as an incremental collector.
|
||||
* Allocator will include:
|
||||
*
|
||||
* struct GC {
|
||||
* struct IAlloc {
|
||||
* using has_incremental_gc_interface = std::true_type;
|
||||
* };
|
||||
**/
|
||||
static inline constexpr bool has_incremental_gc_interface_v = has_incremental_gc_interface<Allocator>::value;
|
||||
|
||||
/** true iff this allocator advertises trivial deallocate
|
||||
* Allocate will include:
|
||||
*
|
||||
* struct IAlloc {
|
||||
* using has_trivial_deallocate = std::true_type;
|
||||
* };
|
||||
**/
|
||||
static inline constexpr bool has_trivial_deallocate_v = has_trivial_deallocate<Allocator>::value;
|
||||
};
|
||||
} /*namespace gc*/
|
||||
} /*namespace xo*/
|
||||
|
|
|
|||
|
|
@ -420,35 +420,53 @@ namespace xo {
|
|||
} /*find_sum_glb*/
|
||||
|
||||
void clear() {
|
||||
auto visitor_fn = [this](RbNode const * x, uint32_t /*d*/) {
|
||||
/* RbUtil.postorder_node_visitor() isn't expecting us to
|
||||
* alter node, but will not examine it after it's deleted
|
||||
*/
|
||||
RbNode * xx = const_cast<RbNode *>(x);
|
||||
if constexpr (node_allocator_traits::has_trivial_deallocate_v) {
|
||||
// nothing to do since trivial deallocator
|
||||
} else {
|
||||
// visitor to delete all Nodes
|
||||
auto visitor_fn = [this](RbNode const * x, uint32_t depth) {
|
||||
(void)depth;
|
||||
|
||||
/* RbUtil.postorder_node_visitor() isn't expecting us to
|
||||
* alter node, but will not examine it after it's deleted
|
||||
*/
|
||||
RbNode * xx = const_cast<RbNode *>(x);
|
||||
|
||||
node_allocator_traits::deallocate(node_alloc_, xx, 1);
|
||||
};
|
||||
|
||||
RbUtil::postorder_node_visitor(this->root_,
|
||||
0 /*depth -- ignored by lambda*/,
|
||||
visitor_fn);
|
||||
|
||||
node_allocator_traits::deallocate(node_alloc_, xx, 1);
|
||||
// delete x
|
||||
};
|
||||
|
||||
RbUtil::postorder_node_visitor(this->root_,
|
||||
0 /*depth -- ignored by lambda*/,
|
||||
visitor_fn);
|
||||
|
||||
this->size_ = 0;
|
||||
this->root_ = nullptr;
|
||||
} /*clear*/
|
||||
|
||||
std::pair<iterator, bool>
|
||||
insert(std::pair<Key const, Value> const & kv_pair) {
|
||||
RbNode * adj_root = this->root_;
|
||||
|
||||
std::pair<bool, RbNode *> insert_result
|
||||
= RbUtil::insert_aux(kv_pair,
|
||||
true /*allow_replace_flag*/,
|
||||
this->reduce_fn_,
|
||||
&(this->root_));
|
||||
&adj_root);
|
||||
|
||||
if (insert_result.first)
|
||||
if (insert_result.first) {
|
||||
++(this->size_);
|
||||
|
||||
if (adj_root != root_) {
|
||||
allocator_type alloc = node_alloc_;
|
||||
|
||||
this->_gc_assign_member(&(this->root_), adj_root, alloc);
|
||||
}
|
||||
} else {
|
||||
assert(adj_root == root_);
|
||||
}
|
||||
|
||||
return (std::pair<iterator, bool>
|
||||
(iterator(detail::ID_Forward,
|
||||
detail::IL_Regular,
|
||||
|
|
@ -464,16 +482,28 @@ namespace xo {
|
|||
constexpr bool c_logging_enabled = false;
|
||||
scope log(XO_DEBUG(c_logging_enabled));
|
||||
|
||||
RbNode * adj_root = this->root_;
|
||||
|
||||
std::pair<bool, RbNode *> insert_result
|
||||
= RbUtil::insert_aux(this->node_alloc_,
|
||||
std::move(kv_pair),
|
||||
true /*allow_replace_flag*/,
|
||||
this->reduce_fn_,
|
||||
&(this->root_));
|
||||
this->debug_flag_,
|
||||
&adj_root);
|
||||
|
||||
if (insert_result.first)
|
||||
if (insert_result.first) {
|
||||
++(this->size_);
|
||||
|
||||
if (adj_root != root_) {
|
||||
allocator_type alloc = node_alloc_;
|
||||
|
||||
this->_gc_assign_member(&(this->root_), adj_root, alloc);
|
||||
}
|
||||
} else {
|
||||
assert(adj_root == root_);
|
||||
}
|
||||
|
||||
return (std::pair<iterator, bool>
|
||||
(iterator(detail::ID_Forward,
|
||||
detail::IL_Regular,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue