#ifndef UC_SLOT_ALLOCATOR_H_ #define UC_SLOT_ALLOCATOR_H_ #include #include #include // Repurpose free memory to eep a linked list of free slots typedef struct UCSlot UCSlot; struct UCSlot { UCSlot *next; }; typedef struct UCSlotArena UCSlotArena; struct UCSlotArena { UCSlot *free_list; uint8_t *memory_start; size_t memory_len; size_t n_slots; size_t slot_size; }; /** * Initialize a memory arena for dynamically allocating slots of memory. * Each allocation returns memory slots of the same size * Note: For max speed, align @memory and @slot_size to the size of a pointer * * @param arena arena to initialize * @param memory start of the backing memory * @param memory_len length of @memory * @param slot_size size of each slot allocation */ static inline void uc_slot_arena_init(UCSlotArena *arena, void *memory, size_t memory_len, size_t slot_size) { // Optionally - align to a pointer //slot_size = (slot_size + _Alignof(UCSlot) - 1) & (~(_Alignof(UCSlot) - 1)); assert(slot_size >= sizeof(UCSlot)); size_t n_slots = memory_len / slot_size; arena->free_list = NULL; uint8_t *start = (uint8_t *)memory; // build free_list in ascending order, anticipating sequential allocation // and sequential access as the common case for (size_t slot = n_slots; slot > 0; slot--) { size_t index = slot - 1; UCSlot *free_slot = (UCSlot *)(start + index * slot_size); free_slot->next = arena->free_list; arena->free_list = free_slot; } arena->n_slots = n_slots; arena->memory_start = (uint8_t*)memory; arena->memory_len = memory_len; arena->slot_size = slot_size; } static inline void *uc_slot_alloc(UCSlotArena *arena) { UCSlot *slot = arena->free_list; if (slot != NULL) { arena->free_list = slot->next; } return slot; } static inline void uc_slot_free(UCSlotArena *arena, void *mem) { if (mem != NULL) { assert((uint8_t *)mem >= arena->memory_start); assert((uint8_t *)mem < arena->memory_start + arena->memory_len); UCSlot *slot = (UCSlot *)mem; slot->next = arena->free_list; arena->free_list = slot; } } #endif