16#define restrict __restrict__
34#define PASTE(a, b) a##b
42#define XPASTE(a, b) PASTE(a, b)
50#define JOIN(a, b) XPASTE(a, XPASTE(_, b))
61#define IS_POW2(X) ((X) != 0 && ((X) & ((X) - 1)) == 0)
74#ifndef FQUEUE_FOR_EACH
75#define FQUEUE_FOR_EACH(self, index, value) \
76 for ((index) = 0; (index) < (self)->count \
77 && ((value) = (self)->values[((self)->begin_index + (index)) & ((self)->capacity - 1)], true); \
91#ifndef FQUEUE_FOR_EACH_REVERSE
92#define FQUEUE_FOR_EACH_REVERSE(self, index, value) \
93 for ((index) = 0; (index) < (self)->count \
94 && ((value) = (self)->values[((self)->end_index - 1 - (index)) & ((self)->capacity - 1)], true); \
108#ifndef FQUEUE_CALC_SIZEOF
109#define FQUEUE_CALC_SIZEOF(fqueue_name, capacity) \
110 (uint32_t)(offsetof(struct fqueue_name, values) + capacity * sizeof(((struct fqueue_name *)0)->values[0]))
123#ifndef FQUEUE_CALC_SIZEOF_OVERFLOWS
124#define FQUEUE_CALC_SIZEOF_OVERFLOWS(fqueue_name, capacity) \
125 (capacity > (UINT32_MAX - offsetof(struct fqueue_name, values)) / sizeof(((struct fqueue_name *)0)->values[0]))
136#error "Must define NAME."
137#define FUNCTION_DEFINITIONS
138#define TYPE_DEFINITIONS
140#define FQUEUE_NAME NAME
151#define VALUE_TYPE int
152#error "Must define VALUE_TYPE."
159#ifndef FUNCTION_LINKAGE
160#define FUNCTION_LINKAGE
164#define FQUEUE_TYPE struct FQUEUE_NAME
165#define FQUEUE_INIT JOIN(FQUEUE_NAME, init)
166#define FQUEUE_IS_EMPTY JOIN(FQUEUE_NAME, is_empty)
167#define FQUEUE_IS_FULL JOIN(FQUEUE_NAME, is_full)
180#ifdef TYPE_DEFINITIONS
205FUNCTION_LINKAGE FQUEUE_TYPE *
JOIN(FQUEUE_NAME, init)(FQUEUE_TYPE *self,
const uint32_t pow2_capacity);
220 create_custom)(
const uint32_t min_capacity,
void *context_ptr,
221 void *(*allocate)(
void *context_ptr,
size_t alignment,
size_t size));
245 void (*deallocate)(
void *context_ptr,
void *mem));
344FUNCTION_LINKAGE void JOIN(FQUEUE_NAME, copy)(FQUEUE_TYPE *restrict dest_ptr,
const FQUEUE_TYPE *restrict src_ptr);
354#ifdef FUNCTION_DEFINITIONS
361#include "round_up_pow2_32.h"
366 assert(
IS_POW2(pow2_capacity));
368 self->begin_index = self->end_index = 0;
370 self->capacity = pow2_capacity;
376 create_custom)(
const uint32_t min_capacity,
void *context_ptr,
377 void *(*allocate)(
void *context_ptr,
size_t alignment,
size_t size))
379 if (min_capacity == 0 || min_capacity > UINT32_MAX / 2 + 1) {
383 const uint32_t capacity = round_up_pow2_32(min_capacity);
391 FQUEUE_TYPE *self = (FQUEUE_TYPE *)allocate(context_ptr,
alignof(FQUEUE_TYPE), size);
397 memset(self, 0, size);
398 FQUEUE_INIT(self, capacity);
404static inline void *
JOIN(internal,
JOIN(FQUEUE_NAME, allocate))(
void *context_ptr,
size_t alignment,
size_t size)
414 return JOIN(FQUEUE_NAME, create_custom)(capacity, NULL,
JOIN(internal,
JOIN(FQUEUE_NAME, allocate)));
418 void (*deallocate)(
void *context_ptr,
void *mem))
420 assert(self != NULL);
422 deallocate(context_ptr, self);
426static inline void JOIN(internal,
JOIN(FQUEUE_NAME, deallocate))(
void *context_ptr,
void *mem)
435 assert(self != NULL);
437 JOIN(FQUEUE_NAME, destroy_custom)(self, NULL,
JOIN(internal,
JOIN(FQUEUE_NAME, deallocate)));
442 assert(self != NULL);
444 return self->count == 0;
449 assert(self != NULL);
451 return self->count == self->capacity;
456 assert(self != NULL);
457 assert(index < self->count);
459 const uint32_t index_mask = (self->capacity - 1);
461 return self->values[(self->begin_index + index) & index_mask];
466 assert(self != NULL);
467 assert(!FQUEUE_IS_EMPTY(self));
469 return self->values[self->begin_index];
474 assert(self != NULL);
475 assert(!FQUEUE_IS_EMPTY(self));
477 const uint32_t index_mask = (self->capacity - 1);
479 return self->values[(self->end_index - 1) & index_mask];
484 return JOIN(FQUEUE_NAME, get_front)(self);
489 assert(self != NULL);
490 assert(!FQUEUE_IS_FULL(self));
492 const uint32_t index_mask = (self->capacity - 1);
494 self->values[self->end_index] = value;
496 self->end_index &= index_mask;
504 assert(self != NULL);
505 assert(!FQUEUE_IS_EMPTY(self));
507 const uint32_t index_mask = (self->capacity - 1);
509 const VALUE_TYPE value = self->values[self->begin_index];
511 self->begin_index &= index_mask;
519 assert(self != NULL);
522 self->begin_index = self->end_index = 0;
525FUNCTION_LINKAGE void JOIN(FQUEUE_NAME, copy)(FQUEUE_TYPE *restrict dest_ptr,
const FQUEUE_TYPE *restrict src_ptr)
527 assert(src_ptr != NULL);
528 assert(dest_ptr != NULL);
529 assert(src_ptr->count <= dest_ptr->capacity);
530 assert(FQUEUE_IS_EMPTY(dest_ptr));
532 const uint32_t src_begin_index = src_ptr->begin_index;
533 const uint32_t src_index_mask = src_ptr->capacity - 1;
535 for (uint32_t i = 0; i < src_ptr->count; i++) {
536 dest_ptr->values[i] = src_ptr->values[(src_begin_index + i) & src_index_mask];
539 dest_ptr->count = src_ptr->count;
540 dest_ptr->begin_index = 0;
541 dest_ptr->end_index = src_ptr->count;
552#undef FUNCTION_LINKAGE
553#undef FUNCTION_DEFINITIONS
554#undef TYPE_DEFINITIONS
558#undef FQUEUE_CALC_SIZEOF
560#undef FQUEUE_IS_EMPTY
#define JOIN(a, b)
First expand tokens, then paste them together with a _ in between.
Definition fqueue_template.h:50
#define IS_POW2(X)
Macro to check if a number is a power of two.
Definition fqueue_template.h:61
#define FQUEUE_CALC_SIZEOF(fqueue_name, capacity)
Calculate the size of the queue struct. No overflow checks.
Definition fqueue_template.h:109
#define FQUEUE_CALC_SIZEOF_OVERFLOWS(fqueue_name, capacity)
Check for a given capacity, if the equivalent size of the queue struct overflows.
Definition fqueue_template.h:124
#define VALUE_TYPE
Queue value type. This must be manually defined before including this header file.
Definition fqueue_template.h:151
#define FUNCTION_LINKAGE
Specify function linkage e.g. static inline.
Definition fstack_template.h:145
#define VALUE_TYPE
Stack value type. This must be manually defined before including this header file.
Definition fstack_template.h:136
uint32_t count
Number of values.
Definition fqueue_template.h:188
uint32_t end_index
Index used to track the back of the queue.
Definition fqueue_template.h:187
VALUE_TYPE values[]
Array of values.
Definition fqueue_template.h:190
uint32_t begin_index
Index used to track the front of the queue.
Definition fqueue_template.h:186
uint32_t capacity
Maximum number of values allocated for.
Definition fqueue_template.h:189