libGimbal 0.1.0
C17-Based Extended Standard Library and Cross-Language Runtime Framework
Loading...
Searching...
No Matches
gimbal_arena_allocator.h
Go to the documentation of this file.
1/*! \file
2 * \brief GblArenaAllocator zone/region/area-based allocator + API
3 * \ingroup allocators
4 * \copydoc GblArenaAllocator
5 *
6 * \author Falco Girgis
7 */
8#ifndef GIMBAL_ARENA_ALLOCATOR_H
9#define GIMBAL_ARENA_ALLOCATOR_H
10
11#include "../containers/gimbal_linked_list.h"
12#include "../meta/instances/gimbal_object.h"
13#include "../meta/ifaces/gimbal_iallocator.h"
14#include "../core/gimbal_result.h"
15
16/*! \name Type System
17 * \brief Type UUID and cast operators
18 * @{
19 */
20#define GBL_ARENA_ALLOCATOR_TYPE (GBL_TYPEID(GblArenaAllocator)) //!< Type UUID for GblArenaAllocator
21#define GBL_ARENA_ALLOCATOR(self) (GBL_CAST(GblArenaAllocator, self)) //!< Cast a GblInstance to GblArenaAllocator
22#define GBL_ARENA_ALLOCATOR_CLASS(klass) (GBL_CLASS_CAST(GblArenaAllocator, klass)) //!< Cast a GblClass to GblArenaAllocatorClass
23#define GBL_ARENA_ALLOCATOR_GET_CLASS(self) (GBL_CLASSOF(GblArenaAllocator, self)) //!< Get a GblArenaAllocatorClass from a GblInstance
24//! @}
25
26#define GBL_SELF_TYPE GblArenaAllocator
27
29
31
32/*! \brief Represents a single arena allocation page
33 *
34 * GblArenaAllocatorPage is the meta data header and
35 * memory payload buffer for a preset number of bytes
36 * which can be allocated from a GblArenaAllocator
37 * \ingroup allocators
38 * \sa GblArenaAllocator
39 */
40typedef struct GblArenaAllocatorPage {
41 union {
42 struct GblArenaAllocatorPage* pNext; ///< Next (used) allocator page
43 GblLinkedListNode listNode; ///< Linked list node base
44 };
45 size_t capacity; ///< Page capacity
46 size_t used; ///< Number of bytes filled on page
47 union {
48 GblBool staticAlloc; ///< Whether this page is static or heap allocated
49 size_t padding;
50 };
51 unsigned char bytes[1]; ///< first byte of data segment
52} GblArenaAllocatorPage;
53
54/*! \struct GblArenaAllocatorClass
55 * \extends GblObjectClass
56 * \implements GblIAllocatorClass
57 * \brief GblClass structure for GblArenaAllocator
58 *
59 * No public methods.
60 *
61 * \sa GblArenaAllocator
62 */
63GBL_CLASS_DERIVE_EMPTY(GblArenaAllocator, GblObject, GblIAllocator);
64
65/*! \struct GblArenaAllocator
66 * \extends GblObject
67 * \implements GblIAllocator
68 * \ingroup dataTypes
69 * \brief Arena/zone/region/area-based paged allocator
70 *
71 * GblArenaAllocator is a custom allocator which is useful
72 * for when you are allocating a bunch of data dynamically
73 * which all has the same shared lifetime. The allocator is
74 * created once, then as allocations are requested, it
75 * only allocates new memory in per-page incremements rather
76 * than for individual allocations. Finally, when you're
77 * done, rather than calling delete, you simply destruct
78 * the allocator, which frees its pages all at once. This
79 * can be SUBSTANTIALLY faster than calling malloc() or
80 * new for backing data structures with such allocation
81 * patterns.
82 *
83 * \note
84 * It's often useful to create the first allocation page
85 * as a static buffer somewhere in a source file, so that
86 * heap memory isn't even used until it's necessary. Be sure
87 * to set the GblArenaAllocatorPage::staticAlloc flag to
88 * ensure the allocator does not attempt to free it!
89 *
90 * \sa GblArenaAllocatorPage, GblPoolAllocator
91 */
93 union {
94 GblArenaAllocatorPage* pActivePage; ///< Active (unfilled) page at list head
95 GblLinkedListNode listNode; ///< Linked list node base
96 };
97 GblContext* pCtx; ///< Custom context associated with allocator
98 size_t pageSize; ///< Default page size for all new pages
99 size_t pageAlign; ///< Alignment of each page, also maximum requestable alignment
100 size_t allocCount; ///< Total # of allocations across all pages
102
103/*! \brief Represents the current state of a GblArenaAllocator
104 *
105 * GblArenaAllocatorState is an auxiliary struct
106 * whose purpose is to capture the current page
107 * state associated with a given arena allocator,
108 * so that it may be use to "restore" the arena's
109 * state later.
110 *
111 * This is useful for wanting to make temporary
112 * use of an arena's resources, allowing you to
113 * free them when you're done.
114 *
115 * \sa GblArenaAllocator GblArenaAllocatorPage
116 */
118 GblArenaAllocatorPage* pActivePage;
119 size_t bytesUsed;
120} GblArenaAllocatorState;
121
122GBL_EXPORT GblType GblArenaAllocator_type (void) GBL_NOEXCEPT;
123
124// ===== Public methods =====
125GBL_EXPORT GBL_RESULT GblArenaAllocator_construct (GBL_SELF,
126 size_t pageSize,
127 size_t pageAlign,
128 GblArenaAllocatorPage* pInitialPage,
129 GblContext* pCtx) GBL_NOEXCEPT;
130
131GBL_EXPORT GBL_RESULT GblArenaAllocator_destruct (GBL_SELF) GBL_NOEXCEPT;
132
133GBL_EXPORT size_t GblArenaAllocator_pageCount (GBL_CSELF) GBL_NOEXCEPT;
134GBL_EXPORT size_t GblArenaAllocator_bytesUsed (GBL_CSELF) GBL_NOEXCEPT;
135GBL_EXPORT size_t GblArenaAllocator_bytesAvailable (GBL_CSELF) GBL_NOEXCEPT;
136
137GBL_EXPORT size_t GblArenaAllocator_totalCapacity (GBL_CSELF) GBL_NOEXCEPT;
138GBL_EXPORT size_t GblArenaAllocator_fragmentedBytes (GBL_CSELF) GBL_NOEXCEPT;
139GBL_EXPORT float GblArenaAllocator_utilization (GBL_CSELF) GBL_NOEXCEPT;
140
141GBL_EXPORT void GblArenaAllocator_saveState (GBL_CSELF, GblArenaAllocatorState* pState) GBL_NOEXCEPT;
142GBL_EXPORT GBL_RESULT GblArenaAllocator_loadState (GBL_SELF, const GblArenaAllocatorState* pState) GBL_NOEXCEPT;
143
144GBL_EXPORT void* GblArenaAllocator_alloc (GBL_SELF, size_t size, size_t alignment) GBL_NOEXCEPT;
145GBL_EXPORT GBL_RESULT GblArenaAllocator_freeAll (GBL_SELF) GBL_NOEXCEPT;
146
147// ===== Macro overloads =====
148#define GblArenaAllocator_construct(...) GblArenaAllocator_constructDefault_(__VA_ARGS__)
149#define GblArenaAllocator_alloc(...) GblArenaAllocator_allocDefault_(__VA_ARGS__)
150
151// ===== IMPL =====
152///\cond
153#define GblArenaAllocator_constructDefault_(...)
154 GblArenaAllocator_constructDefault__(__VA_ARGS__, 16, GBL_NULL, GBL_NULL)
155#define GblArenaAllocator_constructDefault__(self, size, align, initial, ctx, ...)
156 (GblArenaAllocator_construct)(self, size, align, initial, ctx)
157
158#define GblArenaAllocator_allocDefault_(...)
159 GblArenaAllocator_allocDefault__(__VA_ARGS__, 0)
160#define GblArenaAllocator_allocDefault__(self, size, align, ...)
161 (GblArenaAllocator_alloc)(self, size, align)
162///\endcond
164
165#undef GBL_SELF_TYPE
166
167#endif // GIMBAL_ARENA_ALLOCATOR_H
#define GblArenaAllocator_construct(...)
#define GblArenaAllocator_alloc(...)
#define GBL_CLASS_CAST(cType, klass)
#define GBL_NULL
#define GBL_NOEXCEPT
#define GBL_DECLS_BEGIN
#define GBL_FORWARD_DECLARE_STRUCT(S)
#define GBL_TYPEID(instanceStruct)
#define GBL_INSTANCE_DERIVE(derivedInstance, baseInstance)
#define GBL_INSTANCE_END
#define GBL_CLASS_DERIVE_EMPTY(...)
#define GBL_EXPORT
#define GBL_CLASSOF(cType, self)
#define GBL_CAST(cType, self)
uint8_t GblBool
Basic boolean type, standardized to sizeof(char)
uintptr_t GblType
Meta Type UUID.
Definition gimbal_type.h:51
Arena/zone/region/area-based paged allocator.
size_t pageSize
Default page size for all new pages.
GblContext * pCtx
Custom context associated with allocator.
GblArenaAllocatorPage * pActivePage
Active (unfilled) page at list head.
size_t pageAlign
Alignment of each page, also maximum requestable alignment.
GblLinkedListNode listNode
Linked list node base.
size_t allocCount
Total # of allocations across all pages.
Represents a single arena allocation page.
GblLinkedListNode listNode
Linked list node base.
size_t capacity
Page capacity.
struct GblArenaAllocatorPage * pNext
Next (used) allocator page.
size_t used
Number of bytes filled on page.
GblBool staticAlloc
Whether this page is static or heap allocated.
unsigned char bytes[1]
first byte of data segment
Represents the current state of a GblArenaAllocator.