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 ALLOCATIONS_MAP   NS(NAME, allocations)
 For unit tests expected to throw, as C has no unwind, we cannot free allocated memory. This macro wraps the allocator in debug, to allow clearing leaks after an exception.
#define ALLOC   stdalloc
#define KEY   void*
#define KEY_HASH(ptr)
#define KEY_DEBUG   dc_void_ptr_debug
#define VALUE   size_t
#define INTERNAL_NAME   ALLOCATIONS_MAP

Functions

static DC_PUBLIC SELF new (ref alloc_ref)
static DC_PUBLIC ALLOCATIONS_MAP const * get_allocations (SELF const *self)
static DC_PUBLIC void delete (SELF *self)
static DC_PUBLIC void unleak (SELF *self)
static DC_PUBLIC void * allocate_zeroed (SELF *self, size_t size)
static DC_PUBLIC void * allocate_uninit (SELF *self, size_t size)
static DC_PUBLIC void * reallocate (SELF *self, void *old_ptr, size_t old_size, size_t new_size)
static DC_PUBLIC void deallocate (SELF *self, void *ptr, size_t size)
static DC_PUBLIC void debug (SELF const *self, dc_debug_fmt fmt, FILE *stream)
 DC_TRAIT_REFERENCABLE_BY_PTR (SELF)
 DC_TRAIT_ALLOC (SELF)

Macro Definition Documentation

◆ ALLOC

#define ALLOC   stdalloc

Definition at line 31 of file template.h.

◆ ALLOCATIONS_MAP

#define ALLOCATIONS_MAP   NS(NAME, allocations)

For unit tests expected to throw, as C has no unwind, we cannot free allocated memory. This macro wraps the allocator in debug, to allow clearing leaks after an exception.

In release, it is a no-op / pass through.

  • Not entirely zero cost, as the reference type is pointer size, even if the wrapped allocator's reference is not.

As this is entirely C, we do not get the niceties of a C++ RAII allocator guard shebang. However, this is usable inside unit tests written in C.

Definition at line 25 of file template.h.

◆ INTERNAL_NAME

#define INTERNAL_NAME   ALLOCATIONS_MAP

Definition at line 36 of file template.h.

◆ KEY

#define KEY   void*

Definition at line 32 of file template.h.

◆ KEY_DEBUG

#define KEY_DEBUG   dc_void_ptr_debug

Definition at line 34 of file template.h.

◆ KEY_HASH

#define KEY_HASH ( ptr)
Value:
((size_t)(*(ptr)))

Definition at line 33 of file template.h.

◆ VALUE

#define VALUE   size_t

Definition at line 35 of file template.h.

Function Documentation

◆ allocate_uninit()

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

Definition at line 78 of file template.h.

78 {
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}
static DC_PUBLIC void * allocate_uninit(SELF *self, size_t size)
Definition template.h:92
#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 size_t size(SELF const *self)
Definition template.h:252
static DC_PUBLIC VALUE * try_insert(SELF *self, KEY key, VALUE value)
Definition template.h:318
#define NS(pre, post)
Definition namespace.h:14
#define DC_ASSERT(expr,...)
Definition panic.h:37
#define DC_ASSUME(expr,...)
Definition panic.h:57
ref alloc_ref
Definition template.h:49
ALLOCATIONS_MAP allocations
Definition template.h:43

◆ allocate_zeroed()

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

Definition at line 68 of file template.h.

68 {
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}
static DC_PUBLIC void * allocate_zeroed(SELF *self, size_t size)
Definition template.h:117

◆ 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 110 of file template.h.

110 {
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
122
123 NS(ALLOC, deallocate)(self->alloc_ref, ptr, size);
124}
static DC_PUBLIC void deallocate(SELF *self, void *ptr, size_t size)
Definition template.h:127
static DC_PUBLIC VALUE const * try_read(SELF const *self, INDEX index)
Definition template.h:180
static DC_PUBLIC void delete_entry(SELF *self, KEY key)
Definition template.h:504

◆ debug()

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

Definition at line 126 of file template.h.

126 {
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}
static DC_PUBLIC void debug(SELF const *self, dc_debug_fmt fmt, FILE *stream)
Definition template.h:212
#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_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 58 of file template.h.

58 {
59 NS(ALLOCATIONS_MAP, delete)(&self->allocations);
60}

◆ get_allocations()

DC_PUBLIC ALLOCATIONS_MAP const * get_allocations ( SELF const * self)
static

Definition at line 53 of file template.h.

53 {
54 DC_ASSUME(self);
55 return &self->allocations;
56}

◆ new()

DC_PUBLIC SELF new ( ref alloc_ref)
static

Definition at line 46 of file template.h.

46 {
47 return (SELF){
48 .alloc_ref = alloc_ref,
49 .allocations = NS(ALLOCATIONS_MAP, new)(stdalloc_get_ref()),
50 };
51}

◆ reallocate()

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

Definition at line 88 of file template.h.

89 {
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}
static DC_PUBLIC void * reallocate(SELF *self, void *ptr, size_t old_size, size_t new_size)
Definition template.h:137

◆ unleak()

DC_PUBLIC void unleak ( SELF * self)
static

Definition at line 62 of file template.h.

62 {
63 DC_FOR(ALLOCATIONS_MAP, &self->allocations, iter, entry) {
64 NS(ALLOC, deallocate)(self->alloc_ref, *entry.key, *entry.value);
65 }
66}
#define DC_FOR(TYPE, INSTANCE, ITER, ITEM)
Definition for.h:13