Derive-C
Loading...
Searching...
No Matches
template.h File Reference

Go to the source code of this file.

Data Structures

struct  SELF
 An allocator that prints to stdout when it allocates or frees memory. More...

Macros

#define CAPACITY   1024
 A hybrid of a bump allocator on a statically allocated buffer, and any other allocator.

Typedefs

typedef char buffer[CAPACITY]

Functions

 DC_STATIC_ASSERT (CAPACITY > 0, "Capacity must be larger than zero")
static DC_INTERNAL bool PRIV contains_ptr (SELF const *self, void *ptr)
static DC_PUBLIC SELF new (buffer *buffer, ref alloc_ref)
static DC_PUBLIC void *PRIV static_allocate_zeroed (SELF *self, size_t size)
static DC_PUBLIC void * allocate_zeroed (SELF *self, size_t size)
static DC_PUBLIC void *PRIV static_allocate_uninit (SELF *self, size_t size)
static DC_PUBLIC void * allocate_uninit (SELF *self, size_t size)
static DC_PUBLIC void PRIV static_deallocate (SELF *self, void *ptr, size_t size)
static DC_PUBLIC void deallocate (SELF *self, void *ptr, size_t size)
static DC_PUBLIC void *PRIV static_reallocate (SELF *self, void *ptr, size_t old_size, size_t new_size)
static DC_PUBLIC void * reallocate (SELF *self, void *ptr, size_t old_size, size_t new_size)
static DC_PUBLIC void debug (SELF const *self, dc_debug_fmt fmt, FILE *stream)
static DC_PUBLIC void reset (SELF *self)
static DC_PUBLIC void delete (SELF *self)
 DC_TRAIT_REFERENCABLE_BY_PTR (SELF)
 DC_TRAIT_ALLOC (SELF)

Macro Definition Documentation

◆ CAPACITY

#define CAPACITY   1024

A hybrid of a bump allocator on a statically allocated buffer, and any other allocator.

  • Useful for reducing allocation overhead when the expected number of allocations is known.
  • Once the static allocation is exhausted, it uses the fallback allocator.
  • Simplified: no size storage, no buffer zeroing, tracks only head and last allocation

Definition at line 18 of file template.h.

Typedef Documentation

◆ buffer

typedef char buffer[CAPACITY]

Definition at line 23 of file template.h.

Function Documentation

◆ allocate_uninit()

DC_PUBLIC void * allocate_uninit ( SELF * self,
size_t size )
static

Definition at line 112 of file template.h.

112 {
113 DC_ASSUME(self);
114 DC_ASSERT(size > 0, "Cannot allocate zero sized");
115
116 void* statically_allocated = PRIV(NS(SELF, static_allocate_uninit))(self, size);
117
118 if (statically_allocated == NULL) {
119 return NS(ALLOC, allocate_uninit)(self->alloc_ref, size);
120 }
121
122 return statically_allocated;
123}
static DC_PUBLIC void * allocate_uninit(SELF *self, size_t size)
Definition template.h:92
static DC_PUBLIC void *PRIV static_allocate_uninit(SELF *self, size_t size)
Definition template.h:92
#define ALLOC
Definition template.h:31
static DC_PUBLIC size_t size(SELF const *self)
Definition template.h:252
#define SELF
Definition def.h:52
#define NS(pre, post)
Definition namespace.h:14
#define PRIV(name)
Definition namespace.h:20
#define DC_ASSERT(expr,...)
Definition panic.h:37
#define DC_ASSUME(expr,...)
Definition panic.h:57
ref alloc_ref
Definition template.h:49

◆ allocate_zeroed()

DC_PUBLIC void * allocate_zeroed ( SELF * self,
size_t size )
static

Definition at line 84 of file template.h.

84 {
85 void* allocation_ptr = PRIV(NS(SELF, static_allocate_zeroed))(self, size);
86 if (allocation_ptr == NULL) {
87 return NS(ALLOC, allocate_zeroed)(self->alloc_ref, size);
88 }
89 return allocation_ptr;
90}
static DC_PUBLIC void * allocate_zeroed(SELF *self, size_t size)
Definition template.h:117
static DC_PUBLIC void *PRIV static_allocate_zeroed(SELF *self, size_t size)
Definition template.h:56

◆ contains_ptr()

DC_INTERNAL bool PRIV contains_ptr ( SELF const * self,
void * ptr )
static

Definition at line 33 of file template.h.

33 {
34 void* buffer_start = &(*self->buffer)[0];
35 void* buffer_end = &(*self->buffer)[CAPACITY];
36 return buffer_start <= ptr && ptr < buffer_end;
37}
#define CAPACITY
A hybrid of a bump allocator on a statically allocated buffer, and any other allocator.
Definition template.h:18

