libGimbal 0.2.0
C17-Based Extended Standard Library and Cross-Language Runtime Framework
Loading...
Searching...
No Matches
gimbal_array_deque.h
Go to the documentation of this file.
1/*! \file
2 * \brief GblArrayDeque container and related functions
3 * \ingroup containers
4 * \copydoc GblArrayDeque
5 *
6 * \author Falco Girgis 2023, 2026
7 * \copyright MIT License
8 */
9
10#ifndef GIMBAL_ARRAY_DEQUE_H
11#define GIMBAL_ARRAY_DEQUE_H
12
14
15#ifndef GBL_ARRAY_DEQUE_FORCE_POW2
16# define GBL_ARRAY_DEQUE_FORCE_POW2 1
17#endif
18
19#define GBL_SELF_TYPE GblArrayDeque
20
22
23/*! Circular array-based double-ended queue container
24 * \ingroup containers
25 *
26 * GblArrayDeque is a very flexible container type which
27 * combines the fast random access and cache coherency
28 * of a contiguous array with the semantics of a double-ended
29 * queue. This means that not only are random
30 * accesses extremely efficient, but also adding and
31 * removing entries from either end as well.
32 *
33 * This container is well-suited for data sets which can
34 * grow or shrink from either end, but which are typically
35 * accessed as an array.
36 *
37 * Operation |Time Complexity
38 * --------------------------|------------------
39 * iteration | O(N)
40 * insertion (back or front) | O(1)
41 * insertion (middle) | O(N)
42 * removal (back or front) | O(1)
43 * removal (middle) | O(N)
44 * access (front or back) | O(1)
45 * random access (middle) | O(1)
46 *
47 * For reference, the following are the results of the
48 * profiler unit tests for some common operations shared
49 * between GblArrayList (comparable to std::vector) and
50 * GblArrayDeque (1024 pointer-sized entries):
51 *
52 * Test |GblArrayList|GblArrayDeque
53 * ----------|------------|-------------
54 * at |0.004 ms |0.008 ms
55 * pushBack |0.030 ms |0.030 ms
56 * pushFront |0.116 ms |0.027 ms
57 *
58 * \note
59 * This container can be seen as a slightly more specific,
60 * more optimized version of C++'s std::deque. A std::deque
61 * also allows for efficient insertion and removal to and
62 * from the middle of the array; however, this flexibility
63 * comes at the price of increased indirection overhead
64 * for random access and increased memory utilization.
65 * While GblArrayDeque does support random insertions and
66 * deletions, these are more costly than doing so from the
67 * front or back, as they require the shuffling around of
68 * surrounding elements in memory. We have decided that
69 * this trade-off is worth it, since we still support
70 * the operation, but fast lookups and lower memory
71 * utilization are much higher priorities.
72 *
73 * \note
74 * Internally this structure is implemented as an extension
75 * of the GblRingBuffer container, which is able to push
76 * from the front, pop from the back, and dynamically resize
77 * itself as it reaches its capacity.
78 *
79 * \note
80 * When the GBL_ARRAY_DEQUE_FORCE_POW2 macro is defined as 1
81 * (default) behavior), the capacity of the deque will always
82 * be rounded to the next power-of-two. This means any direct
83 * requests to GblArrayDeque_reserve() or
84 * GblArrayDeque_shrinkToFit() will not resize the container
85 * to the exact value specified. As a consequence of this,
86 * lookup times can be optimized by another 15-30% by reducing
87 * a modulo operation to a decrement + bitmask.
88 *
89 * \sa GblRingBuffer, GblArrayList
90 */
91typedef struct GblArrayDeque { // Size (32/64-bit)
93 GblRingBuffer ringBuffer;
94 GBL_PRIVATE_END // 22/42 total
95} GblArrayDeque;
96
97// ===== Public methods =====
98GBL_EXPORT GBL_RESULT GblArrayDeque_construct (GBL_SELF,
99 uint16_t elementSize,
100 size_t capacity,
101 size_t initialSize,
102 const void* pInitialData,
103 GblContext* pCtx) GBL_NOEXCEPT;
104
105GBL_EXPORT GBL_RESULT GblArrayDeque_destruct (GBL_SELF) GBL_NOEXCEPT;
106GBL_EXPORT GBL_RESULT GblArrayDeque_copy (GBL_SELF, const GblArrayDeque* pOther) GBL_NOEXCEPT;
107GBL_EXPORT GBL_RESULT GblArrayDeque_move (GBL_SELF, GblArrayDeque* pOther) GBL_NOEXCEPT;
108
109GBL_EXPORT GblContext* GblArrayDeque_context (GBL_CSELF) GBL_NOEXCEPT;
110GBL_EXPORT size_t GblArrayDeque_capacity (GBL_CSELF) GBL_NOEXCEPT;
111GBL_EXPORT size_t GblArrayDeque_size (GBL_CSELF) GBL_NOEXCEPT;
112GBL_EXPORT size_t GblArrayDeque_elementSize (GBL_CSELF) GBL_NOEXCEPT;
113
114GBL_EXPORT GblBool GblArrayDeque_empty (GBL_CSELF) GBL_NOEXCEPT;
115GBL_EXPORT GblBool GblArrayDeque_full (GBL_CSELF) GBL_NOEXCEPT;
116
117GBL_EXPORT void* GblArrayDeque_at (GBL_CSELF, size_t index) GBL_NOEXCEPT;
118GBL_EXPORT void* GblArrayDeque_front (GBL_CSELF) GBL_NOEXCEPT;
119GBL_EXPORT void* GblArrayDeque_back (GBL_CSELF) GBL_NOEXCEPT;
120
121GBL_EXPORT GBL_RESULT GblArrayDeque_pushBack (GBL_SELF, const void* pData) GBL_NOEXCEPT;
122GBL_EXPORT void* GblArrayDeque_emplaceBack (GBL_SELF) GBL_NOEXCEPT;
123GBL_EXPORT GBL_RESULT GblArrayDeque_pushFront (GBL_SELF, const void* pData) GBL_NOEXCEPT;
124GBL_EXPORT void* GblArrayDeque_emplaceFront (GBL_SELF) GBL_NOEXCEPT;
125
126GBL_EXPORT void* GblArrayDeque_popBack (GBL_SELF) GBL_NOEXCEPT;
127GBL_EXPORT void* GblArrayDeque_popFront (GBL_SELF) GBL_NOEXCEPT;
128
129GBL_EXPORT void* GblArrayDeque_insert (GBL_SELF, size_t pos, const void* pData, size_t count) GBL_NOEXCEPT;
130GBL_EXPORT void* GblArrayDeque_emplace (GBL_SELF, size_t pos) GBL_NOEXCEPT;
131GBL_EXPORT GBL_RESULT GblArrayDeque_erase (GBL_SELF, size_t pos, size_t count ) GBL_NOEXCEPT;
132
133GBL_EXPORT void GblArrayDeque_clear (GBL_SELF) GBL_NOEXCEPT;
134GBL_EXPORT GBL_RESULT GblArrayDeque_reserve (GBL_SELF, size_t capacity) GBL_NOEXCEPT;
135GBL_EXPORT GBL_RESULT GblArrayDeque_resize (GBL_SELF, size_t size) GBL_NOEXCEPT;
136GBL_EXPORT GBL_RESULT GblArrayDeque_shrinkToFit (GBL_SELF) GBL_NOEXCEPT;
137
139
140//! \cond
141#define GblArrayDeque_construct(...)
142 GblArrayDeque_constructDefault_(__VA_ARGS__)
143#define GblArrayDeque_constructDefault_(...)
144 GblArrayDeque_constructDefault__(__VA_ARGS__, 0, 0, GBL_NULL, GBL_NULL)
145#define GblArrayDeque_constructDefault__(self, elem, cap, size, data, ctx, ...)
146 (GblArrayDeque_construct)(self, elem, cap, size, data, ctx)
147
148#define GblArrayDeque_insert(...)
149 GblArrayDeque_insertDefault_(__VA_ARGS__)
150#define GblArrayDeque_insertDefault_(...)
151 GblArrayDeque_insertDefault__(__VA_ARGS__, 1)
152#define GblArrayDeque_insertDefault__(self, pos, data, count, ...)
153 (GblArrayDeque_insert(self, pos, data, count))
154
155#define GblArrayDeque_erase(...)
156 GblArrayDeque_eraseDefault_(__VA_ARGS__)
157#define GblArrayDeque_eraseDefault_(...)
158 GblArrayDeque_eraseDefault__(__VA_ARGS__, 1)
159#define GblArrayDeque_eraseDefault__(self, pos, count, ...)
160 ((GblArrayDeque_erase)(self, pos, count))
161//! \endcond
162
163#undef GBL_SELF_TYPE
164
165#endif // GIMBAL_ARRAY_DEQUE_H
#define GBL_NULL
#define GBL_NOEXCEPT
#define GBL_DECLS_BEGIN
#define GBL_PRIVATE_BEGIN
#define GBL_EXPORT
#define GBL_PRIVATE_END
Private data structure.
uint8_t GblBool
Basic boolean type, standardized to sizeof(char)
Circular array-based double-ended queue container.