Derive-C
Loading...
Searching...
No Matches
template.h
Go to the documentation of this file.
1
10
11#ifdef NDEBUG
13#else
14
16 #if !defined(SKIP_INCLUDES)
17 #include "includes.h"
18 #endif
19
22
23 #include <derive-c/alloc/std.h>
24
25 #define ALLOCATIONS_MAP NS(NAME, allocations)
26
27 #pragma push_macro("ALLOC")
28
29 // JUSTIFY: Always use the std allocator for test book keeping
30 // - keeps the observed behaviour (e.g. allocator usage) the same as in release
31 #define ALLOC stdalloc // [DERIVE-C] for template
32 #define KEY void* // [DERIVE-C] for template
33 #define KEY_HASH(ptr) ((size_t)(*(ptr))) // [DERIVE-C] for template
34 #define KEY_DEBUG dc_void_ptr_debug // [DERIVE-C] for template
35 #define VALUE size_t // [DERIVE-C] for template
36 #define INTERNAL_NAME ALLOCATIONS_MAP // [DERIVE-C] for template
38
39 #pragma pop_macro("ALLOC")
40
41typedef struct {
42 NS(ALLOC, ref) alloc_ref;
44} SELF;
45
46DC_PUBLIC static SELF NS(SELF, new)(NS(ALLOC, ref) alloc_ref) {
47 return (SELF){
48 .alloc_ref = alloc_ref,
49 .allocations = NS(ALLOCATIONS_MAP, new)(stdalloc_get_ref()),
50 };
51}
52
53DC_PUBLIC static ALLOCATIONS_MAP const* NS(SELF, get_allocations)(SELF const* self) {
54 DC_ASSUME(self);
55 return &self->allocations;
56}
57
58DC_PUBLIC static void NS(SELF, delete)(SELF* self) {
59 NS(ALLOCATIONS_MAP, delete)(&self->allocations);
60}
61
62DC_PUBLIC static void NS(SELF, unleak)(SELF* self) {
63 DC_FOR(ALLOCATIONS_MAP, &self->allocations, iter, entry) {
64 NS(ALLOC, deallocate)(self->alloc_ref, *entry.key, *entry.value);
65 }
66}
67
68DC_PUBLIC static void* NS(SELF, allocate_zeroed)(SELF* self, size_t size) {
69 DC_ASSUME(self);
70 void* ptr = NS(ALLOC, allocate_zeroed)(self->alloc_ref, size);
71 size_t* alloc = NS(ALLOCATIONS_MAP, try_insert)(&self->allocations, ptr, size);
72 DC_ASSERT(alloc != NULL,
73 "Got zeroed allocation, that is already allocated at %p (attempted size: %zu)", ptr,
74 size);
75 return ptr;
76}
77
78DC_PUBLIC static void* NS(SELF, allocate_uninit)(SELF* self, size_t size) {
79 DC_ASSUME(self);
80 void* ptr = NS(ALLOC, allocate_uninit)(self->alloc_ref, size);
81 size_t* alloc = NS(ALLOCATIONS_MAP, try_insert)(&self->allocations, ptr, size);
82 DC_ASSERT(alloc != NULL,
83 "Got uninit allocation, that is already allocated at %p (attempted size: %zu)", ptr,
84 *alloc);
85 return ptr;
86}
87
88DC_PUBLIC static void* NS(SELF, reallocate)(SELF* self, void* old_ptr, size_t old_size,
89 size_t new_size) {
90 DC_ASSUME(self);
91 DC_ASSUME(old_ptr);
92
93 size_t const* tracked_size = NS(ALLOCATIONS_MAP, try_read)(&self->allocations, old_ptr);
94 DC_ASSERT(tracked_size != NULL, "Reallocating pointer that is not allocated");
95 DC_ASSERT(*tracked_size == old_size,
96 "Incorrect size provided for reallocation of %p (was %zu, but expected %zu)", old_ptr,
97 old_size, *tracked_size);
98 NS(ALLOCATIONS_MAP, delete_entry)(&self->allocations, old_ptr);
99
100 void* new_ptr = NS(ALLOC, reallocate)(self->alloc_ref, old_ptr, old_size, new_size);
101
102 size_t* alloc = NS(ALLOCATIONS_MAP, try_insert)(&self->allocations, new_ptr, new_size);
103 DC_ASSERT(alloc != NULL,
104 "Got new reallocation, that is already allocated at %p (attempted size: %zu)",
105 new_ptr, new_size);
106
107 return new_ptr;
108}
109
110DC_PUBLIC static void NS(SELF, deallocate)(SELF* self, void* ptr, size_t size) {
111 DC_ASSUME(ptr);
112 DC_ASSUME(self);
113
114 size_t const* tracked_size = NS(ALLOCATIONS_MAP, try_read)(&self->allocations, ptr);
115 DC_ASSERT(tracked_size != NULL,
116 "Attempted to deallocate %p (size: %zu), but was not already allocated", ptr, size);
117 DC_ASSERT(*tracked_size == size,
118 "Incorrect size passed on %p deallocation (was: %zu, expected: %zu)", ptr,
119 *tracked_size, size);
120
121 NS(ALLOCATIONS_MAP, delete_entry)(&self->allocations, ptr);
122
123 NS(ALLOC, deallocate)(self->alloc_ref, ptr, size);
124}
125
126DC_PUBLIC static void NS(SELF, debug)(SELF const* self, dc_debug_fmt fmt, FILE* stream) {
127 fprintf(stream, DC_EXPAND_STRING(SELF) " @%p {\n", (void*)self);
128 fmt = dc_debug_fmt_scope_begin(fmt);
129 dc_debug_fmt_print(fmt, stream, "base: " DC_EXPAND_STRING(ALLOC) "@%p,\n",
130 (void*)NS(NS(ALLOC, ref), deref)(self->alloc_ref));
131
132 dc_debug_fmt_print(fmt, stream, "allocations: ");
133 NS(ALLOCATIONS_MAP, debug)(&self->allocations, fmt, stream);
134 fprintf(stream, "\n");
135
136 fmt = dc_debug_fmt_scope_end(fmt);
137 dc_debug_fmt_print(fmt, stream, "}");
138}
139
140 #undef ALLOCATIONS_MAP
141
143
145
149
150#endif
static DC_PUBLIC void deallocate(SELF *self, void *ptr, size_t size)
Definition template.h:127
static DC_PUBLIC void debug(SELF const *self, dc_debug_fmt fmt, FILE *stream)
Definition template.h:212
static DC_PUBLIC void * allocate_zeroed(SELF *self, size_t size)
Definition template.h:117
static DC_PUBLIC void * allocate_uninit(SELF *self, size_t size)
Definition template.h:92
static DC_PUBLIC void * reallocate(SELF *self, void *ptr, size_t old_size, size_t new_size)
Definition template.h:137
static DC_PUBLIC ALLOCATIONS_MAP const * get_allocations(SELF const *self)
Definition template.h:53
#define ALLOC
Definition template.h:31
#define ALLOCATIONS_MAP
For unit tests expected to throw, as C has no unwind, we cannot free allocated memory....
Definition template.h:25
static DC_PUBLIC void unleak(SELF *self)
Definition template.h:62
#define DC_TRAIT_ALLOC(SELF)
Definition trait.h:18
static DC_PUBLIC VALUE const * try_read(SELF const *self, INDEX index)
Definition template.h:180
static DC_PUBLIC size_t size(SELF const *self)
Definition template.h:252
static DC_PUBLIC void delete_entry(SELF *self, KEY key)
Definition template.h:504
static DC_PUBLIC VALUE * try_insert(SELF *self, KEY key, VALUE value)
Definition template.h:318
#define SELF
Definition def.h:52
static DC_PUBLIC void dc_debug_fmt_print(dc_debug_fmt fmt, FILE *stream, const char *format,...)
Definition fmt.h:32
static DC_PUBLIC dc_debug_fmt dc_debug_fmt_scope_end(dc_debug_fmt fmt)
Definition fmt.h:57
static DC_PUBLIC dc_debug_fmt dc_debug_fmt_scope_begin(dc_debug_fmt fmt)
Definition fmt.h:50
#define DC_FOR(TYPE, INSTANCE, ITER, ITEM)
Definition for.h:13
#define DC_PUBLIC
Definition namespace.h:25
#define NS(pre, post)
Definition namespace.h:14
#define DC_EXPAND_STRING(NAME)
Definition namespace.h:6
#define DC_ASSERT(expr,...)
Definition panic.h:37
#define DC_ASSUME(expr,...)
Definition panic.h:57
#define DC_TRAIT_REFERENCABLE_BY_PTR(SELF)
Definition ref.h:19
ALLOCATIONS_MAP allocations
Definition template.h:43
Debug format helpers for debug printin data structures.
Definition fmt.h:11
static DC_PUBLIC FILE * stream(SELF *self)
Definition template.h:108