mirror of
https://github.com/raysan5/raylib.git
synced 2025-12-25 10:22:33 -05:00
Updated raylib memory pool (markdown)
@ -67,7 +67,7 @@ When we finish using the pool's memory, we clean it up by using `MemPool_Destroy
|
||||
```c
|
||||
MemPool_Destroy(&pool);
|
||||
```
|
||||
|
||||
|
||||
Alternatively, if you're not in a position to use any kind of dynamic allocation from the operating system, you have the option to utilize an existing buffer as memory for the mempool:
|
||||
```c
|
||||
char mem[64000];
|
||||
@ -79,7 +79,7 @@ To allocate from the pool, we have two functions:
|
||||
void *MemPool_Alloc(MemPool *mempool, size_t bytes);
|
||||
void *MemPool_Realloc(MemPool *mempool, void *ptr, size_t bytes);
|
||||
```
|
||||
|
||||
|
||||
`MemPool_Alloc` returns a (zeroed) pointer to a memory block.
|
||||
```c
|
||||
// allocate an int pointer.
|
||||
@ -242,3 +242,83 @@ Which of course is equivalent to:
|
||||
```c
|
||||
ObjPool_Free(&vector_pool, origin), origin = NULL;
|
||||
```
|
||||
|
||||
# Double-Ended aka Bi(furcated) Stack
|
||||
|
||||
By Kevin 'Assyrianic' Yonan @ https://github.com/assyrianic
|
||||
|
||||
**About**:
|
||||
The raylib BiStack is a fast & efficient bifurcated stack "bi-stack" allocator.
|
||||
|
||||
**Purpose**:
|
||||
raylib BiStack's purpose is the following list:
|
||||
* A quick, efficient way of allocating temporary, dynamically-sizeable memory during various operations.
|
||||
* Bifurcated to allow certain temporary data to have a different lifetime from other, temporary data.
|
||||
|
||||
**Data Implementation**:
|
||||
The bifurcated stack encapsulates one public struct:
|
||||
* `mem` which is an unsigned integer large enough to represent a pointer; the pointer value it holds is the memory address of the backing buffer.
|
||||
* `front` holds a pointer value representing the first aka _front_ portion of the bifurcated stack.
|
||||
* `back` holds a pointer value representing the second aka _back_ portion of the bifurcated stack.
|
||||
* and a `size` that holds the amount of bytes of the backing buffer.
|
||||
```c
|
||||
typedef struct BiStack {
|
||||
uintptr_t mem, front, back;
|
||||
size_t size;
|
||||
} BiStack;
|
||||
```
|
||||
|
||||
**Usage**:
|
||||
The bi-stack is designed to be used as a direct object.
|
||||
There are two constructor functions:
|
||||
```c
|
||||
BiStack CreateBiStack(size_t len);
|
||||
BiStack CreateBiStackFromBuffer(void *buf, size_t len);
|
||||
```
|
||||
To which you create a `BiStack` instance and give the function a max amount of memory you wish or require for your data.
|
||||
Remember not to exceed that memory amount or the allocation functions of the allocator will give you a NULL pointer.
|
||||
|
||||
So we create a bistack that will malloc an internal buffer of 10K bytes.
|
||||
```c
|
||||
BiStack bistack = CreateBiStack(10000);
|
||||
```
|
||||
|
||||
When the bi-stack is no longer needed, we clean it up by using `DestroyBiStack`.
|
||||
```c
|
||||
DestroyBiStack(&bistack);
|
||||
```
|
||||
|
||||
Alternatively, if you're not in a position to use any kind of dynamic allocation from the operating system, you have the option to utilize an existing buffer as memory for the bistack:
|
||||
```c
|
||||
char mem[64000];
|
||||
BiStack pool = CreateBiStackFromBuffer(mem, sizeof mem);
|
||||
```
|
||||
|
||||
To allocate from the bistack, we have two functions:
|
||||
```c
|
||||
void *BiStackAllocFront(BiStack *destack, size_t len);
|
||||
void *BiStackAllocBack(BiStack *destack, size_t len);
|
||||
```
|
||||
|
||||
**NOTE**: _The two allocator functions do **NOT** zero memory._
|
||||
```c
|
||||
// allocate an int pointer from the front.
|
||||
int *i = BiStackAllocFront(&bistack, sizeof *i);
|
||||
|
||||
// allocate a float pointer from the back.
|
||||
float *f = BiStackAllocBack(&bistack, sizeof *f);
|
||||
```
|
||||
|
||||
Unlike the other allocators, the Bi-stack does not require you free given pointers back to the allocator. However, you will need to reset the bi-stack in order to "free" the data back to the bi-stack. Here are three functions that resets the bi-stack:
|
||||
```c
|
||||
void BiStackResetFront(BiStack *destack);
|
||||
void BiStackResetBack(BiStack *destack);
|
||||
void BiStackResetAll(BiStack *destack);
|
||||
```
|
||||
`BiStackResetFront` will reset allocation data for the front portion of the bi-stack. So ALL pointers given from the front portion can be overwritten if any new pointers allocated also point to those parts. Same deal for `BiStackResetBack` and the back portion of the bi-stack.
|
||||
|
||||
If both portions need to be reset, `BiStackResetAll` will do the job.
|
||||
|
||||
An important caveat with the bi-stack is that if the back portion or the front portion collide with one another, you will be given a `NULL` pointer. To check if they will collide, `intptr_t BiStackMargins(BiStack destack);` is used to get the difference between how far, in bytes, the back portion is from the front.
|
||||
|
||||
The way this works is that, when allocating from the front portion, the `front` member is increased. When allocating the back portion, the `back` member is decreased. If the front portion reaches the back, that means the front portion of the bi-stack is out of memory, same deal for the back portion if it reaches the front. Thus, `BiStackMargins` provides you the difference between these two portions; a number of 0 or less means that one of the portions has reached the other and a reset is necessary.
|
||||
Reference in New Issue
Block a user