xo-callback xo-alloc: + GC copy callbacks + unique_ptr cbset support

This commit is contained in:
Roland Conybeare 2025-08-12 12:53:06 -05:00
commit 279a1a040c
3 changed files with 47 additions and 2 deletions

View file

@ -7,6 +7,7 @@
#include "ListAlloc.hpp"
#include "GcStatistics.hpp"
#include "xo/callback/UpCallbackSet.hpp"
#include "xo/indentlog/print/array.hpp"
#include <vector>
#include <array>
@ -105,12 +106,31 @@ namespace xo {
using MutationLog = std::vector<MutationLogEntry>;
/** @class GcCopyCallback
* @brief optional callback to observe individual copy operations during GC
*
* For viz
**/
class GcCopyCallback {
public:
virtual void notify_gc_copy(std::size_t z, const void * src_addr, const void * dest_addr,
generation src_gen, generation dest_gen) = 0;
/** invoked when added to callback set (i.e. @ref GC::GcCopyCallbackSet) **/
void notify_add_callback() {}
/** invoked when removed from callback set **/
void notify_remove_callback() {}
};
/** @class GC
* @brief generational garbage collector
*
* Works with objects of type @ref xo::Object
**/
class GC : public IAlloc {
public:
using CallbackId = xo::fn::CallbackId;
using GcCopyCallbackSet = xo::fn::UpCallbackSet<GcCopyCallback>;
public:
/** create new GC instance with configuration @p config **/
explicit GC(const Config & config);
@ -160,6 +180,11 @@ namespace xo {
* from @c *addr
**/
void add_gc_root(Object ** addr);
/** may optionally use this to observe GC copy phase.
* Will be invoked once _per surviving object_, so not cheap.
* Intended for GC visualization.
**/
CallbackId add_gc_copy_callback(up<GcCopyCallback> fn);
/** request garbage collection. **/
void request_gc(generation g);
/** disable garbage collection until matching call to @ref enable_gc.
@ -335,6 +360,9 @@ namespace xo {
/** enabled when 0. disabled when <0 **/
int gc_enabled_ = 0;
/** for (optional) viz: invoke when copying individual objects **/
GcCopyCallbackSet gc_copy_cbset_;
};
} /*namespace gc*/

View file

@ -15,5 +15,6 @@ set(SELF_SRCS
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
xo_dependency(${SELF_LIB} reflect)
xo_dependency(${SELF_LIB} callback)
#end CMakeLists.txt

View file

@ -289,6 +289,12 @@ namespace xo {
gc_root_v_.push_back(addr);
}
auto
GC::add_gc_copy_callback(up<GcCopyCallback> fn) -> CallbackId
{
return gc_copy_cbset_.add_callback(std::move(fn));
}
void
GC::checkpoint()
{
@ -322,16 +328,19 @@ namespace xo {
{
scope log(XO_DEBUG(config_.debug_flag_), xtag("z", z), xtag("+pad", IAlloc::alloc_padding(z)));
generation_result gr = this->fromspace_generation_of(src);
generation_result src_gr = this->fromspace_generation_of(src);
std::byte * retval = nullptr;
switch (gr) {
switch (src_gr) {
case generation_result::tenured:
{
log && log("tenured");
retval = this->tenured_to()->alloc(z);
gc_copy_cbset_.invoke(&GcCopyCallback::notify_gc_copy,
z, src, retval, generation::tenured, generation::tenured);
}
break;
case generation_result::nursery:
@ -347,11 +356,18 @@ namespace xo {
assert(this->tospace_generation_of(retval) == generation_result::tenured);
gc_copy_cbset_.invoke(&GcCopyCallback::notify_gc_copy,
z, src, retval, generation::nursery, generation::tenured);
this->gc_statistics_.total_promoted_ += IAlloc::with_padding(z);
} else {
log && log("nursery");
retval = this->nursery_to()->alloc(z);
gc_copy_cbset_.invoke(&GcCopyCallback::notify_gc_copy,
z, src, retval, generation::nursery, generation::nursery);
}
}
break;