Derive-C
Loading...
Searching...
No Matches
template.h File Reference
#include <stdint.h>
#include <string.h>
#include <derive-c/alloc/trait.h>
#include <derive-c/core/debug/gdb_marker.h>
#include <derive-c/core/debug/memory_tracker.h>
#include <derive-c/core/prelude.h>
#include <derive-c/core/self/def.h>
#include <derive-c/core/self/undef.h>
Include dependency graph for template.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

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

Macros

#define CAPACITY   1024
 A very simple bump allocator making use of a provided fixed size buffer (e.g. statically allocated).
#define USED   uint8_t

Typedefs

typedef char buffer[CAPACITY]

Functions

static SELF new (buffer *buffer)
static void clear (SELF *self)
 Clear the allocator, note that all data should be freed before this occurs.
static USED get_used (SELF const *self)
static void * malloc (SELF *self, size_t size)
static void free (SELF *self, void *ptr)
static void * realloc (SELF *self, void *ptr, size_t new_size)
static void * calloc (SELF *self, size_t count, size_t size)
 TRAIT_ALLOC (SELF)

Variables

static size_t metadata_size = sizeof(USED)

Macro Definition Documentation

◆ CAPACITY

#define CAPACITY   1024

A very simple bump allocator making use of a provided fixed size buffer (e.g. statically allocated).

  • Useful when an upper bound for allocation size is known at compile time
  • Can be used when no global allocator is available (e.g. embedded systems, kernel dev)

Definition at line 19 of file template.h.

◆ USED

#define USED   uint8_t

Definition at line 27 of file template.h.

Typedef Documentation

◆ buffer

typedef char buffer[CAPACITY]

Definition at line 36 of file template.h.

Function Documentation

◆ calloc()

void * calloc ( SELF * self,
size_t count,
size_t size )
static

Definition at line 189 of file template.h.

189 {
190 // JUSTIFY:
191 // - We already zeroed the buffer in `new()`
192 return NS(SELF, malloc)(self, count * size);
193}
static void * malloc(SELF *self, size_t size)
Definition template.h:25
static INDEX_TYPE size(SELF const *self)
Definition template.h:275
#define NS(pre, post)
Definition namespace.h:4
#define SELF
Definition def.h:52
Here is the call graph for this function:

◆ clear()

void clear ( SELF * self)
static

Clear the allocator, note that all data should be freed before this occurs.

Definition at line 65 of file template.h.

65 {
66 ASSUME(self);
67
68#if !defined NDEBUG
69 // JUSTIFY: Allocations & sizes zeroed on free in debug, we check all data has been freed.
71 self->used);
72 for (size_t i = 0; i < self->used; i++) {
73 if ((*self->buffer)[i] != 0) {
74 PANIC("Data not freed before clearing the static bump allocator");
75 }
76 }
77#endif
79 self->used);
80 memset((*self->buffer), 0, self->used);
82 CAPACITY);
83 self->used = 0;
84}
#define CAPACITY
A very simple bump allocator making use of a provided fixed size buffer (e.g. statically allocated).
Definition template.h:19
#define ASSUME(expr,...)
Definition macros.h:62
#define PANIC(...)
Definition macros.h:34
@ MEMORY_TRACKER_LVL_ALLOC
static void memory_tracker_set(memory_tracker_level level, memory_tracker_capability cap, const volatile void *addr, size_t size)
@ MEMORY_TRACKER_CAP_NONE
@ MEMORY_TRACKER_CAP_WRITE
@ MEMORY_TRACKER_CAP_READ_WRITE
size_t used
Definition template.h:39
buffer * buffer
Definition template.h:40
Here is the call graph for this function:
Here is the caller graph for this function:

◆ free()

void free ( SELF * self,
void * ptr )
static

Definition at line 110 of file template.h.

