stb_ds: Allow STBDS_REALLOC and STBDS_FREE defines to customize memory management.

This commit is contained in:
Andy Durdin 2019-05-27 11:07:30 +02:00
parent 5a2a8e882f
commit 6b2fb7702f

View File

@ -41,6 +41,15 @@ COMPILE-TIME OPTIONS
hash table insertion about 20% slower on 4- and 8-byte keys, 5% slower on hash table insertion about 20% slower on 4- and 8-byte keys, 5% slower on
64-byte keys, and 10% slower on 256-byte keys on my test computer. 64-byte keys, and 10% slower on 256-byte keys on my test computer.
#define STBDS_REALLOC better_realloc
#define STBDS_FREE better_free
These defines need to be set globally.
By default stb_ds uses stdlib realloc() and free() for memory management. You can
substitute your own functions (with the same signatures) instead by defining these
symbols. You must either define both, or neither.
LICENSE LICENSE
Placed in the public domain and also MIT licensed. Placed in the public domain and also MIT licensed.
@ -321,7 +330,6 @@ CREDITS
#ifndef INCLUDE_STB_DS_H #ifndef INCLUDE_STB_DS_H
#define INCLUDE_STB_DS_H #define INCLUDE_STB_DS_H
#include <stdlib.h>
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
@ -374,6 +382,16 @@ CREDITS
#define stralloc stbds_stralloc #define stralloc stbds_stralloc
#define strreset stbds_strreset #define strreset stbds_strreset
#endif #endif
#if defined(STBDS_REALLOC) && !defined(STBDS_FREE) || !defined(STBDS_REALLOC) && defined(STBDS_FREE)
#error "You must define both STBDS_REALLOC and STBDS_FREE, or neither."
#endif
#if !defined(STBDS_REALLOC) && !defined(STBDS_FREE)
#include <stdlib.h>
#define STBDS_REALLOC realloc
#define STBDS_FREE free
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -449,7 +467,7 @@ extern void * stbds_shmode_func(size_t elemsize, int mode);
#define stbds_arrpop(a) (stbds_header(a)->length--, (a)[stbds_header(a)->length]) #define stbds_arrpop(a) (stbds_header(a)->length--, (a)[stbds_header(a)->length])
#define stbds_arraddn(a,n) (stbds_arrmaybegrow(a,n), stbds_header(a)->length += (n)) #define stbds_arraddn(a,n) (stbds_arrmaybegrow(a,n), stbds_header(a)->length += (n))
#define stbds_arrlast(a) ((a)[stbds_header(a)->length-1]) #define stbds_arrlast(a) ((a)[stbds_header(a)->length-1])
#define stbds_arrfree(a) ((void) ((a) ? free(stbds_header(a)) : (void)0), (a)=NULL) #define stbds_arrfree(a) ((void) ((a) ? STBDS_FREE(stbds_header(a)) : (void)0), (a)=NULL)
#define stbds_arrdel(a,i) stbds_arrdeln(a,i,1) #define stbds_arrdel(a,i) stbds_arrdeln(a,i,1)
#define stbds_arrdeln(a,i,n) (memmove(&(a)[i], &(a)[(i)+(n)], sizeof *(a) * (stbds_header(a)->length-(n)-(i))), stbds_header(a)->length -= (n)) #define stbds_arrdeln(a,i,n) (memmove(&(a)[i], &(a)[(i)+(n)], sizeof *(a) * (stbds_header(a)->length-(n)-(i))), stbds_header(a)->length -= (n))
#define stbds_arrdelswap(a,i) ((a)[i] = stbds_arrlast(a), stbds_header(a)->length -= 1) #define stbds_arrdelswap(a,i) ((a)[i] = stbds_arrlast(a), stbds_header(a)->length -= 1)
@ -645,7 +663,7 @@ void *stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap)
else if (min_cap < 4) else if (min_cap < 4)
min_cap = 4; min_cap = 4;
b = realloc((a) ? stbds_header(a) : 0, elemsize * min_cap + sizeof(stbds_array_header)); b = STBDS_REALLOC((a) ? stbds_header(a) : 0, elemsize * min_cap + sizeof(stbds_array_header));
b = (char *) b + sizeof(stbds_array_header); b = (char *) b + sizeof(stbds_array_header);
if (a == NULL) { if (a == NULL) {
stbds_header(b)->length = 0; stbds_header(b)->length = 0;
@ -737,7 +755,7 @@ static size_t stbds_log2(size_t slot_count)
static stbds_hash_index *stbds_make_hash_index(size_t slot_count, stbds_hash_index *ot) static stbds_hash_index *stbds_make_hash_index(size_t slot_count, stbds_hash_index *ot)
{ {
stbds_hash_index *t; stbds_hash_index *t;
t = (stbds_hash_index *) realloc(0,(slot_count >> STBDS_BUCKET_SHIFT) * sizeof(stbds_hash_bucket) + sizeof(stbds_hash_index) + STBDS_CACHE_LINE_SIZE-1); t = (stbds_hash_index *) STBDS_REALLOC(0,(slot_count >> STBDS_BUCKET_SHIFT) * sizeof(stbds_hash_bucket) + sizeof(stbds_hash_index) + STBDS_CACHE_LINE_SIZE-1);
t->storage = (stbds_hash_bucket *) STBDS_ALIGN_FWD((size_t) (t+1), STBDS_CACHE_LINE_SIZE); t->storage = (stbds_hash_bucket *) STBDS_ALIGN_FWD((size_t) (t+1), STBDS_CACHE_LINE_SIZE);
t->slot_count = slot_count; t->slot_count = slot_count;
t->slot_count_log2 = stbds_log2(slot_count); t->slot_count_log2 = stbds_log2(slot_count);
@ -1053,7 +1071,6 @@ static int stbds_is_key_equal(void *a, size_t elemsize, void *key, size_t keysiz
#define STBDS_HASH_TO_ARR(x,elemsize) ((char*) (x) - (elemsize)) #define STBDS_HASH_TO_ARR(x,elemsize) ((char*) (x) - (elemsize))
#define STBDS_ARR_TO_HASH(x,elemsize) ((char*) (x) + (elemsize)) #define STBDS_ARR_TO_HASH(x,elemsize) ((char*) (x) + (elemsize))
#define STBDS_FREE(x) free(x)
#define stbds_hash_table(a) ((stbds_hash_index *) stbds_header(a)->hash_table) #define stbds_hash_table(a) ((stbds_hash_index *) stbds_header(a)->hash_table)
@ -1374,7 +1391,7 @@ static char *stbds_strdup(char *str)
// to keep replaceable allocator simple, we don't want to use strdup. // to keep replaceable allocator simple, we don't want to use strdup.
// rolling our own also avoids problem of strdup vs _strdup // rolling our own also avoids problem of strdup vs _strdup
size_t len = strlen(str)+1; size_t len = strlen(str)+1;
char *p = (char*) realloc(0, len); char *p = (char*) STBDS_REALLOC(0, len);
memmove(p, str, len); memmove(p, str, len);
return p; return p;
} }
@ -1407,7 +1424,7 @@ char *stbds_stralloc(stbds_string_arena *a, char *str)
// note that we still advance string_block so block size will continue // note that we still advance string_block so block size will continue
// increasing, so e.g. if somebody only calls this with 1000-long strings, // increasing, so e.g. if somebody only calls this with 1000-long strings,
// eventually the arena will start doubling and handling those as well // eventually the arena will start doubling and handling those as well
stbds_string_block *sb = (stbds_string_block *) realloc(0, sizeof(*sb)-8 + len); stbds_string_block *sb = (stbds_string_block *) STBDS_REALLOC(0, sizeof(*sb)-8 + len);
memmove(sb->storage, str, len); memmove(sb->storage, str, len);
if (a->storage) { if (a->storage) {
// insert it after the first element, so that we don't waste the space there // insert it after the first element, so that we don't waste the space there
@ -1420,7 +1437,7 @@ char *stbds_stralloc(stbds_string_arena *a, char *str)
} }
return sb->storage; return sb->storage;
} else { } else {
stbds_string_block *sb = (stbds_string_block *) realloc(0, sizeof(*sb)-8 + blocksize); stbds_string_block *sb = (stbds_string_block *) STBDS_REALLOC(0, sizeof(*sb)-8 + blocksize);
sb->next = a->storage; sb->next = a->storage;
a->storage = sb; a->storage = sb;
a->remaining = blocksize; a->remaining = blocksize;
@ -1440,7 +1457,7 @@ void stbds_strreset(stbds_string_arena *a)
x = a->storage; x = a->storage;
while (x) { while (x) {
y = x->next; y = x->next;
free(x); STBDS_FREE(x);
x = y; x = y;
} }
memset(a, 0, sizeof(*a)); memset(a, 0, sizeof(*a));