◆ DC_STATIC_ASSERT()

DC_STATIC_ASSERT ( CAPACITY ,
0 ,
"Capacity must be larger than zero"  )

◆ DC_TRAIT_ALLOC()

DC_TRAIT_ALLOC ( SELF )

◆ DC_TRAIT_REFERENCABLE_BY_PTR()

DC_TRAIT_REFERENCABLE_BY_PTR ( SELF )

◆ deallocate()

DC_PUBLIC void deallocate ( SELF * self,
void * ptr,
size_t size )
static

Definition at line 142 of file template.h.

142 {
143 DC_ASSUME(self);
144 DC_ASSUME(ptr);
145
146 if (PRIV(NS(SELF, contains_ptr))(self, ptr)) {
147 PRIV(NS(SELF, static_deallocate))(self, ptr, size);
148 } else {
149 NS(ALLOC, deallocate)(self->alloc_ref, ptr, size);
150 }
151}
static DC_PUBLIC void deallocate(SELF *self, void *ptr, size_t size)
Definition template.h:127
static DC_PUBLIC void PRIV static_deallocate(SELF *self, void *ptr, size_t size)
Definition template.h:125
static DC_INTERNAL bool PRIV contains_ptr(SELF const *self, void *ptr)
Definition template.h:33

◆ debug()

DC_PUBLIC void debug ( SELF const * self,
dc_debug_fmt fmt,
FILE * stream )
static

Definition at line 213 of file template.h.

213 {
214 DC_ASSUME(self);
215 fprintf(stream, DC_EXPAND_STRING(SELF) "@%p {\n", (void*)self);
216 fmt = dc_debug_fmt_scope_begin(fmt);
217 dc_debug_fmt_print(fmt, stream, "capacity: %zu,\n", (size_t)CAPACITY);
218 dc_debug_fmt_print(fmt, stream, "used: %zu,\n", (size_t)(self->head_ptr - &(*self->buffer)[0]));
219 dc_debug_fmt_print(fmt, stream, "buffer: %p,\n", (void*)self->buffer);
220 dc_debug_fmt_print(fmt, stream, "last_alloc: %p,\n", (void*)self->last_alloc_ptr);
221 dc_debug_fmt_print(fmt, stream, "alloc: ");
222 NS(ALLOC, debug)(NS(NS(ALLOC, ref), deref)(self->alloc_ref), fmt, stream);
223 fprintf(stream, "\n");
224 fmt = dc_debug_fmt_scope_end(fmt);
225 dc_debug_fmt_print(fmt, stream, "}");
226}
static DC_PUBLIC void debug(SELF const *self, dc_debug_fmt fmt, FILE *stream)
Definition template.h:212
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_EXPAND_STRING(NAME)
Definition namespace.h:6
static DC_PUBLIC FILE * stream(SELF *self)
Definition template.h:108

◆ delete()

DC_PUBLIC void delete ( SELF * self)
static

Definition at line 243 of file template.h.

243 {
245 &self->buffer[0], sizeof(NS(SELF, buffer)));
246 DC_ASSUME(self);
247}
char buffer[CAPACITY]
Definition template.h:23
static DC_PUBLIC void dc_memory_tracker_set(dc_memory_tracker_level level, dc_memory_tracker_capability cap, const volatile void *addr, size_t size)
@ DC_MEMORY_TRACKER_LVL_ALLOC
@ DC_MEMORY_TRACKER_CAP_WRITE
buffer * buffer
Definition template.h:26

◆ new()

DC_PUBLIC SELF new ( buffer * buffer,
ref alloc_ref )
static

Definition at line 39 of file template.h.

39 {
40 SELF self = {
41 .buffer = buffer,
42 .alloc_ref = alloc_ref,
43 .head_ptr = &(*buffer)[0],
44 .last_alloc_ptr = NULL,
45 .derive_c_hybridstaticalloc = {},
46 };
47
48 // JUSTIFY: no capabilities on init
49 // - Protect access by users outside of malloc/calloc
51 CAPACITY);
52
53 return self;
54}
@ DC_MEMORY_TRACKER_CAP_NONE

◆ reallocate()

DC_PUBLIC void * reallocate ( SELF * self,
void * ptr,
size_t old_size,
size_t new_size )
static

Definition at line 197 of file template.h.

