16 template <
typename T = std::
byte> T *alloc(
size_t n = 1) {
17 return static_cast<T *
>(ffi_guarded(::MemoryContextAlloc)(_memory_context(),
sizeof(T) * n));
19 template <
typename T =
void>
void free(T *ptr) { ffi_guarded(::pfree)(ptr); }
21 void reset() { ffi_guarded(::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_guarded(::MemoryContextRegisterResetCallback)(_memory_context(), cb);
37 void delete_context() { ffi_guarded(::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_guarded(::AllocSetContextCreateInternal)(ctx,
nullptr, ALLOCSET_DEFAULT_SIZES)) {}
106template <
typename C>
requires std::derived_from<C, abstract_memory_context>
109 : ctx(context.ctx), counter(context.counter), cb(context.cb) {
114 : ctx(ctx), counter(0),
115 cb(std::shared_ptr<::MemoryContextCallback>(
116 this->register_reset_callback(
123 : ctx(std::move(other.ctx)), counter(std::move(other.counter)), cb(std::move(other.cb)) {
129 : ctx(std::move(other.ctx)), counter(std::move(other.counter)), cb(std::move(other.cb)) {
137 counter = other.counter;
144 if (cb.use_count() == 1) {
145 cb->func = [](
void *) {};
150 uint64_t resets()
const {
return counter; }
151 C &get_memory_context() {
return ctx; }
154 template <
typename T>
requires std::integral<T>
155 struct shared_counter {
157 constexpr explicit shared_counter(T init = 0) noexcept : value(init) {}
159 shared_counter &operator=(T v)
noexcept {
164 shared_counter &operator++()
noexcept {
169 T operator++(
int)
noexcept {
175 constexpr operator T()
const noexcept {
return value; }
178 shared_counter<uint64_t> counter;
179 std::shared_ptr<::MemoryContextCallback> cb;
182 ::MemoryContext _memory_context()
override {
return ctx._memory_context(); }
187 std::derived_from<T, abstract_memory_context> && std::default_initializable<T>;
191 : previous(::CurrentMemoryContext), ctx(ctx.operator ::MemoryContext()) {
192 ::CurrentMemoryContext = ctx;
195 : previous(::CurrentMemoryContext), ctx(ctx.operator ::MemoryContext()) {
196 ::CurrentMemoryContext = ctx;
202 ::MemoryContext previous;
207 using value_type = T;
210 : context(std::move(ctx)), explicit_deallocation(explicit_deallocation) {}
213 : context(c.context) {}
215 [[nodiscard]] T *allocate(std::size_t n) {
217 return context.template alloc<T>(n);
219 throw std::bad_alloc();
223 void deallocate(T *p, std::size_t n)
noexcept {
224 if (explicit_deallocation || context == top_memory_context) {
236 bool explicit_deallocation;
240 const char *what()
const noexcept override {
241 return "pointer belongs to a MemoryContext that has been reset or deleted";
Definition: exception.hpp:7
Definition: memory.hpp:186
Definition: memory.hpp:14
Definition: memory.hpp:94
Definition: memory.hpp:87
Definition: memory.hpp:206
Definition: memory.hpp:189
Definition: memory.hpp:61
Definition: memory.hpp:43
Definition: memory.hpp:239
Definition: memory.hpp:107