#ifndef _PIUMA_LIB_QUEUE_H_ #define _PIUMA_LIB_QUEUE_H_ #include "types.h" #include struct queue_header { u64 start; u64 size; u64 capacity; }; #define QUEUE_HEADER_PTR(queue) ((queue_header *)(((u8*)queue) - sizeof(queue_header))) #define QUEUE_TYPE(type) type * #define Queue_Alloc(alloc_func, type, capacity) ((type*) _queue_alloc(alloc_func, sizeof(type), capacity)) #define Queue_Free(free_func, queue) free_func(QUEUE_HEADER_PTR(queue)) #define Queue_Pop(queue) (queue[_queue_pop_index((u8*)queue)]) #define Queue_Push(queue, element) { queue[_queue_at_index((u8*)queue, QUEUE_HEADER_PTR(queue)->size)] = element; _queue_push_fix_indices((u8*)queue); } #define Queue_At(queue, index) (queue[_queue_at_index((u8*)queue, index)]) #define Queue_Size(queue) _queue_size((u8*)queue) #define Queue_Capacity(queue) _queue_capacity((u8*)queue) typedef void * (*alloc_func_t)(u64); typedef void (*free_func_t)(void *); inline u8 * _queue_alloc(alloc_func_t alloc_func, u64 sizeof_type, u64 capacity) { u8 *data; queue_header *header; data = (u8 *)alloc_func(sizeof(queue_header) + sizeof_type * capacity); header = (queue_header *)data; header->capacity = capacity; header->start = 0; header->size = 0; return data + sizeof(queue_header); } inline u64 _queue_pop_index(u8 *queue) { queue_header *header = QUEUE_HEADER_PTR(queue); assert(header->size > 0); u64 element_index = header->start; header->start = (header->start + 1) % header->capacity; header->size--; return element_index; } inline void _queue_push_fix_indices(u8 *queue) { queue_header *header = QUEUE_HEADER_PTR(queue); header->size++; if(header->size > header->capacity) { // Queue is full. Remove oldest element header->start = (header->start + 1) % header->capacity; header->size = header->capacity; } } inline u64 _queue_at_index(u8 *queue, u64 index) { queue_header *header = QUEUE_HEADER_PTR(queue); return (header->start + index) % header->capacity; } inline u64 _queue_size(u8 *queue) { queue_header *header = QUEUE_HEADER_PTR(queue); return header->size; } inline u64 _queue_capacity(u8 *queue) { queue_header *header = QUEUE_HEADER_PTR(queue); return header->capacity; } #endif