110 {
111 ASSUME(self);
112 ASSUME(ptr);
113
114#if !defined NDEBUG
115 // JUSTIFY: Zero memory in debug.
116 // - Expensive for release, but helpful when debugging
117 // NOTE: This means that users should free, before they clear and reuse the buffer.
118 USED* used_ptr = (USED*)((char*)ptr - sizeof(USED));
120 sizeof(USED));
121 memset(ptr, 0, *used_ptr);
123 *used_ptr = 0;
125#endif
126}
#define USED
Definition template.h:27
Here is the call graph for this function:

◆ get_used()

USED get_used ( SELF const * self)
static

Definition at line 86 of file template.h.

86 {
87 ASSUME(self);
88 return self->used;
89}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ malloc()

void * malloc ( SELF * self,
size_t size )
static

Definition at line 91 of file template.h.

91 {
92 ASSUME(self);
93 if (self->used + (size + sizeof(USED)) > CAPACITY) {
94 return NULL;
95 }
96 char* ptr = &(*self->buffer)[self->used];
97 USED* used_ptr = (USED*)ptr;
98
100 *used_ptr = size;
101 char* allocation_ptr = ptr + sizeof(USED);
103
104 self->used += size + sizeof(USED);
106
107 return allocation_ptr;
108}
Here is the call graph for this function:

◆ new()

SELF new ( buffer * buffer)
static

Definition at line 46 of file template.h.

46 {
47 SELF self = {
48 .used = 0,
49 .buffer = buffer,
50 .derive_c_staticbumpalloc = {},
51 };
52 // JUSTIFY: Zeroed buffer
53 // - For easier debugging & view in gdb.
54 // - Additionally allows for calloc to be malloc.
55 memset(*self.buffer, 0, CAPACITY);
56
57 // JUSTIFY: no capabilities on init
58 // - Protect access by users outside of malloc/calloc
60
61 return self;
62}
char buffer[CAPACITY]
Definition template.h:36
Here is the call graph for this function:

◆ realloc()

void * realloc ( SELF * self,
void * ptr,
size_t new_size )
static

Definition at line 128 of file template.h.

128 {
129 ASSUME(self);
130
131 if (!ptr) {
132 return NS(SELF, malloc)(self, new_size);
133 }
134
135 char* byte_ptr = (char*)ptr;
136 USED* old_size = (USED*)(byte_ptr - sizeof(USED));
138 sizeof(USED));
139 const bool was_last_alloc = (byte_ptr + *old_size == &(*self->buffer)[self->used]);
140
141 if (was_last_alloc) {
142 if (new_size > *old_size) {
143 size_t increase = new_size - *old_size;
144 if (self->used + increase > CAPACITY) {
145 return NULL;
146 }
147 self->used += increase;
149 (char*)ptr + *old_size, increase);
150 } else if (new_size < *old_size) {
151 size_t decrease = *old_size - new_size;
152 self->used -= decrease;
153
154 // JUSTIFY: Zeroing the end of the old allocation
155 // - Future calls to calloc may reuse this memory
156 memset((char*)ptr + new_size, 0, decrease);
157
159 (char*)ptr + new_size, decrease);
160 }
161
162 *old_size = new_size;
164 sizeof(USED));
165 return ptr;
166 }
167
168 if (new_size < *old_size) {
169 // JUSTIFY: Shrinking an allocation
170 // - Can become a noop - as we cannot re-extend the allocation
171 // afterwards - no metadata for unused capacity not at end of buffer.
172 *old_size = new_size;
174 sizeof(USED));
175 return ptr;
176 }
177
178 void* new_buff = NS(SELF, malloc)(self, new_size);
179 if (!new_buff) {
180 return NULL;
181 }
182
183 memcpy(new_buff, ptr, *old_size);
184
185 NS(SELF, free)(self, ptr);
186 return new_buff;
187}
static void free(SELF *self, void *ptr)
Definition template.h:58
Here is the call graph for this function:

◆ TRAIT_ALLOC()

TRAIT_ALLOC ( SELF )

Variable Documentation

◆ metadata_size

size_t metadata_size = sizeof(USED)
static

Definition at line 44 of file template.h.