198 {
199 DC_ASSUME(self);
200 DC_ASSERT(new_size > 0, "Cannot allocate zero sized");
201
202 if (!ptr) {
203 return NS(SELF, allocate_uninit)(self, new_size);
204 }
205
206 if (!PRIV(NS(SELF, contains_ptr))(self, ptr)) {
207 return NS(ALLOC, reallocate)(self->alloc_ref, ptr, old_size, new_size);
208 }
209
210 return PRIV(NS(SELF, static_reallocate))(self, ptr, old_size, new_size);
211}
static DC_PUBLIC void * reallocate(SELF *self, void *ptr, size_t old_size, size_t new_size)
Definition template.h:137
static DC_PUBLIC void *PRIV static_reallocate(SELF *self, void *ptr, size_t old_size, size_t new_size)
Definition template.h:153

◆ reset()

DC_PUBLIC void reset ( SELF * self)
static

Definition at line 228 of file template.h.

228 {
229 DC_ASSUME(self);
230
231 size_t used = (size_t)(self->head_ptr - &(*self->buffer)[0]);
232 if (used > 0) {
234 &(*self->buffer)[0], used);
235 }
236
237 self->head_ptr = &(*self->buffer)[0];
238 self->last_alloc_ptr = NULL;
239}
char * last_alloc_ptr
Definition template.h:29
char * head_ptr
Definition template.h:28

◆ static_allocate_uninit()

DC_PUBLIC void *PRIV static_allocate_uninit ( SELF * self,
size_t size )
static

Definition at line 92 of file template.h.

92 {
93 DC_ASSUME(self);
94 DC_ASSERT(size > 0);
95
96 char* buffer_end = &(*self->buffer)[CAPACITY];
97 if (self->head_ptr + size > buffer_end) {
98 return NULL;
99 }
100
101 char* allocation_ptr = self->head_ptr;
102
103 self->last_alloc_ptr = allocation_ptr;
104 self->head_ptr += size;
105
107 size);
108
109 return allocation_ptr;
110}

◆ static_allocate_zeroed()

DC_PUBLIC void *PRIV static_allocate_zeroed ( SELF * self,
size_t size )
static

Definition at line 56 of file template.h.

56 {
57 DC_ASSUME(self);
58 DC_ASSERT(size > 0);
59
60 char* buffer_end = &(*self->buffer)[CAPACITY];
61 if (self->head_ptr + size > buffer_end) {
62 return NULL;
63 }
64
65 char* allocation_ptr = self->head_ptr;
66
67 // Set permissions before zeroing (buffer might be poisoned)
69 size);
70
71 // Zero the allocation
72 memset(allocation_ptr, 0, size);
73
74 self->last_alloc_ptr = allocation_ptr;
75 self->head_ptr += size;
76
77 // Now set to read-write
79 allocation_ptr, size);
80
81 return allocation_ptr;
82}
@ DC_MEMORY_TRACKER_CAP_READ_WRITE

◆ static_deallocate()

DC_PUBLIC void PRIV static_deallocate ( SELF * self,
void * ptr,
size_t size )
static

Definition at line 125 of file template.h.

125 {
126 DC_ASSUME(self);
127 DC_ASSUME(ptr);
128
129 char* byte_ptr = (char*)ptr;
130
131 // If this is the last allocation, we can reclaim the space
132 if (byte_ptr == self->last_alloc_ptr) {
134 self->head_ptr = byte_ptr;
135 self->last_alloc_ptr = NULL;
136 } else {
137 // Not the last allocation, just mark as inaccessible
139 }
140}

◆ static_reallocate()

DC_PUBLIC void *PRIV static_reallocate ( SELF * self,
void * ptr,
size_t old_size,
size_t new_size )
static

Definition at line 153 of file template.h.

154 {
155 char* byte_ptr = (char*)ptr;
156
157 if (new_size == old_size) {
158 return ptr;
159 }
160
161 // If this is the last allocation, we can grow/shrink in place
162 if (byte_ptr == self->last_alloc_ptr) {
163 char* buffer_end = &(*self->buffer)[CAPACITY];
164
165 if (new_size > old_size) {
166 // Growing
167 size_t increase = new_size - old_size;
168 if (self->head_ptr + increase <= buffer_end) {
170 self->head_ptr, increase);
171 self->head_ptr += increase;
172 return ptr;
173 }
174 } else {
175 // Shrinking
176 size_t decrease = old_size - new_size;
178 byte_ptr + new_size, decrease);
179 self->head_ptr -= decrease;
180 return ptr;
181 }
182 } else if (new_size < old_size) {
183 // Not the last allocation, but shrinking - just mark extra space as inaccessible
185 byte_ptr + new_size, old_size - new_size);
186 return ptr;
187 }
188
189 // Need to allocate new buffer and copy
190 void* new_buff = NS(SELF, allocate_uninit)(self, new_size);
191 memcpy(new_buff, ptr, old_size < new_size ? old_size : new_size);
192
193 PRIV(NS(SELF, static_deallocate))(self, ptr, old_size);
194 return new_buff;
195}