diff --git a/turbolist.h b/turbolist.h new file mode 100644 index 0000000..88abc08 --- /dev/null +++ b/turbolist.h @@ -0,0 +1,92 @@ +#ifndef TURBO_LIST_H +#define TURBO_LIST_H +// TODO: malloclike and freelike refactor + +#include +#include +#include + +#ifndef TL_NOINLINE +#define TL_NOINLINE __attribute__((noinline)) +#endif /* TL_NOINLINE */ + +#ifndef TL_LIKELY +#define TL_LIKELY(x) __builtin_expect(!!(x), 1) +#endif /* TL_LIKELY */ +#ifndef TL_UNLIKELY +#define TL_UNLIKELY(x) __builtin_expect(!!(x), 0) +#endif /* TL_UNLIKELY */ + +struct turbolist{ + int *old; + int *nex; + + uint32_t mid; // non-inclusive . . . m + uint32_t end; // non-inclusive e . . . . + + uint32_t capacity; +}; +typedef struct turbolist turbolist; + +static inline void turbolist_insert(turbolist *tl, int elem); + +static TL_NOINLINE void __turbolist_grow_and_insert(turbolist *tl, int elem) { + // assert(mid == 0); + if(tl->old) free(tl->old); + tl->old = tl->nex; + tl->mid = tl->end; + tl->capacity *= 2; + tl->nex = (int *) malloc(tl->capacity * sizeof(int)); + + // Will go into the INSERT code path here + turbolist_insert(tl, elem); +} + +static inline turbolist turbolist_create(uint32_t initial_size = 0, uint32_t initial_cap = 16) { + assert(initial_size <= initial_cap); + + turbolist tl; + tl.old = NULL; + tl.mid = 0; + tl.end = initial_size; + tl.capacity = initial_cap; + tl.nex = (int *) malloc(tl.capacity * sizeof(int)); + return tl; +} + +static inline void turbolist_delete(turbolist *tl) { + if(tl->nex) free(tl->nex); + if(tl->old) free(tl->old); +} + +static inline int turbolist_get(turbolist *tl, uint32_t i) { + return (i < tl->mid) ? tl->old[i] : tl->nex[i]; +} + +static inline void turbolist_insert(turbolist *tl, int elem) { + if(TL_LIKELY(tl->end < tl->capacity)) { + + // INSERT + + /* Same as this: + if(mid > 0) { + nex[mid - 1] = old[mid - 1]; + --mid; + } + */ + bool hasmid = (tl->mid > 0); + tl->mid -= hasmid; + tl->nex[tl->mid] = hasmid ? tl->old[tl->mid] : tl->nex[tl->mid]; + + tl->nex[tl->end++] = elem; + } else { + // GROW + __turbolist_grow_and_insert(tl, elem); + } +} + +static inline uint32_t turbolist_size(turbolist *tl) { + return tl->mid + (tl->capacity - tl->end - 1); +} + +#endif /* TURBO_LIST_H */