86 lines
2.8 KiB
C
86 lines
2.8 KiB
C
// 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 <string.h>
|
|
|
|
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);
|
|
}
|