17 template <
typename T = std::
byte> T *alloc(
size_t n = 1) {
18 return static_cast<T *
>(
ffi_guard{::MemoryContextAlloc}(_memory_context(),
sizeof(T) * n));
20 template <
typename T =
void>
void free(T *ptr) {
ffi_guard{::pfree}(ptr); }
22 void reset() {
ffi_guard{::MemoryContextReset}(_memory_context()); }
25 return _memory_context() == c._memory_context();
28 return _memory_context() != c._memory_context();
31 operator ::MemoryContext() {
return _memory_context(); }
33 ::MemoryContextCallback *register_reset_callback(::MemoryContextCallbackFunction func,
35 auto cb = alloc<::MemoryContextCallback>();
38 ffi_guard{::MemoryContextRegisterResetCallback}(_memory_context(), cb);
42 void delete_context() {
ffi_guard{::MemoryContextDelete}(_memory_context()); }
50 virtual ::MemoryContext _memory_context() = 0;
52 template <
typename T>
requires requires(T t) { t(); }
55 : _ctx(::CurrentMemoryContext), _thunk(thunk) {
56 ::CurrentMemoryContext = ctx;
60 auto operator()() {
return _thunk(); }
76 : context(other.context), moved(other.moved) {
84 context = other.context;
97 ::MemoryContext context;
100 ::MemoryContext _memory_context()
override {
return context; }
108 explicit memory_context(::MemoryContext context) : context(context) {}
114 if (ptr ==
nullptr || ptr != (
void *)MAXALIGN(ptr)) {
115 throw std::runtime_error(
"invalid pointer");
120 template <
typename C>
requires std::derived_from<C, abstract_memory_context>
124 ::MemoryContext context;
126 ::MemoryContext _memory_context()
noexcept override {
return context; }
133 ::MemoryContext _memory_context()
override { return ::CurrentMemoryContext; }
137 using owned_memory_context::owned_memory_context;
140 ::CurrentMemoryContext,
nullptr, ALLOCSET_DEFAULT_SIZES)) {}
143 ffi_guard{::AllocSetContextCreateInternal}(ctx,
nullptr, ALLOCSET_DEFAULT_SIZES)) {}
147 ffi_guard{::AllocSetContextCreateInternal}(ctx,
nullptr, ALLOCSET_DEFAULT_SIZES)) {}
152template <
typename C>
requires std::derived_from<C, abstract_memory_context>
155 template <
typename T>
requires std::integral<T>
156 struct shared_counter {
158 constexpr explicit shared_counter(T init = 0) noexcept :
value(init) {}
160 shared_counter &operator=(T v)
noexcept {
165 shared_counter &operator++()
noexcept {
170 T operator++(
int)
noexcept {
176 constexpr operator T()
const noexcept {
return value; }
179 struct callback_state {
180 shared_counter<uint64_t> counter;
181 ::MemoryContextCallback *callback =
nullptr;
184 static void track_reset(
void *arg) {
185 auto *state =
static_cast<callback_state *
>(arg);
187 state->callback =
nullptr;
192 : ctx(other.ctx), state(other.state) {}
195 state->callback = this->register_reset_callback(track_reset, state.get());
199 : ctx(std::move(other.ctx)), state(std::move(other.state)) {}
202 if (
this != &other) {
210 if (
this != &other) {
211 ctx = std::move(other.ctx);
212 state = std::move(other.state);
218 if (state !=
nullptr && state.use_count() == 1 && state->callback !=
nullptr) {
219 state->callback->func = [](
void *) {};
220 state->callback->arg =
nullptr;
221 state->callback =
nullptr;
225 uint64_t resets()
const {
return state ==
nullptr ? 0 : state->counter; }
226 C &get_memory_context() {
return ctx; }
230 std::shared_ptr<callback_state> state;
233 ::MemoryContext _memory_context()
override {
return ctx._memory_context(); }
238 std::derived_from<T, abstract_memory_context> && std::default_initializable<T>;
242 : previous(::CurrentMemoryContext), ctx(ctx.operator ::MemoryContext()) {
243 ::CurrentMemoryContext = ctx;
246 : previous(::CurrentMemoryContext), ctx(ctx.operator ::MemoryContext()) {
247 ::CurrentMemoryContext = ctx;
253 ::MemoryContext previous;
258 using value_type = T;
261 : context(std::move(ctx)), explicit_deallocation(explicit_deallocation) {}
264 : context(c.context) {}
266 [[nodiscard]] T *allocate(std::size_t n) {
268 return context.template alloc<T>(n);
270 throw std::bad_alloc();
274 void deallocate(T *p, std::size_t n)
noexcept {
275 if (explicit_deallocation || context == top_memory_context()) {
287 bool explicit_deallocation;
291 const char *what()
const noexcept override {
292 return "pointer belongs to a MemoryContext that has been reset or deleted";
Definition: exception.hpp:7
Definition: memory.hpp:237
Definition: memory.hpp:53
Definition: memory.hpp:14
auto operator()(auto thunk)
Definition: memory.hpp:47
Definition: memory.hpp:136
Definition: memory.hpp:129
Definition: memory.hpp:257
Definition: memory.hpp:240
Definition: memory.hpp:103
Definition: memory.hpp:68
Definition: memory.hpp:290
Definition: memory.hpp:153