Rename unzip tool.
[SquirrelJME.git] / nanocoat / include / sjme / alloc.h
blob6dfd4860e4a4c9979d39d8732741d46527f9fcaf
1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // -------------------------------------------------------------------------*/
10 /**
11 * SquirrelJME allocator.
13 * @since 2023/11/18
16 #ifndef SQUIRRELJME_ALLOC_H
17 #define SQUIRRELJME_ALLOC_H
19 #include "sjme/nvm.h"
20 #include "sjme/debug.h"
21 #include "sjme/atomic.h"
22 #include "sjme/multithread.h"
24 /* Anti-C++. */
25 #ifdef __cplusplus
26 #ifndef SJME_CXX_IS_EXTERNED
27 #define SJME_CXX_IS_EXTERNED
28 #define SJME_CXX_SQUIRRELJME_ALLOC_H
29 extern "C" {
30 #endif /* #ifdef SJME_CXX_IS_EXTERNED */
31 #endif /* #ifdef __cplusplus */
33 /*--------------------------------------------------------------------------*/
35 /**
36 * Allocation link chain, each is a chain between each allocation.
38 * @since 2023/11/18
40 typedef struct sjme_alloc_link sjme_alloc_link;
42 /**
43 * Allocation pool and link space types.
45 * @since 2023/11/18
47 typedef enum sjme_alloc_poolSpace
49 /** Invalid space. */
50 SJME_ALLOC_POOL_SPACE_INVALID,
52 /** Free space. */
53 SJME_ALLOC_POOL_SPACE_FREE,
55 /** Used space. */
56 SJME_ALLOC_POOL_SPACE_USED,
58 /** the number of possible spaces. */
59 SJME_NUM_ALLOC_POOL_SPACE
60 } sjme_alloc_poolSpace;
62 /**
63 * Special link flags.
65 * @since 2024/02/08
67 typedef enum sjme_alloc_linkFlag
69 /** Nested allocation pool. */
70 SJME_ALLOC_LINK_FLAG_NESTED_POOL = 1,
71 } sjme_alloc_linkFlag;
73 /**
74 * Object for referenced counted weak pointer references.
76 * @since 2024/07/01
78 typedef struct sjme_alloc_weakBase* sjme_alloc_weak;
80 /**
81 * This is called when a weak reference has been freed or is about to be
82 * freed.
84 * @param weak The weak reference being freed.
85 * @param data The data for the free.
86 * @param isBlockFree Was this called because the underlying block was freed?
87 * @return Any resultant error code. If this function
88 * returns @c SJME_ERROR_ENQUEUE_KEEP_WEAK and the weak reference reaches
89 * zero references, then it will not be freed.
90 * @since 2024/07/02
92 typedef sjme_errorCode (*sjme_alloc_weakEnqueueFunc)(
93 sjme_attrInNotNull sjme_alloc_weak weak,
94 sjme_attrInNullable sjme_pointer data,
95 sjme_attrInValue sjme_jboolean isBlockFree);
97 /** Weak reference is valid. */
98 #define SJME_ALLOC_WEAK_VALID UINT32_C(0x58657221)
100 struct sjme_alloc_weakBase
102 /** Is this weak reference valid? */
103 sjme_atomic_sjme_jint valid;
105 /** The link this points to, @c NULL if freed. */
106 sjme_alloc_link* link;
108 /** The count for this weak reference, zero will free this reference. */
109 sjme_atomic_sjme_jint count;
111 /** The pointer this points to, @c NULL if freed. */
112 sjme_pointer pointer;
114 /** The data to call for when this is removed. */
115 sjme_alloc_weakEnqueueFunc enqueue;
117 /** The pointer for enqueue. */
118 sjme_pointer enqueueData;
121 struct sjme_alloc_link
123 /** The front guard. */
124 sjme_jint guardFront;
126 /** The pool this is in. */
127 volatile sjme_alloc_pool* pool;
129 /** Previous link. */
130 sjme_alloc_link* prev;
132 /** Next link. */
133 sjme_alloc_link* next;
135 /** The space this is in. */
136 sjme_alloc_poolSpace space;
138 /** The previous free link. */
139 sjme_alloc_link* freePrev;
141 /** The next free link. */
142 sjme_alloc_link* freeNext;
144 /** The weak reference this is attached to. */
145 sjme_alloc_weak weak;
147 /** The allocation size of the link, @code{allocSize <= blockSize}. */
148 sjme_jint allocSize;
150 /** The size of the data area of this block. */
151 sjme_jint blockSize;
153 /** Link flags. */
154 sjme_jint flags;
156 #if defined(SJME_CONFIG_DEBUG)
157 /** The file of this allocation. */
158 sjme_lpcstr debugFile;
160 /** The line of this allocation. */
161 sjme_jint debugLine;
163 /** The function of this allocation. */
164 sjme_lpcstr debugFunction;
165 #endif
167 /** The back guard. */
168 sjme_jint guardBack;
170 /** The memory block. */
171 sjme_jubyte block[sjme_flexibleArrayCount];
175 * Calculates the size of the pool link.
177 * @param size The size to use for the pool link.
178 * @return The size of the given pool link.
179 * @since 2023/11/16
181 #define SJME_SIZEOF_ALLOC_LINK(size) \
182 (offsetof(sjme_alloc_link, block) + (((size_t)(size)) * \
183 sizeof(sjme_jubyte)))
186 * Structure which stores the pooled memory allocator.
188 * @since 2023/11/18
190 struct sjme_alloc_pool
192 /** The front end wrapped type. */
193 sjme_frontEnd frontEnd;
195 /** The size of the allocation pool. */
196 sjme_jint size;
198 /** Whole pool spin lock. */
199 sjme_thread_spinLock spinLock;
201 /** Free and used space information. */
202 struct
204 /** Space that can be used. */
205 sjme_jint usable;
207 /** Space that is actually reserved due to overhead. */
208 sjme_jint reserved;
209 } space[SJME_NUM_ALLOC_POOL_SPACE];
211 /** Previous pool in multi-pool chain allocation. */
212 sjme_alloc_pool* prevPool;
214 /** Next pool in multi-pool chain allocation. */
215 sjme_alloc_pool* nextPool;
217 /** The front chain link. */
218 sjme_alloc_link* frontLink;
220 /** The back chain link. */
221 sjme_alloc_link* backLink;
223 /** The first free link in the chain. */
224 sjme_alloc_link* freeFirstLink;
226 /** The last free link in the chain. */
227 sjme_alloc_link* freeLastLink;
229 /** The memory block. */
230 sjme_jubyte block[sjme_flexibleArrayCount];
234 * Calculates the size of the allocation pool.
236 * @param size The size to use for the allocation pool.
237 * @return The size of the given allocation pool.
238 * @since 2023/11/16
240 #define SJME_SIZEOF_ALLOC_POOL(size) \
241 (sizeof(sjme_alloc_pool) + (((size_t)(size)) * \
242 sizeof(sjme_jubyte)))
245 * Allocates a pool that is based on @c malloc() .
247 * @param outPool The resultant pool.
248 * @param size The requested pool size.
249 * @return Returns an error code.
250 * @since 2023/11/18
252 sjme_errorCode sjme_alloc_poolInitMalloc(
253 sjme_attrOutNotNull sjme_alloc_pool** outPool,
254 sjme_attrInPositive sjme_jint size);
257 * Allocates a pool that is based on a static region of memory.
259 * @param outPool The resultant pool.
260 * @param baseAddr The base address of the block.
261 * @param size The size of the block.
262 * @return Returns an error code.
263 * @since 2023/11/18
265 sjme_errorCode sjme_alloc_poolInitStatic(
266 sjme_attrOutNotNull sjme_alloc_pool** outPool,
267 sjme_attrInNotNull sjme_pointer baseAddr,
268 sjme_attrInPositive sjme_jint size);
271 * Returns the total space that is available within the pool, includes both
272 * free and used spaces.
274 * @param pool The pool to get the information of.
275 * @param outTotal The total space of the pool, will be @c outReserved plus
276 * the value of @c outUsable .
277 * @param outReserved The total reserved space within the pool.
278 * @param outUsable The total usable space within the pool.
279 * @return Any error or otherwise success.
280 * @since 2023/12/11
282 sjme_errorCode sjme_alloc_poolSpaceTotalSize(
283 sjme_attrInNotNull const sjme_alloc_pool* pool,
284 sjme_attrOutNullable sjme_jint* outTotal,
285 sjme_attrOutNullable sjme_jint* outReserved,
286 sjme_attrOutNullable sjme_jint* outUsable);
289 * Allocates memory within the given pool.
291 * @param pool The pool to allocate within.
292 * @param size The number of bytes to allocate.
293 * @param outAddr The output address.
294 * @return Returns an error code.
295 * @since 2023/11/19
297 sjme_errorCode SJME_DEBUG_IDENTIFIER(sjme_alloc)(
298 sjme_attrInNotNull volatile sjme_alloc_pool* pool,
299 sjme_attrInPositiveNonZero sjme_jint size,
300 sjme_attrOutNotNull sjme_pointer* outAddr
301 SJME_DEBUG_ONLY_COMMA SJME_DEBUG_DECL_FILE_LINE_FUNC_OPTIONAL);
304 * Allocates a weak reference within the given pool.
306 * @param inPool The pool to allocate within.
307 * @param size The number of bytes to allocate.
308 * @param inEnqueue The optional function to call when this reference is
309 * enqueued. If this function returns @c SJME_ERROR_ENQUEUE_KEEP_WEAK and the
310 * weak reference count is zero, then the weak reference will not be freed.
311 * @param inEnqueueData Optional data to pass to @c inEnqueue .
312 * @param outAddr The output address.
313 * @param outWeak The resultant weak reference.
314 * @return Returns an error code.
315 * @since 2024/07/08
317 sjme_errorCode SJME_DEBUG_IDENTIFIER(sjme_alloc_weakNew)(
318 sjme_attrInNotNull volatile sjme_alloc_pool* inPool,
319 sjme_attrInPositiveNonZero sjme_jint size,
320 sjme_attrInNullable sjme_alloc_weakEnqueueFunc inEnqueue,
321 sjme_attrInNullable sjme_pointer inEnqueueData,
322 sjme_attrOutNotNull sjme_pointer* outAddr,
323 sjme_attrOutNotNull sjme_alloc_weak* outWeak
324 SJME_DEBUG_ONLY_COMMA SJME_DEBUG_DECL_FILE_LINE_FUNC_OPTIONAL);
327 * Allocates a copy of the given data.
329 * @param pool The pool to allocate within.
330 * @param size The allocation size.
331 * @param outAddr The output address.
332 * @param inAddr The input address.
333 * @return Returns an error code.
334 * @since 2023/12/13
336 sjme_errorCode SJME_DEBUG_IDENTIFIER(sjme_alloc_copy)(
337 sjme_attrInNotNull volatile sjme_alloc_pool* pool,
338 sjme_attrInPositiveNonZero sjme_jint size,
339 sjme_attrOutNotNull sjme_pointer* outAddr,
340 sjme_attrInNotNull sjme_pointer inAddr
341 SJME_DEBUG_ONLY_COMMA SJME_DEBUG_DECL_FILE_LINE_FUNC_OPTIONAL);
344 * Allocates a formatted string.
346 * @param inPool The pool to allocate within.
347 * @param outString The output string.
348 * @param format The format string.
349 * @param ...
350 * @return Any resultant error.
351 * @since 2023/12/22
353 sjme_errorCode SJME_DEBUG_IDENTIFIER(sjme_alloc_format)(
354 sjme_attrInNotNull sjme_alloc_pool* inPool,
355 sjme_attrOutNotNull sjme_lpstr* outString,
356 SJME_DEBUG_DECL_FILE_LINE_FUNC_OPTIONAL SJME_DEBUG_ONLY_COMMA
357 sjme_attrInNotNull sjme_attrFormatArg const char* format,
358 ...) SJME_DEBUG_TERNARY(sjme_attrFormatOuter(5, 6),
359 sjme_attrFormatOuter(2, 3));
362 * Reallocates memory, either growing it or shrinking... the pointer will be
363 * adjusted accordingly.
365 * @param inOutAddr The address to reallocate.
366 * @param newSize The new size of the allocation, if @c 0 then the pointer
367 * is freed instead.
368 * @return Returns an error code.
369 * @since 2023/11/28
371 sjme_errorCode SJME_DEBUG_IDENTIFIER(sjme_alloc_realloc)(
372 sjme_attrInOutNotNull sjme_pointer* inOutAddr,
373 sjme_attrInPositive sjme_jint newSize
374 SJME_DEBUG_ONLY_COMMA SJME_DEBUG_DECL_FILE_LINE_FUNC_OPTIONAL);
377 * Allocates a copy of the given C character sequence.
379 * @param inPool The pool to allocate within.
380 * @param outString The output string copy.
381 * @param stringToCopy The string to copy.
382 * @return Any resultant error, if any.
383 * @since 2024/07/21
385 sjme_errorCode SJME_DEBUG_IDENTIFIER(sjme_alloc_strdup)(
386 sjme_attrInNotNull sjme_alloc_pool* inPool,
387 sjme_attrOutNotNull sjme_lpcstr* outString,
388 sjme_attrInNotNull sjme_lpcstr stringToCopy
389 SJME_DEBUG_ONLY_COMMA SJME_DEBUG_DECL_FILE_LINE_FUNC_OPTIONAL);
391 #if defined(SJME_CONFIG_DEBUG)
394 * Allocates memory within the given pool.
396 * @param pool The pool to allocate within.
397 * @param size The number of bytes to allocate.
398 * @param outAddr The output address.
399 * @return Returns an error code.
400 * @since 2023/11/19
402 #define sjme_alloc(pool, size, outAddr) \
403 sjme_allocR((pool), (size), (outAddr), SJME_DEBUG_FILE_LINE_FUNC)
406 * Allocates a weak reference within the given pool.
408 * @param pool The pool to allocate within.
409 * @param size The number of bytes to allocate.
410 * @param inEnqueue The optional function to call when this reference is
411 * enqueued. If this function returns @c SJME_ERROR_ENQUEUE_KEEP_WEAK and the
412 * weak reference count is zero, then the weak reference will not be freed.
413 * @param inEnqueueData Optional data to pass to @c inEnqueue .
414 * @param outAddr The output address.
415 * @param outWeak The resultant weak reference.
416 * @return Returns an error code.
417 * @since 2024/07/08
419 #define sjme_alloc_weakNew(pool, size, inEnqueue, inEnqueueData, \
420 outAddr, outWeak) \
421 sjme_alloc_weakNewR((pool), (size), (inEnqueue), (inEnqueueData), \
422 (outAddr), (outWeak), SJME_DEBUG_FILE_LINE_FUNC)
425 * Allocates a copy of the given data.
427 * @param pool The pool to allocate within.
428 * @param size The allocation size.
429 * @param outAddr The output address.
430 * @param inAddr The input address.
431 * @return Returns an error code.
432 * @since 2023/12/13
434 #define sjme_alloc_copy(pool, size, outAddr, inAddr) \
435 sjme_alloc_copyR((pool), (size), (outAddr), (inAddr), \
436 SJME_DEBUG_FILE_LINE_FUNC)
439 * Allocates a formatted string.
441 * @param inPool The pool to allocate within.
442 * @param outString The output string.
443 * @param format The format string.
444 * @param ...
445 * @return Any resultant error.
446 * @since 2023/12/22
448 #define sjme_alloc_format(inPool, outString, ...) \
449 sjme_alloc_formatR((inPool), (outString), SJME_DEBUG_FILE_LINE_FUNC, \
450 __VA_ARGS__)
453 * Reallocates memory, either growing it or shrinking... the pointer will be
454 * adjusted accordingly.
456 * @param inOutAddr The address to reallocate.
457 * @param newSize The new size of the allocation, if @c 0 then the pointer
458 * is freed instead.
459 * @return Returns an error code.
460 * @since 2023/11/28
462 #define sjme_alloc_realloc(inOutAddr, newSize) \
463 sjme_alloc_reallocR((inOutAddr), (newSize), SJME_DEBUG_FILE_LINE_FUNC)
466 * Allocates a copy of the given C character sequence.
468 * @param inPool The pool to allocate within.
469 * @param outString The output string copy.
470 * @param stringToCopy The string to copy.
471 * @return Any resultant error, if any.
472 * @since 2024/07/21
474 #define sjme_alloc_strdup(inPool, outString, stringToCopy) \
475 sjme_alloc_strdupR((inPool), (outString), (stringToCopy), \
476 SJME_DEBUG_FILE_LINE_FUNC)
478 #endif
481 * Frees memory.
483 * @param addr The memory to free.
484 * @return Returns @c SJME_JNI_TRUE on success.
485 * @since 2023/11/19
487 sjme_errorCode sjme_alloc_free(
488 sjme_attrInNotNull sjme_pointer addr);
491 * Returns the link of the given memory block
493 * @param addr The pointer to get the link from.
494 * @param outLink The resultant link.
495 * @return Returns an error code.
496 * @since 2023/11/19
498 sjme_errorCode sjme_alloc_getLink(
499 sjme_attrInNotNull sjme_pointer addr,
500 sjme_attrOutNotNull sjme_alloc_link** outLink);
503 * Deletes a weak reference by un-counting it, if the count reaches zero
504 * then this weak will be freed if that was requested.
506 * @param inOutWeak The weak reference to delete, if the count reaches
507 * zero then the pointer will be set to @c NULL .
508 * @return Any resultant error, if any.
509 * @since 2024/07/01
511 sjme_errorCode sjme_alloc_weakDelete(
512 sjme_attrInOutNotNull sjme_alloc_weak* inOutWeak);
515 * Gets the pointer pointed to by the given weak reference, if this returns
516 * the value @c NULL then @c sjme_alloc_weakDelete should be called to
517 * remove any stale weak references.
519 * @param inWeak The weak reference to get from.
520 * @param outPointer The pointer to the referenced memory, if it has been
521 * freed then this will return @c NULL .
522 * @return Any resultant error, if any.
523 * @since 2024/07/01
525 sjme_errorCode sjme_alloc_weakGetPointer(
526 sjme_attrInNotNull sjme_alloc_weak inWeak,
527 sjme_attrOutNotNull sjme_pointer* outPointer);
530 * Creates or returns a weak reference to the given block. If the reference
531 * already exists, then it will be incremented.
533 * @param addr The address to reference.
534 * @param outWeak The resultant weak reference for the type.
535 * @param inEnqueue The optional function to call when this reference is
536 * enqueued. If this function returns @c SJME_ERROR_ENQUEUE_KEEP_WEAK and the
537 * weak reference count is zero, then the weak reference will not be freed.
538 * @param inEnqueueData Optional data to pass to @c inEnqueue .
539 * @return Any resultant error, if any.
540 * @since 2024/07/01
542 sjme_errorCode sjme_alloc_weakRef(
543 sjme_attrInNotNull sjme_pointer addr,
544 sjme_attrOutNotNull sjme_alloc_weak* outWeak,
545 sjme_attrInNullable sjme_alloc_weakEnqueueFunc inEnqueue,
546 sjme_attrInNullable sjme_pointer inEnqueueData);
548 #if defined(SJME_CONFIG_DEBUG)
551 * Dumps the entire pool.
553 * @param inPool The pool to dump.
554 * @return Any resultant error, if any.
555 * @since 2024/08/16
557 sjme_errorCode sjme_alloc_poolDump(
558 sjme_attrInNotNull sjme_alloc_pool* inPool);
560 #endif
562 /*--------------------------------------------------------------------------*/
564 /* Anti-C++. */
565 #ifdef __cplusplus
566 #ifdef SJME_CXX_SQUIRRELJME_ALLOC_H
568 #undef SJME_CXX_SQUIRRELJME_ALLOC_H
569 #undef SJME_CXX_IS_EXTERNED
570 #endif /* #ifdef SJME_CXX_SQUIRRELJME_ALLOC_H */
571 #endif /* #ifdef __cplusplus */
573 #endif /* SQUIRRELJME_ALLOC_H */