diff --git a/poolsclosed/.clang-format b/poolsclosed/.clang-format new file mode 100644 index 0000000..5364839 --- /dev/null +++ b/poolsclosed/.clang-format @@ -0,0 +1,7 @@ +# Language: C +BasedOnStyle: LLVM +IndentWidth: 4 # Use 4 spaces for indentation +TabWidth: 4 # Tab width is also 4 spaces +UseTab: Never # Always use spaces instead of tabs +ColumnLimit: 80 # Wrap lines after 80 characters +AllowShortLoopsOnASingleLine: true diff --git a/poolsclosed/pool.c b/poolsclosed/pool.c new file mode 100644 index 0000000..181ea3a --- /dev/null +++ b/poolsclosed/pool.c @@ -0,0 +1,126 @@ +#include +#include +#include + +/* See: https://8dcc.github.io/programming/pool-allocator.html */ +/* See: https://github.com/8dcc/libpool */ + +#define CHUNK_SIZE 64 + +typedef union Chunk Chunk; +union Chunk { + Chunk *next; // When not null, it is used + char arr[CHUNK_SIZE]; +}; + +typedef struct LinkedPtr LinkedPtr; +struct LinkedPtr { + Chunk *ptr; + LinkedPtr *next; +}; + +typedef struct Pool Pool; +struct Pool { + Chunk *free_chunk; // Pointer to a linked list of free chunks + LinkedPtr *array_starts; +}; + +Pool *pool_new(size_t pool_size) { + Pool *pool = malloc(sizeof(Pool)); + + if (pool == NULL) + return NULL; + + Chunk *arr = pool->free_chunk = malloc(pool_size * sizeof(Chunk)); + if (arr == NULL) { + free(pool); + return NULL; + } + + for (size_t i = 0; i < pool_size - 1; i++) arr[i].next = &arr[i + 1]; + arr[pool_size - 1].next = NULL; + + pool->array_starts = malloc(sizeof(LinkedPtr)); + if (pool->array_starts == NULL) { + /* Allocation failed */ + free(arr); + free(pool); + return NULL; + } + + pool->array_starts->next = NULL; + pool->array_starts->ptr = arr; + + return pool; +} + +void *pool_alloc(Pool *pool) { + if (pool == NULL || pool->free_chunk == NULL) + return NULL; + + // Pop a new one from the free list + Chunk *result = pool->free_chunk; + pool->free_chunk = pool->free_chunk->next; + + return result; +} + +void pool_free(Pool *pool, void *ptr) { + if (pool == NULL || ptr == NULL) + return; + + // This can be done withuot an intermediate ptr + Chunk *freed = ptr; + freed->next = pool->free_chunk; + pool->free_chunk = freed; +} + +void pool_close(Pool *pool) { + if (pool == NULL) + return; + + LinkedPtr *lptr = pool->array_starts; + while (lptr != NULL) { + LinkedPtr *next = lptr->next; + free(lptr->ptr); + free(lptr); + lptr = next; + } + + free(pool); +} + +bool pool_resize(Pool *pool, size_t extra_chunk_num) { + if (pool == NULL || extra_chunk_num == 0) + return false; + + // Allocate the array of extra chunks that we are trying to add to the pool. + Chunk *extra_chunk_arr = malloc(extra_chunk_num * sizeof(Chunk)); + if (extra_chunk_arr == NULL) + return false; + + // Link the new chunks together, just like we did when creating the pool. + for (size_t i = 0; i < extra_chunk_num - 1; i++) + extra_chunk_arr[i].next = &extra_chunk_arr[i + 1]; + + // Prepend the array of extra chunks to the “free chunks” list, just like we + // did when freeing chunks. + extra_chunk_arr[extra_chunk_num - 1].next = pool->free_chunk; + pool->free_chunk = extra_chunk_arr; + + // Allocate a new LinkedPtr structure, and store the start of the new chunk + // array in it. + LinkedPtr *array_start = malloc(sizeof(LinkedPtr)); + if (array_start == NULL) { + free(extra_chunk_arr); + return false; + } + + // Prepend this new LinkedPtr structure to the linked list of “array + // starts”, stored inside the Pool structure. + array_start->ptr = extra_chunk_arr; + array_start->next = pool->array_starts; + pool->array_starts = array_start; + + return true; +} diff --git a/poolsclosed/simpe_pool.c b/poolsclosed/simpe_pool.c new file mode 100644 index 0000000..1f964d0 --- /dev/null +++ b/poolsclosed/simpe_pool.c @@ -0,0 +1,47 @@ +#include +#include + +/* See: https://8dcc.github.io/programming/pool-allocator.html */ + +#define CHUNK_SIZE 64 + +typedef union Chunk Chunk; +union Chunk { + Chunk *next; // When not null, it is used + char arr[CHUNK_SIZE]; +}; + +typedef struct Pool Pool; +struct Pool { + Chunk *free_chunk; // Pointer to a linked list of free chunks + Chunk *chunk_arr; +}; + +void *pool_alloc(Pool *pool) { + if (pool == NULL || pool->free_chunk == NULL) + return NULL; + + // Pop a new one from the free list + Chunk *result = pool->free_chunk; + pool->free_chunk = pool->free_chunk->next; + + return result; +} + +void pool_free(Pool *pool, void *ptr) { + if (pool == NULL || ptr == NULL) + return; + + // This can be done withuot an intermediate ptr + Chunk *freed = ptr; + freed->next = pool->free_chunk; + pool->free_chunk = freed; +} + +void pool_close(Pool *pool) { + if (pool == NULL) + return; + + free(pool->chunk_arr); + free(pool); +} diff --git a/poolsclosed/test.lua b/poolsclosed/test.lua new file mode 100755 index 0000000..60ba9b6 --- /dev/null +++ b/poolsclosed/test.lua @@ -0,0 +1,33 @@ +#!/usr/bin/env lua + +local m = {} + +print("Hello") +os.execute("echo $SHELL") + +m.abc = { + kek = 10, +} + +function m:print() + print(m.abc.kek) +end + +function os.getName() + local osname + -- ask LuaJIT first + if jit then + return jit.os + end + + -- Unix, Linux variants + local fh, _ = assert(io.popen("uname -o 2>/dev/null", "r")) + if fh then + osname = fh:read() + end + + return osname or "Windows" +end + +m:print() +print(os.getName())