4#if !defined(SKIP_INCLUDES)
12 #if !defined DC_PLACEHOLDERS
20 #define ITEM_DELETE item_delete
22 #define ITEM_CLONE item_clone
24 #define ITEM_DEBUG item_debug
28#if !defined ITEM_DELETE
29 #define ITEM_DELETE DC_NO_DELETE
32#if !defined ITEM_CLONE
33 #define ITEM_CLONE DC_COPY_CLONE
36#if !defined ITEM_DEBUG
37 #define ITEM_DEBUG DC_DEFAULT_DEBUG
55#define INVARIANT_CHECK(self) \
57 DC_ASSUME(DC_WHEN(!(self)->empty, \
58 (self)->head < (self)->capacity && (self)->tail < (self)->capacity)); \
59 DC_ASSUME(DC_WHEN((self)->empty, (self)->head == (self)->tail)); \
60 DC_ASSUME(DC_WHEN(!(self)->data, (self)->head == 0 && (self)->tail == 0));
70 .alloc_ref = alloc_ref,
78 if (capacity_for == 0) {
79 return NS(
SELF,
new)(alloc_ref);
86 capacity *
sizeof(
ITEM));
95 .alloc_ref = alloc_ref,
118 self->capacity *
sizeof(
ITEM));
119 }
else if (self->head <= self->tail) {
121 (self->capacity - (self->tail + 1)) *
sizeof(
ITEM));
123 self->head *
sizeof(
ITEM));
126 (self->head - (self->tail + 1)) *
sizeof(
ITEM));
134 if (new_capacity_for > self->capacity) {
142 if (self->data == NULL) {
147 self->capacity *
sizeof(
ITEM),
148 new_capacity *
sizeof(
ITEM));
151 if (self->head > self->tail) {
156 size_t const old_capacity = self->capacity;
157 size_t const additional_capacity = new_capacity - old_capacity;
158 size_t const front_tail_items = self->tail + 1;
159 size_t const back_head_items = old_capacity - self->head;
161 if (front_tail_items > back_head_items) {
162 size_t const new_head = self->head + additional_capacity;
163 memmove(&new_data[new_head], &new_data[self->head], back_head_items *
sizeof(
ITEM));
164 self->head = new_head;
170 DC_ASSUME(front_tail_items <= additional_capacity);
172 memcpy(&new_data[old_capacity], &new_data[0], front_tail_items *
sizeof(
ITEM));
173 self->tail = old_capacity + front_tail_items - 1;
176 self->capacity = new_capacity;
177 self->data = new_data;
194 &self->data[self->tail],
sizeof(
ITEM));
195 self->data[self->tail] =
item;
206 if (self->head == 0) {
207 self->head = self->capacity - 1;
213 &self->data[self->head],
sizeof(
ITEM));
214 self->data[self->head] =
item;
225 ITEM value = self->data[self->head];
227 &self->data[self->head],
sizeof(
ITEM));
229 &self->data[self->head],
sizeof(
ITEM));
232 if (self->head == self->tail) {
246 ITEM value = self->data[self->tail];
248 &self->data[self->tail],
sizeof(
ITEM));
250 if (self->head == self->tail) {
253 if (self->tail == 0) {
254 self->tail = self->capacity - 1;
264 if (index < self->
size) {
265 size_t const real_index =
267 return &self->data[real_index];
274 if (index >= self->size) {
277 if (index <= self->tail) {
278 return &self->data[self->tail - index];
280 size_t const from_end = index - self->tail;
281 return &self->data[self->capacity - from_end];
292#define ITER NS(SELF, iter)
339 size_t const size = self->capacity *
sizeof(
ITEM);
348#define ITER_CONST NS(SELF, iter_const)
387 ITEM* new_data = NULL;
389 size_t new_capacity = 0;
390 size_t const old_size = self->size;
406 .capacity = new_capacity,
410 .empty = self->empty,
411 .alloc_ref = self->alloc_ref,
448#undef INVARIANT_CHECK
static DC_PUBLIC void deallocate(SELF *self, void *ptr, size_t size)
static DC_PUBLIC void debug(SELF const *self, dc_debug_fmt fmt, FILE *stream)
static DC_PUBLIC void * allocate_uninit(SELF *self, size_t size)
static DC_PUBLIC void * reallocate(SELF *self, void *ptr, size_t old_size, size_t new_size)
#define INVARIANT_CHECK(self)
static DC_PUBLIC IV_PAIR next(ITER *iter)
static DC_PUBLIC bool empty(ITER const *iter)
static DC_PUBLIC bool empty_item(IV_PAIR const *item)
static DC_PUBLIC ITER get_iter(SELF *self)
static DC_PUBLIC ITER_CONST get_iter_const(SELF const *self)
static DC_PUBLIC size_t size(SELF const *self)
static DC_PUBLIC SELF clone(SELF const *self)
static DC_PUBLIC SELF new_with_capacity_for(INDEX_TYPE items, ref alloc_ref)
static DC_PUBLIC void reserve(SELF *self, size_t new_capacity_for)
static DC_PUBLIC ITEM * try_write_from_back(SELF *self, size_t index)
static DC_PUBLIC ITEM pop_front(SELF *self)
static DC_PUBLIC ITEM const * try_read_from_front(SELF const *self, size_t index)
static DC_PUBLIC ITEM * try_write_from_front(SELF *self, size_t index)
static DC_PUBLIC void push_front(SELF *self, ITEM item)
static DC_PUBLIC ITEM const * try_read_from_back(SELF const *self, size_t index)
static DC_PUBLIC void push_back(SELF *self, ITEM item)
static void PRIV set_inaccessible_memory_caps(SELF *self, dc_memory_tracker_capability cap)
static DC_PUBLIC ITEM pop_back(SELF *self)
#define DC_TRAIT_QUEUE(SELF)
static DC_PUBLIC ITEM * data(SELF *self)
#define TEMPLATE_ERROR(...)
With the user provided name, even in nested templates.
static DC_PUBLIC void dc_debug_fmt_print(dc_debug_fmt fmt, FILE *stream, const char *format,...)
static DC_PUBLIC void dc_debug_fmt_print_indents(dc_debug_fmt fmt, FILE *stream)
static DC_PUBLIC dc_debug_fmt dc_debug_fmt_scope_end(dc_debug_fmt fmt)
static DC_PUBLIC dc_debug_fmt dc_debug_fmt_scope_begin(dc_debug_fmt fmt)
static DC_PUBLIC dc_gdb_marker dc_gdb_marker_new()
#define DC_MATH_IS_POWER_OF_2(x)
static DC_PUBLIC size_t DC_INLINE DC_CONST dc_math_modulus_power_of_2_capacity(size_t index, size_t capacity)
static DC_INLINE DC_CONST size_t dc_math_next_power_of_2(size_t x)
static DC_PUBLIC void dc_memory_tracker_set(dc_memory_tracker_level level, dc_memory_tracker_capability cap, const volatile void *addr, size_t size)
static DC_PUBLIC void dc_memory_tracker_check(dc_memory_tracker_level level, dc_memory_tracker_capability cap, const void *addr, size_t size)
@ DC_MEMORY_TRACKER_LVL_CONTAINER
dc_memory_tracker_capability
a wrapper over asan & msan Containers and allocators can use this for custom asan & msan poisoning,...
@ DC_MEMORY_TRACKER_CAP_WRITE
@ DC_MEMORY_TRACKER_CAP_NONE
static DC_PUBLIC void mutation_tracker_mutate(mutation_tracker *self)
static DC_PUBLIC void mutation_version_check(mutation_version const *self)
static DC_PUBLIC mutation_tracker mutation_tracker_new()
static DC_PUBLIC mutation_version mutation_tracker_get(mutation_tracker const *self)
#define DC_EXPAND_STRING(NAME)
#define DC_ASSERT(expr,...)
#define DC_ASSUME(expr,...)
mutation_tracker iterator_invalidation_tracker
dc_gdb_marker derive_c_circular
Debug format helpers for debug printin data structures.
A queue comprised of an extendable circular buffer.
tracks a specific version of a value, so that this can be compared later to check modification For ex...
static DC_PUBLIC FILE * stream(SELF *self)