#ifndef TURBO_LIST_H #define TURBO_LIST_H #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; void* (*malloc)(size_t size); void (*free)(void*); }; 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) tl->free(tl->old); tl->old = tl->nex; tl->mid = tl->end; tl->capacity *= 2; tl->nex = (int *) tl->malloc(tl->capacity * sizeof(int)); // Will go into the INSERT code path here turbolist_insert(tl, elem); } static inline turbolist turbolist_create_adv(void* (*malloc_like)(size_t size), void (*free_like)(void*), uint32_t initial_size, uint32_t initial_cap) { assert(initial_size <= initial_cap); turbolist tl; tl.old = NULL; tl.mid = 0; tl.end = initial_size; tl.capacity = initial_cap; tl.malloc = malloc_like; tl.free = free_like; tl.nex = (int *) tl.malloc(tl.capacity * sizeof(int)); return tl; } #ifndef NO_CSTDLIB static inline turbolist turbolist_create() { return turbolist_create_adv(malloc, free, 0, 16); } #endif /* NO_CSTDLIB */ static inline void turbolist_delete(turbolist *tl) { if(tl->nex) tl->free(tl->nex); if(tl->old) tl->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->end; } #endif /* TURBO_LIST_H */