mirror of
https://github.com/raysan5/raylib.git
synced 2026-02-04 05:09:17 -05:00
Updated raylib memory pool (markdown)
@ -242,3 +242,83 @@ Which of course is equivalent to:
|
|||||||
```c
|
```c
|
||||||
ObjPool_Free(&vector_pool, origin), origin = NULL;
|
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