xo-interpreter2: work towards utest w/ vsm+reader [WIP]
This commit is contained in:
parent
6b948e8200
commit
756e8a94cf
26 changed files with 503 additions and 270 deletions
|
|
@ -62,6 +62,10 @@ namespace xo {
|
|||
|
||||
/** RTTI: unique id# for actual runtime data representation **/
|
||||
virtual typeseq _typeseq() const noexcept = 0;
|
||||
/** destroy instance @p d. Calls c++ destructor for actual runtime type.
|
||||
* does not recover memory.
|
||||
**/
|
||||
virtual void _drop(Opaque d) const noexcept = 0;
|
||||
/** optional name for allocator @p d .
|
||||
* Allows labeling allocators, for diagnostics/instrumentation.
|
||||
**/
|
||||
|
|
@ -142,10 +146,12 @@ namespace xo {
|
|||
virtual value_type alloc_copy(Opaque d, value_type src) const = 0;
|
||||
/** reset allocator @p d to empty state. **/
|
||||
virtual void clear(Opaque d) const = 0;
|
||||
#ifdef OBSOLETE
|
||||
/** Destruct allocator @p d.
|
||||
* Releases allocator memory to operating system.
|
||||
**/
|
||||
virtual void destruct_data(Opaque d) const = 0;
|
||||
#endif
|
||||
|
||||
///@}
|
||||
}; /*AAllocator*/
|
||||
|
|
|
|||
|
|
@ -32,7 +32,10 @@ namespace xo {
|
|||
const AAllocator * iface() const { return std::launder(this); }
|
||||
|
||||
// from AAllocator
|
||||
|
||||
// builtin methods
|
||||
typeseq _typeseq() const noexcept override { return s_typeseq; }
|
||||
void _drop(Opaque) const noexcept override { _fatal(); }
|
||||
|
||||
// const methods
|
||||
[[noreturn]] std::string_view name(Copaque) const noexcept override { _fatal(); }
|
||||
|
|
@ -55,7 +58,6 @@ namespace xo {
|
|||
[[noreturn]] value_type sub_alloc(Opaque, std::size_t, bool) const override { _fatal(); }
|
||||
[[noreturn]] value_type alloc_copy(Opaque, value_type) const override { _fatal(); }
|
||||
[[noreturn]] void clear(Opaque) const override { _fatal(); }
|
||||
[[noreturn]] void destruct_data(Opaque) const override { _fatal(); }
|
||||
|
||||
private:
|
||||
[[noreturn]] static void _fatal();
|
||||
|
|
|
|||
|
|
@ -36,10 +36,14 @@ namespace xo {
|
|||
|
||||
// from AAllocator
|
||||
|
||||
// const methods
|
||||
|
||||
// builtin methods
|
||||
/** return typeseq for @tparam DRepr **/
|
||||
typeseq _typeseq() const noexcept override { return s_typeseq; }
|
||||
/** invoke native c++ dtor **/
|
||||
void _drop(Opaque d) const noexcept override { _dcast(d).~DRepr(); }
|
||||
|
||||
// const methods
|
||||
|
||||
std::string_view name(Copaque d) const noexcept override { return I::name(_dcast(d)); }
|
||||
size_type reserved(Copaque d) const noexcept override { return I::reserved(_dcast(d)); }
|
||||
size_type size(Copaque d) const noexcept override { return I::size(_dcast(d)); }
|
||||
|
|
@ -73,7 +77,6 @@ namespace xo {
|
|||
value_type alloc_copy(Opaque d,
|
||||
value_type src) const override { return I::alloc_copy(_dcast(d), src); }
|
||||
void clear(Opaque d) const override { return I::clear(_dcast(d)); }
|
||||
void destruct_data(Opaque d) const override { return I::destruct_data(_dcast(d)); }
|
||||
///@}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ namespace xo {
|
|||
RAllocator(Object::DataPtr data) : Object{std::move(data)} {}
|
||||
|
||||
typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); }
|
||||
void _drop() const noexcept { O::iface()->_drop(O::data()); }
|
||||
std::string_view name() const noexcept { return O::iface()->name(O::data()); }
|
||||
size_type reserved() const noexcept { return O::iface()->reserved(O::data()); }
|
||||
size_type size() const noexcept { return O::iface()->size(O::data()); }
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ namespace ut {
|
|||
using xo::mm::ACollector;
|
||||
using xo::mm::AGCObject;
|
||||
using xo::mm::DX1Collector;
|
||||
using xo::mm::CollectorConfig;
|
||||
using xo::mm::X1CollectorConfig;
|
||||
using xo::mm::ArenaConfig;
|
||||
using xo::facet::with_facet;
|
||||
using xo::facet::typeseq;
|
||||
|
|
@ -54,14 +54,13 @@ namespace ut {
|
|||
REQUIRE(s_init.evidence());
|
||||
|
||||
// Create collector
|
||||
CollectorConfig cfg{
|
||||
.name_ = "x1_duniquestring_test",
|
||||
.arena_config_ = ArenaConfig{
|
||||
.size_ = 8192,
|
||||
.store_header_flag_ = true},
|
||||
.object_types_z_ = 16384,
|
||||
.gc_trigger_v_{{1024, 1024}},
|
||||
.debug_flag_ = false,
|
||||
X1CollectorConfig cfg{ .name_ = "x1_duniquestring_test",
|
||||
.arena_config_ = ArenaConfig{
|
||||
.size_ = 8192,
|
||||
.store_header_flag_ = true},
|
||||
.object_types_z_ = 16384,
|
||||
.gc_trigger_v_{{1024, 1024}},
|
||||
.debug_flag_ = false,
|
||||
};
|
||||
|
||||
DX1Collector gc(cfg);
|
||||
|
|
|
|||
|
|
@ -1,74 +0,0 @@
|
|||
/** @file OUniqueBox.hpp
|
||||
*
|
||||
* @author Roland Conybeare, Dec 2025
|
||||
**/
|
||||
|
||||
namespace xo {
|
||||
namespace facet {
|
||||
/**
|
||||
* Uniquely-owned instance with runtime polymorphism.
|
||||
*
|
||||
* Reminder that in the facet object model we expect
|
||||
* objects to be transient.
|
||||
*
|
||||
|
||||
*
|
||||
* Unlike OUniqueBox<AInterface, ..> can use for variant data
|
||||
* without additional overhead. Tradeoff is that avoiding such
|
||||
* overhead excludes std::unique_ptr.
|
||||
*
|
||||
* We're going to instead rely on AInterface providing a destruct_data() method,
|
||||
* so in practice get the deleter from interface state.
|
||||
*
|
||||
* Possibly means we need all abstract interfaces to share a common base
|
||||
*
|
||||
* Remarks:
|
||||
* - when @tparam Data is supplied
|
||||
**/
|
||||
template <typename AInterface, typename Data = DOpaquePlaceholder>
|
||||
struct OUniqueBox {
|
||||
using AbstractInterface = AInterface;
|
||||
using ISpecific = ISpecificFor<AInterface, Data>::ImplType;
|
||||
/* note: Data can be void here */
|
||||
using DataType = Data;
|
||||
using DataBox = Data*;
|
||||
|
||||
explicit OUniqueBox() {}
|
||||
/* unsatisfactory b/c doesn't enforce that @p d is heap-allocated */
|
||||
explicit OUniqueBox(DataBox d) : data_{std::move(d)} {}
|
||||
|
||||
~OUniqueBox() {
|
||||
if (data_ != nullptr) {
|
||||
this->iface()->destruct_data(data_);
|
||||
delete data_;
|
||||
this->data_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const AInterface * iface() const
|
||||
requires std::is_same_v<Data, DOpaquePlaceholder>
|
||||
{
|
||||
return std::launder(&iface_);
|
||||
}
|
||||
|
||||
const AInterface * iface() const
|
||||
requires (!std::is_same_v<Data, DOpaquePlaceholder>)
|
||||
{
|
||||
return &iface_;
|
||||
}
|
||||
|
||||
/** note: would prefer this to be constexpr, but not simple asof gcc 14.3 **/
|
||||
static bool _valid;
|
||||
|
||||
/** note: load-bearing for routing classes such as RComplex<OUniqueBox> **/
|
||||
Data * data() const { return data_; }
|
||||
|
||||
ISpecific iface_;
|
||||
DataBox data_ = nullptr;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end OUniqueBox.hpp */
|
||||
83
xo-facet/include/xo/facet/box.hpp
Normal file
83
xo-facet/include/xo/facet/box.hpp
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/** @file box.hpp
|
||||
*
|
||||
* @author Roland Conybeare, Jan 2026
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "obj.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace facet {
|
||||
|
||||
/** object with owned state
|
||||
* - with default DRepr argument:
|
||||
* type-erased container (runtime polymorphism).
|
||||
* - with sepcific DRepr argument:
|
||||
* typed container (comptime polymorphism).
|
||||
**/
|
||||
template <typename AFacet, typename DRepr = DVariantPlaceholder>
|
||||
struct box : public RoutingType<AFacet, OObject<AFacet, DRepr>> {
|
||||
using Super = RoutingType<AFacet, OObject<AFacet, DRepr>>;
|
||||
|
||||
box() : Super() {}
|
||||
|
||||
/** box takes ownership of data @p *d;
|
||||
* will destroy when box goes out of scope.
|
||||
*
|
||||
* Note this is not useful when DRepr=DVariablePlaceholder
|
||||
**/
|
||||
explicit box(Super::DataPtr d) : Super(d) {}
|
||||
|
||||
/** Adopt instance that has interface @p iface and (type-erased here)
|
||||
* representation @p data
|
||||
**/
|
||||
box(const AFacet * iface, void * data)
|
||||
requires std::is_same_v<DRepr, DVariantPlaceholder>
|
||||
: Super(iface, data)
|
||||
{}
|
||||
|
||||
/** (copy ctor not supported -- ownership is unique) **/
|
||||
|
||||
// --------------------------------
|
||||
|
||||
/** Move constructor **/
|
||||
template <typename DOther>
|
||||
box(box<AFacet, DOther> && other)
|
||||
requires (std::is_same_v<DRepr, DVariantPlaceholder>
|
||||
|| std::is_same_v<DRepr, DOther>)
|
||||
: obj<AFacet,DRepr>()
|
||||
{
|
||||
/* replacing .iface_ along w/ .data_ */
|
||||
this->from_obj(other);
|
||||
|
||||
other.reset_opaque(nullptr);
|
||||
}
|
||||
|
||||
/** explicit conversion to obj<AFacet,DRepr> **/
|
||||
obj<AFacet, DRepr> to_op() const noexcept { return obj<AFacet, DRepr>(this->iface(), this->data()); }
|
||||
|
||||
/** Take ownership from unowned object **/
|
||||
template <typename DOther>
|
||||
box & adopt(const obj<AFacet, DOther> & other)
|
||||
requires (std::is_same_v<DRepr, DVariantPlaceholder>
|
||||
|| std::is_same_v<DRepr, DOther>)
|
||||
{
|
||||
/* replace .iface_ along w/ .data_ */
|
||||
this->from_obj(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~box() {
|
||||
auto p = this->data();
|
||||
this->_drop();
|
||||
::operator delete(p);
|
||||
}
|
||||
};
|
||||
} /*namespace facet*/
|
||||
|
||||
using facet::box;
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end box.hpp */
|
||||
|
|
@ -12,9 +12,9 @@
|
|||
namespace xo {
|
||||
namespace facet {
|
||||
/** object with borrowed state pointer
|
||||
* - With default Data argument:
|
||||
* - With default DRepr argument:
|
||||
* type-erased polymorphic container
|
||||
* - with specific Data argument:
|
||||
* - with specific DRepr argument:
|
||||
* typed container. Trivially de-virtualizable
|
||||
*
|
||||
* Example:
|
||||
|
|
@ -88,7 +88,7 @@ namespace xo {
|
|||
* - same strategy for holding state (naked / unique / refcounted ...)
|
||||
**/
|
||||
template <typename DOther>
|
||||
obj(const obj<AFacet, DOther> && other)
|
||||
obj(obj<AFacet, DOther> && other)
|
||||
requires (std::is_same_v<DRepr, DVariantPlaceholder>
|
||||
|| std::is_convertible_v<DRepr, DOther>)
|
||||
: Super()
|
||||
|
|
@ -98,7 +98,7 @@ namespace xo {
|
|||
}
|
||||
|
||||
obj & operator=(const obj & rhs) {
|
||||
/* ensure we replace .iface_ along w/ .ata_ */
|
||||
/* ensure we replace .iface_ along w/ .data_ */
|
||||
this->from_obj(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "X1CollectorConfig.hpp"
|
||||
#include "GCObject.hpp"
|
||||
#include "generation.hpp"
|
||||
#include "object_age.hpp"
|
||||
|
|
@ -40,104 +41,6 @@ namespace xo {
|
|||
};
|
||||
#endif
|
||||
|
||||
struct CollectorConfig {
|
||||
using size_type = std::size_t;
|
||||
|
||||
#ifdef OBSOLETE // get from arena_config_.header_
|
||||
/*
|
||||
* alloc header
|
||||
* TTTTTTTTTTTTGGGGGZZZZZZZZZZZZ
|
||||
* < tseq ><gen>< size >
|
||||
*
|
||||
* masking
|
||||
*
|
||||
* ..432107654321076543210 bit
|
||||
*
|
||||
* > < .gen_bits
|
||||
* 0..............01111111 gen_mask_unshifted
|
||||
* 0..011111110..........0 gen_mask_shifted
|
||||
* > < gen_shift
|
||||
*/
|
||||
//constexpr std::uint64_t gen_mult() const;
|
||||
constexpr std::uint64_t gen_shift() const;
|
||||
constexpr std::uint64_t gen_mask_unshifted() const;
|
||||
constexpr std::uint64_t gen_mask_shifted() const;
|
||||
|
||||
//constexpr std::uint64_t tseq_mult() const;
|
||||
constexpr std::uint64_t tseq_shift() const;
|
||||
constexpr std::uint64_t tseq_mask_unshifted() const;
|
||||
constexpr std::uint64_t tseq_mask_shifted() const;
|
||||
#endif
|
||||
|
||||
|
||||
/** copy of this config,
|
||||
* with @c arena_config_.size_ set to @p gen_z
|
||||
**/
|
||||
CollectorConfig with_size(std::size_t gen_z);
|
||||
|
||||
generation age2gen(object_age age) const noexcept {
|
||||
return generation(age % n_survive_threshold_);
|
||||
}
|
||||
|
||||
public:
|
||||
// ----- Instance Variables -----
|
||||
|
||||
/** optional name, for diagnostics **/
|
||||
std::string name_;
|
||||
|
||||
/** Configuration for collector spaces.
|
||||
* Will have at least {nursery,tenured} x {from,to} spaces.
|
||||
* Not using name_ member.
|
||||
*
|
||||
* REQUIRE:
|
||||
* - arena_config_.store_header_flag_ must be true
|
||||
**/
|
||||
ArenaConfig arena_config_;
|
||||
|
||||
/** storage for N object types requires 8*N bytes **/
|
||||
std::size_t object_types_z_ = 2*1024*1024;
|
||||
|
||||
/** storage for N object roots requires 8*N bytes **/
|
||||
std::size_t object_roots_z_ = 16*1024;
|
||||
|
||||
/** number of bits to represent generation **/
|
||||
std::uint64_t gen_bits_ = 8;
|
||||
|
||||
/** number of bits to represent tseq **/
|
||||
std::uint64_t tseq_bits_ = 24;
|
||||
|
||||
/** Number of generations.
|
||||
* Must be at least 2.
|
||||
**/
|
||||
uint32_t n_generation_ = 2;
|
||||
|
||||
/** Number of promotion steps.
|
||||
* An object that survives this number of collections
|
||||
* advances to the next generation.
|
||||
**/
|
||||
uint32_t n_survive_threshold_ = 2;
|
||||
|
||||
/** Trigger garbage collection when to-space allocation for
|
||||
* generation g reaches gc_trigger_v_[g]
|
||||
**/
|
||||
std::array<size_type, c_max_generation> gc_trigger_v_;
|
||||
|
||||
/** true -> enable incremental collection.
|
||||
* false -> only do full collection.
|
||||
*
|
||||
* Incremental collection requires mutation logs.
|
||||
**/
|
||||
bool allow_incremental_gc_ = true;
|
||||
|
||||
/** If non-zero remember statistics for
|
||||
* the last @p stats_history_z_ collections.
|
||||
**/
|
||||
uint32_t stats_history_z_ = false;
|
||||
|
||||
/** true to enable debug logging **/
|
||||
bool debug_flag_ = false;
|
||||
};
|
||||
|
||||
// ----- GCRunState -----
|
||||
|
||||
/** @class GCRunState
|
||||
|
|
@ -173,7 +76,7 @@ namespace xo {
|
|||
static constexpr size_t c_max_typeseq = 4096;
|
||||
|
||||
/** Create X1 collector instance. **/
|
||||
explicit DX1Collector(const CollectorConfig & cfg);
|
||||
explicit DX1Collector(const X1CollectorConfig & cfg);
|
||||
|
||||
/** faceted object pointer to this instance */
|
||||
template <typename AFacet = AAllocator>
|
||||
|
|
@ -344,7 +247,7 @@ namespace xo {
|
|||
|
||||
public:
|
||||
/** garbage collector configuration **/
|
||||
CollectorConfig config_;
|
||||
X1CollectorConfig config_;
|
||||
|
||||
/** current gc state **/
|
||||
GCRunState runstate_;
|
||||
|
|
|
|||
92
xo-gc/include/xo/gc/X1CollectorConfig.hpp
Normal file
92
xo-gc/include/xo/gc/X1CollectorConfig.hpp
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/** @file X1CollectorConfig.hpp
|
||||
*
|
||||
* @author Roland Conybeare, Jan 2026
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "object_age.hpp"
|
||||
#include "generation.hpp"
|
||||
#include <xo/arena/ArenaConfig.hpp>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace mm {
|
||||
struct X1CollectorConfig {
|
||||
using size_type = std::size_t;
|
||||
|
||||
/** copy of this config,
|
||||
* with @c arena_config_.size_ set to @p gen_z
|
||||
**/
|
||||
X1CollectorConfig with_size(std::size_t gen_z);
|
||||
|
||||
generation age2gen(object_age age) const noexcept {
|
||||
return generation(age % n_survive_threshold_);
|
||||
}
|
||||
|
||||
public:
|
||||
// ----- Instance Variables -----
|
||||
|
||||
/** optional name, for diagnostics **/
|
||||
std::string name_;
|
||||
|
||||
/** Configuration for collector spaces.
|
||||
* Will have at least {nursery,tenured} x {from,to} spaces.
|
||||
* Not using name_ member.
|
||||
*
|
||||
* REQUIRE:
|
||||
* - arena_config_.store_header_flag_ must be true
|
||||
**/
|
||||
ArenaConfig arena_config_;
|
||||
|
||||
/** storage for N object types requires 8*N bytes **/
|
||||
std::size_t object_types_z_ = 2*1024*1024;
|
||||
|
||||
/** storage for N object roots requires 8*N bytes **/
|
||||
std::size_t object_roots_z_ = 16*1024;
|
||||
|
||||
/** number of bits to represent generation **/
|
||||
std::uint64_t gen_bits_ = 8;
|
||||
|
||||
/** number of bits to represent tseq **/
|
||||
std::uint64_t tseq_bits_ = 24;
|
||||
|
||||
/** Number of generations.
|
||||
* Must be at least 2.
|
||||
**/
|
||||
uint32_t n_generation_ = 2;
|
||||
|
||||
/** Number of promotion steps.
|
||||
* An object that survives this number of collections
|
||||
* advances to the next generation.
|
||||
**/
|
||||
uint32_t n_survive_threshold_ = 2;
|
||||
|
||||
/** Trigger garbage collection when to-space allocation for
|
||||
* generation g reaches gc_trigger_v_[g]
|
||||
**/
|
||||
std::array<size_type, c_max_generation> gc_trigger_v_;
|
||||
|
||||
/** true -> enable incremental collection.
|
||||
* false -> only do full collection.
|
||||
*
|
||||
* Incremental collection requires mutation logs.
|
||||
**/
|
||||
bool allow_incremental_gc_ = true;
|
||||
|
||||
/** If non-zero remember statistics for
|
||||
* the last @p stats_history_z_ collections.
|
||||
**/
|
||||
uint32_t stats_history_z_ = false;
|
||||
|
||||
/** true to enable debug logging **/
|
||||
bool debug_flag_ = false;
|
||||
};
|
||||
|
||||
|
||||
} /*namespace mm*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end X1CollectorConfig.hpp */
|
||||
|
||||
|
|
@ -25,24 +25,24 @@ namespace xo {
|
|||
|
||||
namespace mm {
|
||||
|
||||
CollectorConfig
|
||||
CollectorConfig::with_size(std::size_t gen_z)
|
||||
X1CollectorConfig
|
||||
X1CollectorConfig::with_size(std::size_t gen_z)
|
||||
{
|
||||
CollectorConfig copy = *this;
|
||||
X1CollectorConfig copy = *this;
|
||||
copy.arena_config_ = arena_config_.with_size(gen_z);
|
||||
return copy;
|
||||
}
|
||||
|
||||
#ifdef NOT_USING
|
||||
constexpr std::uint64_t
|
||||
CollectorConfig::gen_mult() const {
|
||||
X1CollectorConfig::gen_mult() const {
|
||||
return 1ul << arena_config_.header_size_bits_;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NOT_USING
|
||||
constexpr std::uint64_t
|
||||
CollectorConfig::tseq_mult() const {
|
||||
X1CollectorConfig::tseq_mult() const {
|
||||
return 1ul << (gen_bits_ + arena_config_.header_size_bits_);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -69,7 +69,7 @@ namespace xo {
|
|||
|
||||
using size_type = xo::mm::DX1Collector::size_type;
|
||||
|
||||
DX1Collector::DX1Collector(const CollectorConfig & cfg) : config_{cfg}
|
||||
DX1Collector::DX1Collector(const X1CollectorConfig & cfg) : config_{cfg}
|
||||
{
|
||||
assert(config_.arena_config_.header_.size_bits_ +
|
||||
config_.arena_config_.header_.age_bits_ +
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
namespace xo {
|
||||
using xo::mm::AAllocator;
|
||||
using xo::mm::ACollector;
|
||||
using xo::mm::CollectorConfig;
|
||||
using xo::mm::X1CollectorConfig;
|
||||
using xo::mm::DX1Collector;
|
||||
using xo::mm::ArenaConfig;
|
||||
using xo::mm::AllocHeaderConfig;
|
||||
|
|
@ -61,12 +61,12 @@ namespace xo {
|
|||
0 /*tseq_bits*/,
|
||||
0 /*age_bits*/,
|
||||
16 /*size_bits*/), };
|
||||
CollectorConfig cfg = { .arena_config_ = arena_cfg,
|
||||
.n_generation_ = 2,
|
||||
.gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0}} };
|
||||
X1CollectorConfig cfg = { .arena_config_ = arena_cfg,
|
||||
.n_generation_ = 2,
|
||||
.gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0}} };
|
||||
|
||||
DX1Collector gc = DX1Collector{cfg};
|
||||
|
||||
|
|
@ -109,12 +109,12 @@ namespace xo {
|
|||
0 /*tseq_bits*/,
|
||||
0 /*age_bits*/,
|
||||
16 /*size_bits*/), };
|
||||
CollectorConfig cfg = { .arena_config_ = arena_cfg,
|
||||
.n_generation_ = 2,
|
||||
.gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0}} };
|
||||
X1CollectorConfig cfg = { .arena_config_ = arena_cfg,
|
||||
.n_generation_ = 2,
|
||||
.gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0}} };
|
||||
|
||||
DX1Collector gc = DX1Collector{cfg};
|
||||
|
||||
|
|
@ -135,12 +135,12 @@ namespace xo {
|
|||
0 /*tseq-bits*/,
|
||||
0 /*age-bits*/,
|
||||
16 /*size-bits*/), };
|
||||
CollectorConfig cfg = { .arena_config_ = arena_cfg,
|
||||
.n_generation_ = 2,
|
||||
.gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0}} };
|
||||
X1CollectorConfig cfg = { .arena_config_ = arena_cfg,
|
||||
.n_generation_ = 2,
|
||||
.gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0}} };
|
||||
|
||||
DX1Collector gc = DX1Collector{cfg};
|
||||
|
||||
|
|
@ -165,12 +165,12 @@ namespace xo {
|
|||
16 /*size-bits*/), };
|
||||
|
||||
/* collector with one generation collapses to a non-generational copying collector */
|
||||
CollectorConfig cfg = { .arena_config_ = arena_cfg,
|
||||
.n_generation_ = 1,
|
||||
.gc_trigger_v_ = {{64*1024, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0}} };
|
||||
X1CollectorConfig cfg = { .arena_config_ = arena_cfg,
|
||||
.n_generation_ = 1,
|
||||
.gc_trigger_v_ = {{64*1024, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0}} };
|
||||
|
||||
DX1Collector x1state = DX1Collector{cfg};
|
||||
|
||||
|
|
@ -209,12 +209,12 @@ namespace xo {
|
|||
};
|
||||
|
||||
/* collector with one generation collapses to a non-generational copying collector */
|
||||
CollectorConfig cfg = { .arena_config_ = arena_cfg,
|
||||
.n_generation_ = 1,
|
||||
.gc_trigger_v_ = {{64*1024, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0}} };
|
||||
X1CollectorConfig cfg = { .arena_config_ = arena_cfg,
|
||||
.n_generation_ = 1,
|
||||
.gc_trigger_v_ = {{64*1024, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0}} };
|
||||
|
||||
/* X1 allocator+collector */
|
||||
DX1Collector x1state = DX1Collector{cfg};
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace xo {
|
|||
using xo::mm::DX1CollectorIterator;
|
||||
using xo::mm::DArena;
|
||||
using xo::mm::DArenaIterator;
|
||||
using xo::mm::CollectorConfig;
|
||||
using xo::mm::X1CollectorConfig;
|
||||
using xo::mm::ArenaConfig;
|
||||
using xo::mm::AllocHeaderConfig;
|
||||
using xo::mm::cmpresult;
|
||||
|
|
@ -51,12 +51,12 @@ namespace xo {
|
|||
0 /*tseq_bits*/,
|
||||
0 /*age_bits*/,
|
||||
16 /*size_bits*/), };
|
||||
CollectorConfig cfg = { .arena_config_ = arena_cfg,
|
||||
.n_generation_ = 2,
|
||||
.gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0}} };
|
||||
X1CollectorConfig cfg = { .arena_config_ = arena_cfg,
|
||||
.n_generation_ = 2,
|
||||
.gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0}} };
|
||||
|
||||
DX1Collector gc = DX1Collector{cfg};
|
||||
|
||||
|
|
@ -94,12 +94,12 @@ namespace xo {
|
|||
0 /*tseq_bits*/,
|
||||
0 /*age_bits*/,
|
||||
16 /*size_bits*/), };
|
||||
CollectorConfig cfg = { .arena_config_ = arena_cfg,
|
||||
.n_generation_ = 2,
|
||||
.gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0}} };
|
||||
X1CollectorConfig cfg = { .arena_config_ = arena_cfg,
|
||||
.n_generation_ = 2,
|
||||
.gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0}} };
|
||||
|
||||
DX1Collector gc = DX1Collector{cfg};
|
||||
obj<AAllocator, DX1Collector> a1o{&gc};
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ add_definitions(${PROJECT_CXX_FLAGS})
|
|||
# output targets
|
||||
|
||||
add_subdirectory(src/interpreter2)
|
||||
#add_subdirectory(utest)
|
||||
add_subdirectory(utest)
|
||||
|
||||
xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets)
|
||||
|
||||
|
|
|
|||
|
|
@ -5,9 +5,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "VsmConfig.hpp"
|
||||
#include "VsmInstr.hpp"
|
||||
#include <xo/reader2/SchematikaReader.hpp>
|
||||
#include <xo/expression2/Expression.hpp>
|
||||
#include <xo/gc/GCObject.hpp>
|
||||
#include <xo/facet/box.hpp>
|
||||
|
||||
namespace xo {
|
||||
namespace scm {
|
||||
|
|
@ -18,10 +21,11 @@ namespace xo {
|
|||
public:
|
||||
// will be DArenaVector<obj<StackFrame>> probably
|
||||
using Stack = void *;
|
||||
using AAllocator = xo::mm::AAllocator;
|
||||
using AGCObject = xo::mm::AGCObject;
|
||||
|
||||
public:
|
||||
VirtualSchematikaMachine();
|
||||
VirtualSchematikaMachine(const VsmConfig & config);
|
||||
|
||||
/** borrow calling thread to run indefinitely,
|
||||
* until halt instruction
|
||||
|
|
@ -93,6 +97,14 @@ namespace xo {
|
|||
* value_
|
||||
*/
|
||||
|
||||
/** configuration **/
|
||||
VsmConfig config_;
|
||||
|
||||
box<AAllocator> mm_;
|
||||
|
||||
/** reader: text -> expression **/
|
||||
SchematikaReader reader_;
|
||||
|
||||
/** program counter **/
|
||||
VsmInstr pc_ = VsmInstr::halt();
|
||||
|
||||
|
|
|
|||
28
xo-interpreter2/include/xo/interpreter2/VsmConfig.hpp
Normal file
28
xo-interpreter2/include/xo/interpreter2/VsmConfig.hpp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/** @file VsmConfig.hpp
|
||||
*
|
||||
* @author Roland Conybeare, Jan 2026
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <xo/reader2/ReaderConfig.hpp>
|
||||
#include <xo/gc/X1CollectorConfig.hpp>
|
||||
|
||||
namespace xo {
|
||||
namespace scm {
|
||||
/** Configuration for virtual schematika machine
|
||||
**/
|
||||
struct VsmConfig {
|
||||
using X1CollectorConfig = xo::mm::X1CollectorConfig;
|
||||
|
||||
/** reader configuration **/
|
||||
ReaderConfig rdr_config_;
|
||||
/** Configuration for allocator/collector.
|
||||
* TODO: may want to make CollectorConfig polymorphic
|
||||
**/
|
||||
X1CollectorConfig x1_config_ = X1CollectorConfig().with_size(4*1024*1024);
|
||||
};
|
||||
} /*namespace scm*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end VsmConfig.hpp */
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/** @file init_interpreter2.hpp
|
||||
*
|
||||
* @author Roland Conybeare, Jan 2026
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <xo/subsys/Subsystem.hpp>
|
||||
|
||||
namespace xo {
|
||||
/* tag to represent the xo-interpreter2/ subsystem within ordered initialization */
|
||||
enum S_interpreter2_tag {};
|
||||
|
||||
template <>
|
||||
struct InitSubsys<S_interpreter2_tag> {
|
||||
static void init();
|
||||
static InitEvidence require();
|
||||
};
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end init_interpreter2.hpp */
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
set(SELF_LIB xo_interpreter2)
|
||||
set(SELF_SRCS
|
||||
init_interpreter2.cpp
|
||||
VirtualSchematikaMachine.cpp
|
||||
#IExpression_Any.cpp
|
||||
#interpreter2_register_facets.cpp
|
||||
|
|
@ -9,7 +10,7 @@ set(SELF_SRCS
|
|||
|
||||
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
|
||||
# note: deps here must also appear in cmake/xo_interpreter2Config.cmake.in
|
||||
xo_dependency(${SELF_LIB} xo_expression2)
|
||||
xo_dependency(${SELF_LIB} xo_reader2)
|
||||
xo_dependency(${SELF_LIB} xo_gc)
|
||||
#xo_dependency(${SELF_LIB} reflect)
|
||||
#xo_dependency(${SELF_LIB} xo_printable2)
|
||||
|
|
|
|||
|
|
@ -6,12 +6,19 @@
|
|||
#include "VirtualSchematikaMachine.hpp"
|
||||
#include <xo/expression2/detail/IExpression_DConstant.hpp>
|
||||
#include <xo/expression2/DConstant.hpp>
|
||||
#include <xo/gc/DX1Collector.hpp>
|
||||
#include <xo/gc/detail/IAllocator_DX1Collector.hpp>
|
||||
#include <cassert>
|
||||
|
||||
namespace xo {
|
||||
using xo::mm::DX1Collector;
|
||||
|
||||
namespace scm {
|
||||
|
||||
VirtualSchematikaMachine::VirtualSchematikaMachine()
|
||||
VirtualSchematikaMachine::VirtualSchematikaMachine(const VsmConfig & config)
|
||||
: config_{config},
|
||||
mm_(box<AAllocator,DX1Collector>(new DX1Collector(config.x1_config_))),
|
||||
reader_{config.rdr_config_, mm_.to_op()}
|
||||
{}
|
||||
|
||||
void
|
||||
|
|
|
|||
50
xo-interpreter2/src/interpreter2/init_interpreter2.cpp
Normal file
50
xo-interpreter2/src/interpreter2/init_interpreter2.cpp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/** @file init_interpreter2.cpp
|
||||
*
|
||||
* @author Roland Conybeare, Jan 2026
|
||||
**/
|
||||
|
||||
#include "init_interpreter2.hpp"
|
||||
|
||||
#ifdef NOT_YET
|
||||
#include "interpreter2_register_facets.hpp"
|
||||
#include "interpreter2_register_types.hpp"
|
||||
#endif
|
||||
|
||||
#include <xo/reader2/init_reader2.hpp>
|
||||
#ifdef NOT_YET
|
||||
#include <xo/gc/CollectorTypeRegistry.hpp>
|
||||
#endif
|
||||
|
||||
namespace xo {
|
||||
#ifdef NOT_YET
|
||||
using xo::scm::interpreter2_register_facets;
|
||||
using xo::scm::interpreter2_register_types;
|
||||
using xo::mm::CollectorTypeRegistry;
|
||||
#endif
|
||||
|
||||
void
|
||||
InitSubsys<S_interpreter2_tag>::init()
|
||||
{
|
||||
#ifdef NOT_YET
|
||||
interpreter2_register_facets();
|
||||
|
||||
CollectorTypeRegistry::instance().register_types(&interpreter2_register_types);
|
||||
#endif
|
||||
}
|
||||
|
||||
InitEvidence
|
||||
InitSubsys<S_interpreter2_tag>::require()
|
||||
{
|
||||
InitEvidence retval;
|
||||
|
||||
/* direct subsystem deps for xo-interpreter2/ */
|
||||
retval ^= InitSubsys<S_reader2_tag>::require();
|
||||
|
||||
/* xo-interpreter2/'s own initialization code */
|
||||
retval ^= Subsystem::provide<S_interpreter2_tag>("interpreter2", &init);
|
||||
|
||||
return retval;
|
||||
}
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end init_interpreter2.cpp */
|
||||
11
xo-interpreter2/utest/CMakeLists.txt
Normal file
11
xo-interpreter2/utest/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# build unittest xo-interpreter2/utest
|
||||
|
||||
set(UTEST_EXE utest.interpreter2)
|
||||
set(UTEST_SRCS
|
||||
interpreter2_utest_main.cpp
|
||||
VirtualSchematikaMachine.test.cpp
|
||||
)
|
||||
|
||||
xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS})
|
||||
xo_self_dependency(${UTEST_EXE} xo_interpreter2)
|
||||
xo_external_target_dependency(${UTEST_EXE} Catch2 Catch2::Catch2)
|
||||
63
xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp
Normal file
63
xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/** @file VirtualSchematikaMachine.test.cpp
|
||||
*
|
||||
* @author Roland Conybeare, Jan 2026
|
||||
**/
|
||||
|
||||
#include <xo/interpreter2/VirtualSchematikaMachine.hpp>
|
||||
|
||||
#ifdef NOT_YET
|
||||
#include <xo/reader2/SchematikaParser.hpp>
|
||||
#include <xo/reader2/DDefineSsm.hpp>
|
||||
#include <xo/reader2/DExpectExprSsm.hpp>
|
||||
#include <xo/reader2/ssm/ISyntaxStateMachine_DExpectExprSsm.hpp>
|
||||
#include <xo/reader2/ssm/ISyntaxStateMachine_DDefineSsm.hpp>
|
||||
#endif
|
||||
#include <xo/interpreter2/init_interpreter2.hpp>
|
||||
#ifdef NOT_YET
|
||||
#include <xo/alloc2/arena/IAllocator_DArena.hpp>
|
||||
#endif
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
namespace xo {
|
||||
#ifdef NOT_YET
|
||||
using xo::scm::SchematikaParser;
|
||||
using xo::scm::ASyntaxStateMachine;
|
||||
using xo::scm::syntaxstatetype;
|
||||
// using xo::scm::DDefineSsm;
|
||||
using xo::scm::DExpectExprSsm;
|
||||
// using xo::scm::defexprstatetype;
|
||||
//using xo::scm::ParserResult;
|
||||
//using xo::scm::parser_result_type;
|
||||
using xo::scm::Token;
|
||||
using xo::scm::DString;
|
||||
using xo::mm::ArenaConfig;
|
||||
using xo::mm::AAllocator;
|
||||
using xo::mm::DArena;
|
||||
using xo::facet::with_facet;
|
||||
#endif
|
||||
|
||||
static InitEvidence s_init = (InitSubsys<S_interpreter2_tag>::require());
|
||||
|
||||
namespace ut {
|
||||
TEST_CASE("VirtualSchematikaMachine-ctor", "[interpreter2][VSM]")
|
||||
{
|
||||
#ifdef NOT_YET
|
||||
ArenaConfig config;
|
||||
config.name_ = "test-arena";
|
||||
config.size_ = 16 * 1024;
|
||||
|
||||
DArena expr_arena = DArena::map(config);
|
||||
obj<AAllocator> expr_alloc = with_facet<AAllocator>::mkobj(&expr_arena);
|
||||
|
||||
SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/);
|
||||
|
||||
REQUIRE(parser.debug_flag() == false);
|
||||
REQUIRE(parser.is_at_toplevel() == true);
|
||||
#endif
|
||||
}
|
||||
|
||||
} /*namespace ut*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end SchematikaParser.test.cpp */
|
||||
27
xo-interpreter2/utest/interpreter2_utest_main.cpp
Normal file
27
xo-interpreter2/utest/interpreter2_utest_main.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/** @file interpreter2_utest_main.cpp
|
||||
*
|
||||
* @author Roland Conybeare, Jan 2026
|
||||
**/
|
||||
|
||||
#include <xo/subsys/Subsystem.hpp>
|
||||
|
||||
#define CATCH_CONFIG_RUNNER
|
||||
#include "catch2/catch.hpp"
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
using xo::Subsystem;
|
||||
|
||||
// initialize subsystems
|
||||
Subsystem::initialize_all();
|
||||
|
||||
// Run Catch2's test session
|
||||
int result = Catch::Session().run(argc, argv);
|
||||
|
||||
// cleanup here, if any
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* end interpreter2_utest_main.cpp */
|
||||
|
|
@ -44,7 +44,7 @@ namespace ut {
|
|||
using xo::mm::ACollector;
|
||||
using xo::mm::AGCObject;
|
||||
using xo::mm::DX1Collector;
|
||||
using xo::mm::CollectorConfig;
|
||||
using xo::mm::X1CollectorConfig;
|
||||
using xo::mm::ArenaConfig;
|
||||
using xo::print::APrintable;
|
||||
using xo::facet::FacetRegistry;
|
||||
|
|
@ -99,15 +99,14 @@ namespace ut {
|
|||
try {
|
||||
const testcase_pp & tc = s_testcase_v[i_tc];
|
||||
|
||||
CollectorConfig cfg{
|
||||
.name_ = "pp_test",
|
||||
.arena_config_ = ArenaConfig{
|
||||
.size_ = tc.gc_gen_size_,
|
||||
.store_header_flag_ = true},
|
||||
.object_types_z_ = 16384,
|
||||
.gc_trigger_v_{{tc.gc_trigger_threshold_,
|
||||
tc.gc_trigger_threshold_}},
|
||||
.debug_flag_ = c_debug_flag
|
||||
X1CollectorConfig cfg{ .name_ = "pp_test",
|
||||
.arena_config_ = ArenaConfig{
|
||||
.size_ = tc.gc_gen_size_,
|
||||
.store_header_flag_ = true},
|
||||
.object_types_z_ = 16384,
|
||||
.gc_trigger_v_{{tc.gc_trigger_threshold_,
|
||||
tc.gc_trigger_threshold_}},
|
||||
.debug_flag_ = c_debug_flag
|
||||
};
|
||||
|
||||
DX1Collector gc(cfg);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ namespace ut {
|
|||
using xo::mm::AGCObject;
|
||||
using xo::mm::DX1Collector;
|
||||
using xo::mm::DArena;
|
||||
using xo::mm::CollectorConfig;
|
||||
using xo::mm::X1CollectorConfig;
|
||||
using xo::mm::ArenaConfig;
|
||||
using xo::mm::generation;
|
||||
using xo::mm::role;
|
||||
|
|
@ -108,16 +108,15 @@ namespace ut {
|
|||
try {
|
||||
const testcase_x1 & tc = s_testcase_v[i_tc];
|
||||
|
||||
CollectorConfig cfg{
|
||||
.name_ = "x1_test",
|
||||
.arena_config_ = ArenaConfig{
|
||||
.size_ = tc.tenured_z_,
|
||||
.store_header_flag_ = true},
|
||||
.object_types_z_ = 16384,
|
||||
.gc_trigger_v_{{
|
||||
tc.incr_gc_threshold_,
|
||||
tc.full_gc_threshold_}},
|
||||
.debug_flag_ = c_debug_flag,
|
||||
X1CollectorConfig cfg{ .name_ = "x1_test",
|
||||
.arena_config_ = ArenaConfig{
|
||||
.size_ = tc.tenured_z_,
|
||||
.store_header_flag_ = true},
|
||||
.object_types_z_ = 16384,
|
||||
.gc_trigger_v_{{
|
||||
tc.incr_gc_threshold_,
|
||||
tc.full_gc_threshold_}},
|
||||
.debug_flag_ = c_debug_flag,
|
||||
};
|
||||
|
||||
DX1Collector gc(cfg);
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ namespace {
|
|||
|
||||
struct AppConfig {
|
||||
using ReaderConfig = xo::scm::ReaderConfig;
|
||||
using CollectorConfig = xo::mm::CollectorConfig;
|
||||
using X1CollectorConfig = xo::mm::X1CollectorConfig;
|
||||
|
||||
AppConfig() {
|
||||
rdr_config_.reader_debug_flag_ = true;
|
||||
|
|
@ -146,17 +146,17 @@ struct AppConfig {
|
|||
|
||||
std::size_t max_history_size_ = 1000;
|
||||
std::string repl_history_fname_ = "repl_history.txt";;
|
||||
CollectorConfig x1_config_ = (CollectorConfig().with_size(4*1024*1024));
|
||||
ReaderConfig rdr_config_;
|
||||
X1CollectorConfig x1_config_ = (X1CollectorConfig().with_size(4*1024*1024));
|
||||
};
|
||||
|
||||
struct AppContext {
|
||||
using DX1Collector = xo::mm::DX1Collector;
|
||||
using CollectorConfig = xo::mm::CollectorConfig;
|
||||
using X1CollectorConfig = xo::mm::X1CollectorConfig;
|
||||
using Replxx = replxx::Replxx;
|
||||
|
||||
AppContext(const AppConfig & cfg = AppConfig()) : config_{cfg},
|
||||
x1_{CollectorConfig().with_size(4*1024*1024)},
|
||||
x1_{X1CollectorConfig().with_size(4*1024*1024)},
|
||||
rdr_{config_.rdr_config_, x1_.ref()}
|
||||
{
|
||||
rx_.set_max_history_size(config_.max_history_size_);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue