16 template <
typename T = std::
byte> T *alloc(
size_t n = 1) {
17 return static_cast<T *
>(
ffi_guard{::MemoryContextAlloc}(_memory_context(),
sizeof(T) * n));
19 template <
typename T =
void>
void free(T *ptr) {
ffi_guard{::pfree}(ptr); }
21 void reset() {
ffi_guard{::MemoryContextReset}(_memory_context()); }
26 operator ::MemoryContext() {
return _memory_context(); }
28 ::MemoryContextCallback *register_reset_callback(::MemoryContextCallbackFunction func,
30 auto cb = alloc<::MemoryContextCallback>(
sizeof(::MemoryContextCallback));
33 ffi_guard{::MemoryContextRegisterResetCallback}(_memory_context(), cb);
37 void delete_context() {
ffi_guard{::MemoryContextDelete}(_memory_context()); }
40 virtual ::MemoryContext _memory_context() = 0;
55 ::MemoryContext context;
58 ::MemoryContext _memory_context()
override {
return context; }
66 explicit memory_context(::MemoryContext context) : context(context) {}
72 if (ptr ==
nullptr || ptr != (
void *)MAXALIGN(ptr)) {
73 throw std::runtime_error(
"invalid pointer");
78 template <
typename C>
requires std::derived_from<C, abstract_memory_context>
82 ::MemoryContext context;
84 ::MemoryContext _memory_context()
override {
return context; }
91 ::MemoryContext _memory_context()
override { return ::CurrentMemoryContext; }
95 using owned_memory_context::owned_memory_context;
98 ::CurrentMemoryContext,
nullptr, ALLOCSET_DEFAULT_SIZES)) {}
101 ffi_guard{::AllocSetContextCreateInternal}(ctx,
nullptr, ALLOCSET_DEFAULT_SIZES)) {}
105 ffi_guard{::AllocSetContextCreateInternal}(ctx,
nullptr, ALLOCSET_DEFAULT_SIZES)) {}
110template <
typename C>
requires std::derived_from<C, abstract_memory_context>
113 : ctx(context.ctx), counter(context.counter), cb(context.cb) {
118 : ctx(ctx), counter(0),
119 cb(std::shared_ptr<::MemoryContextCallback>(
120 this->register_reset_callback(
127 : ctx(std::move(other.ctx)), counter(std::move(other.counter)), cb(std::move(other.cb)) {
133 : ctx(std::move(other.ctx)), counter(std::move(other.counter)), cb(std::move(other.cb)) {
141 counter = other.counter;
148 if (cb.use_count() == 1) {
149 cb->func = [](
void *) {};
154 uint64_t resets()
const {
return counter; }
155 C &get_memory_context() {
return ctx; }
158 template <
typename T>
requires std::integral<T>
159 struct shared_counter {
161 constexpr explicit shared_counter(T init = 0) noexcept :
value(init) {}
163 shared_counter &operator=(T v)
noexcept {
168 shared_counter &operator++()
noexcept {
173 T operator++(
int)
noexcept {
179 constexpr operator T()
const noexcept {
return value; }
182 shared_counter<uint64_t> counter;
183 std::shared_ptr<::MemoryContextCallback> cb;
186 ::MemoryContext _memory_context()
override {
return ctx._memory_context(); }
191 std::derived_from<T, abstract_memory_context> && std::default_initializable<T>;
195 : previous(::CurrentMemoryContext), ctx(ctx.operator ::MemoryContext()) {
196 ::CurrentMemoryContext = ctx;
199 : previous(::CurrentMemoryContext), ctx(ctx.operator ::MemoryContext()) {
200 ::CurrentMemoryContext = ctx;
206 ::MemoryContext previous;
211 using value_type = T;
214 : context(std::move(ctx)), explicit_deallocation(explicit_deallocation) {}
217 : context(c.context) {}
219 [[nodiscard]] T *allocate(std::size_t n) {
221 return context.template alloc<T>(n);
223 throw std::bad_alloc();
227 void deallocate(T *p, std::size_t n)
noexcept {
228 if (explicit_deallocation || context == top_memory_context()) {
240 bool explicit_deallocation;
244 const char *what()
const noexcept override {
245 return "pointer belongs to a MemoryContext that has been reset or deleted";
Definition: exception.hpp:7
Definition: memory.hpp:190
Definition: memory.hpp:14
Definition: memory.hpp:94
Definition: memory.hpp:87
Definition: memory.hpp:210
Definition: memory.hpp:193
Definition: memory.hpp:61
Definition: memory.hpp:43
Definition: memory.hpp:243
Definition: memory.hpp:111