// vim:fileencoding=utf-8:foldmethod=marker #include "queue.h" #include "../array/array.h" #include "../../common/assert/assert.h" #include "../../common/misc/misc_utils.h" #include void _queue_push(GenericQueue *queue, void *item, u64 item_size) { wapp_debug_assert(queue != NULL, "`queue` should not be NULL"); wapp_runtime_assert(item_size == wapp_array_item_size(queue->items), "Invalid type"); u64 capacity = wapp_array_capacity(queue->items); if (queue->count >= capacity) { return; } u64 index = (queue->back)++; _array_set(queue->items, index, item, item_size); ++(queue->count); if (queue->back >= capacity) { queue->back = 0; } } GenericQueue *_queue_push_alloc(const Allocator *allocator, GenericQueue *queue, void *item, u64 item_size) { wapp_debug_assert(allocator != NULL && queue != NULL && item != NULL, "`allocator`, `queue` and `item` should not be NULL"); wapp_runtime_assert(item_size == wapp_array_item_size(queue->items), "Invalid type"); GenericQueue *output = queue; u64 capacity = wapp_array_capacity(queue->items); if (queue->count >= capacity) { u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(capacity * 2); u64 array_size = _array_calc_alloc_size(new_capacity, item_size); u64 alloc_size = sizeof(GenericQueue) + array_size; void *buffer = wapp_mem_allocator_alloc(allocator, alloc_size); if (!buffer) { goto RETURN_QUEUE_PUSH_ALLOC; } memset((void *)buffer, 0, alloc_size); output = (GenericQueue *)buffer; output->items = _array_from_preallocated_buffer((void *)(output + 1), array_size, ARRAY_INIT_FILLED, item_size); // NOTE (Abdelrahman): When the queue is full, the front and back indices should // always be the same u64 front_count = capacity - queue->front; u64 back_count = queue->back; void *copy_boundary = (void *)((uptr)(queue->items) + (queue->front * item_size)); memcpy(output->items, copy_boundary, front_count * item_size); if (back_count > 0) { void *back_copy_dst = (void *)((uptr)(output->items) + (front_count * item_size)); memcpy(back_copy_dst, queue->items, back_count * item_size); } output->front = 0; output->back = front_count + back_count; output->count = queue->count; } _queue_push(output, item, item_size); RETURN_QUEUE_PUSH_ALLOC: return output; } void *_queue_pop(GenericQueue *queue, u64 item_size) { wapp_debug_assert(queue != NULL, "`queue` should not be NULL"); wapp_runtime_assert(item_size == wapp_array_item_size(queue->items), "Invalid type"); if (queue->count == 0) { return NULL; } u64 index = (queue->front)++; --(queue->count); u64 capacity = wapp_array_capacity(queue->items); if (queue->front >= capacity) { queue->front = 0; } return _array_get(queue->items, index, item_size); }