Derive-C
Loading...
Searching...
No Matches
template.h
Go to the documentation of this file.
1
8
10#if !defined(SKIP_INCLUDES)
11 #include "includes.h"
12#endif
13
16
17#ifdef NDEBUG
18typedef struct {
19 ALLOC* alloc;
20} SELF;
21
22static SELF NS(SELF, new)(ALLOC* alloc) { return (SELF){.alloc = alloc}; }
23
24static void* NS(SELF, malloc)(SELF* self, size_t size) {
25 return NS(ALLOC, malloc)(self->alloc, size);
26}
27
28static void* NS(SELF, calloc)(SELF* self, size_t count, size_t size) {
29 return NS(ALLOC, calloc)(self->alloc, count, size);
30}
31
32static void* NS(SELF, realloc)(SELF* self, void* ptr, size_t size) {
33 return NS(ALLOC, realloc)(self->alloc, ptr, size);
34}
35
36static void NS(SELF, free)(SELF* self, void* ptr) { NS(ALLOC, free)(self->alloc, ptr); }
37
38static void NS(SELF, debug)(SELF const* self, dc_debug_fmt fmt, FILE* stream) {
39 fprintf(stream, STRINGIFY(SELF) " @%p {", self);
40 fmt = dc_debug_fmt_scope_begin(fmt);
41 dc_debug_fmt_print(fmt, stream, "alloc: " STRINGIFY(ALLOC) "@%p,\n", self->alloc);
42 fmt = dc_debug_fmt_scope_end(fmt);
43 dc_debug_fmt_print(fmt, stream, "}");
44}
45
46#else
47 #include <derive-c/alloc/std.h>
48 #define ENTRIES_VECTOR NS(NAME, entries)
49 #define TRACKED_ENTRY NS(EXPAND(ENTRIES), entry)
50
51typedef struct {
52 void* ptr;
53 bool freed;
55
56 #pragma push_macro("ALLOC")
57
58 // JUSTIFY: Using a vector rather than a faster lookup map.
59 // - Give this will be used for test & debug, performance matters less
60 // - Much easier to explore a vector, than a hashmap in gdb.
61 // JUSTIFY: Always use the std allocator for test book keeping
62 // - keeps the observed behaviour (e.g. allocator usage) the same as in release
63 #define ITEM TRACKED_ENTRY // [DERIVE-C] for template
64 #define ALLOC stdalloc // [DERIVE-C] for template
65 #define INTERNAL_NAME ENTRIES_VECTOR // [DERIVE-C] for template
67
68 #pragma pop_macro("ALLOC")
69
70typedef struct {
73} SELF;
74
75static SELF NS(SELF, new)(ALLOC* alloc) {
76 return (SELF){.alloc = alloc, .entries = NS(ENTRIES_VECTOR, new)(stdalloc_get())};
77}
78
79static ENTRIES_VECTOR const* NS(SELF, get_entries)(SELF const* self) {
80 DC_ASSUME(self);
81 return &self->entries;
82}
83
84static void NS(SELF, unleak_and_delete)(SELF* self) {
85 NS(ENTRIES_VECTOR, iter) iter = NS(ENTRIES_VECTOR, get_iter)(&self->entries);
86 TRACKED_ENTRY* entry;
87
88 while ((entry = NS(ENTRIES_VECTOR, iter_next)(&iter))) {
89 if (!entry->freed) {
90 NS(ALLOC, free)(self->alloc, entry->ptr);
91 }
92 }
93
94 NS(ENTRIES_VECTOR, delete)(&self->entries);
95}
96
97static void* NS(SELF, calloc)(SELF* self, size_t count, size_t size) {
98 DC_ASSUME(self);
99 void* ptr = NS(ALLOC, calloc)(self->alloc, count, size);
100 if (ptr) {
101 NS(ENTRIES_VECTOR, push)(&self->entries, (TRACKED_ENTRY){
102 .ptr = ptr,
103 .freed = false,
104 });
105 }
106 return ptr;
107}
108
109static void* NS(SELF, malloc)(SELF* self, size_t size) {
110 DC_ASSUME(self);
111 void* ptr = NS(ALLOC, malloc)(self->alloc, size);
112 if (ptr) {
113 NS(ENTRIES_VECTOR, push)(&self->entries, (TRACKED_ENTRY){
114 .ptr = ptr,
115 .freed = false,
116 });
117 }
118 return ptr;
119}
120
121static void* NS(SELF, realloc)(SELF* self, void* ptr, size_t size) {
122 DC_ASSUME(self);
123 DC_ASSUME(ptr);
124 return NS(ALLOC, realloc)(self->alloc, ptr, size);
125}
126
127static void NS(SELF, free)(SELF* self, void* ptr) {
128 DC_ASSUME(ptr);
129 DC_ASSUME(self);
130
131 NS(ENTRIES_VECTOR, iter) iter = NS(ENTRIES_VECTOR, get_iter)(&self->entries);
132 TRACKED_ENTRY* entry;
133
134 while ((entry = NS(ENTRIES_VECTOR, iter_next)(&iter))) {
135 if (entry->ptr == ptr) {
136 DC_ASSUME(!entry->freed);
137 entry->freed = true;
138 break;
139 }
140 }
141
142 NS(ALLOC, free)(self->alloc, ptr);
143}
144
145static void NS(SELF, debug)(SELF const* self, dc_debug_fmt fmt, FILE* stream) {
146 fprintf(stream, STRINGIFY(SELF) " @%p {", self);
147 fmt = dc_debug_fmt_scope_begin(fmt);
148 dc_debug_fmt_print(fmt, stream, "base: " STRINGIFY(ALLOC) "@%p,\n", self->alloc);
149 NS(ENTRIES_VECTOR, debug)(&self->entries, fmt, stream);
150 fmt = dc_debug_fmt_scope_end(fmt);
151 dc_debug_fmt_print(fmt, stream, "}");
152}
153
154 #undef TRACKED_ENTRY
155 #undef ENTRIES_VECTOR
156#endif
157
159
static void debug(SELF const *self, dc_debug_fmt fmt, FILE *stream)
Definition template.h:62
static void free(SELF *self, void *ptr)
Definition template.h:56
static void * realloc(SELF *self, void *ptr, size_t size)
Definition template.h:45
static void * malloc(SELF *self, size_t size)
Definition template.h:23
static void * calloc(SELF *self, size_t count, size_t size)
Definition template.h:34
#define ALLOC
Definition template.h:64
#define TRACKED_ENTRY
Definition template.h:49
#define ENTRIES_VECTOR
For unit tests expected to throw, as C has no unwind, we cannot free allocated memory....
Definition template.h:48
static void unleak_and_delete(SELF *self)
Definition template.h:84
static ENTRIES_VECTOR const * get_entries(SELF const *self)
Definition template.h:79
#define DC_TRAIT_ALLOC(SELF)
Definition trait.h:5
static ITER get_iter(SELF *self)
Definition template.h:370
static INDEX_TYPE size(SELF const *self)
Definition template.h:252
static ITEM * push(SELF *self, ITEM item)
Definition template.h:216
dc_debug_fmt dc_debug_fmt_scope_end(dc_debug_fmt fmt)
Definition fmt.h:39
dc_debug_fmt dc_debug_fmt_scope_begin(dc_debug_fmt fmt)
Definition fmt.h:33
static void dc_debug_fmt_print(dc_debug_fmt fmt, FILE *stream, const char *format,...)
Definition fmt.h:22
#define STRINGIFY(MACRO)
Definition namespace.h:7
#define NS(pre, post)
Definition namespace.h:4
#define DC_ASSUME(expr,...)
Definition panic.h:56
#define SELF
Definition def.h:52
ENTRIES_VECTOR entries
Definition template.h:72
ALLOC * alloc
Definition template.h:71
bool freed
Definition template.h:53
void * ptr
Definition template.h:52
Debug format helpers for debug printin data structures.
Definition fmt.h:10
static FILE * stream(SELF *self)
Opens a file for.
Definition template.h:107