All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
as_queue.h
Go to the documentation of this file.
1 /*
2  * Copyright 2008-2019 Aerospike, Inc.
3  *
4  * Portions may be licensed to Aerospike, Inc. under one or more contributor
5  * license agreements.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8  * use this file except in compliance with the License. You may obtain a copy of
9  * the License at http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14  * License for the specific language governing permissions and limitations under
15  * the License.
16  */
17 #pragma once
18 
19 #include <aerospike/as_std.h>
20 #include <string.h>
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 /******************************************************************************
27  * TYPES
28  ******************************************************************************/
29 
30 /**
31  * A fast, non-thread-safe dynamic queue implementation.
32  * as_queue is not part of the generic as_val family.
33  */
34 typedef struct as_queue_s {
35  /**
36  * The block of items in the queue.
37  */
38  uint8_t* data;
39 
40  /**
41  * The total number of items allocated.
42  */
43  uint32_t capacity;
44 
45  /**
46  * Item offset of head.
47  */
48  uint32_t head;
49 
50  /**
51  * Item offset of tail.
52  */
53  uint32_t tail;
54 
55  /**
56  * The size of a single item.
57  */
58  uint32_t item_size;
59 
60  /**
61  * Total items used which includes items in queue and items popped from queue.
62  */
63  uint32_t total;
64 
65  /**
66  * Internal queue flags.
67  */
68  uint32_t flags;
69 } as_queue;
70 
71 /******************************************************************************
72  * MACROS
73  ******************************************************************************/
74 
75 /**
76  * Initialize a stack allocated as_queue, with item storage on the stack.
77  * as_queue_inita() will transfer stack memory to the heap if a resize is
78  * required.
79  */
80 #define as_queue_inita(__q, __item_size, __capacity)\
81 (__q)->data = alloca((__capacity) * (__item_size));\
82 (__q)->capacity = __capacity;\
83 (__q)->head = (__q)->tail = 0;\
84 (__q)->item_size = __item_size;\
85 (__q)->total = 0;\
86 (__q)->flags = 0;
87 
88 /******************************************************************************
89  * FUNCTIONS
90  ******************************************************************************/
91 
92 /**
93  * Initialize a stack allocated as_queue, with item storage on the heap.
94  */
95 AS_EXTERN bool
96 as_queue_init(as_queue* queue, uint32_t item_size, uint32_t capacity);
97 
98 /**
99  * Create a heap allocated as_queue, with item storage on the heap.
100  */
102 as_queue_create(uint32_t item_size, uint32_t capacity);
103 
104 /**
105  * Release queue memory.
106  */
107 AS_EXTERN void
108 as_queue_destroy(as_queue* queue);
109 
110 /**
111  * Get the number of items currently in the queue.
112  */
113 static inline uint32_t
115 {
116  return queue->tail - queue->head;
117 }
118 
119 /**
120  * Is queue empty?
121  */
122 static inline bool
124 {
125  return queue->tail == queue->head;
126 }
127 
128 /**
129  * Push item to the tail of the queue.
130  */
131 AS_EXTERN bool
132 as_queue_push(as_queue* queue, const void* ptr);
133 
134 /**
135  * Push item to the tail of the queue only if size < capacity.
136  */
137 AS_EXTERN bool
138 as_queue_push_limit(as_queue* queue, const void* ptr);
139 
140 /**
141  * Push item to the head of the queue.
142  */
143 AS_EXTERN bool
144 as_queue_push_head(as_queue* queue, const void* ptr);
145 
146 /**
147  * Push item to the head of the queue only if size < capacity.
148  */
149 AS_EXTERN bool
150 as_queue_push_head_limit(as_queue* queue, const void* ptr);
151 
152 /**
153  * Get item at virtual index. For internal use only.
154  */
155 static inline void*
156 as_queue_get(as_queue* queue, uint32_t index)
157 {
158  return &queue->data[(index % queue->capacity) * queue->item_size];
159 }
160 
161 /**
162  * Pop item from the head of the queue.
163  */
164 static inline bool
165 as_queue_pop(as_queue* queue, void* ptr)
166 {
167  if (as_queue_empty(queue)) {
168  return false;
169  }
170 
171  memcpy(ptr, as_queue_get(queue, queue->head), queue->item_size);
172  queue->head++;
173 
174  // This probably keeps the cache fresher because the queue is fully empty.
175  if (queue->head == queue->tail) {
176  queue->head = queue->tail = 0;
177  }
178  return true;
179 }
180 
181 /**
182  * Pop item from the tail of the queue.
183  */
184 static inline bool
185 as_queue_pop_tail(as_queue* queue, void* ptr)
186 {
187  if (as_queue_empty(queue)) {
188  return false;
189  }
190 
191  queue->tail--;
192  memcpy(ptr, as_queue_get(queue, queue->tail), queue->item_size);
193 
194  if (queue->head == queue->tail) {
195  queue->head = queue->tail = 0;
196  }
197  return true;
198 }
199 
200 /**
201  * Increment total counter if within capacity.
202  */
203 static inline bool
205 {
206  if (queue->total < queue->capacity) {
207  queue->total++;
208  return true;
209  }
210  return false;
211 }
212 
213 /**
214  * Decrement total counter.
215  */
216 static inline void
218 {
219  queue->total--;
220 }
221 
222 #ifdef __cplusplus
223 } // end extern "C"
224 #endif
AS_EXTERN bool as_queue_init(as_queue *queue, uint32_t item_size, uint32_t capacity)
uint32_t tail
Definition: as_queue.h:53
AS_EXTERN bool as_queue_push_head(as_queue *queue, const void *ptr)
AS_EXTERN bool as_queue_push(as_queue *queue, const void *ptr)
#define AS_EXTERN
Definition: as_std.h:25
static bool as_queue_pop(as_queue *queue, void *ptr)
Definition: as_queue.h:165
uint32_t head
Definition: as_queue.h:48
uint8_t * data
Definition: as_queue.h:38
uint32_t item_size
Definition: as_queue.h:58
static void * as_queue_get(as_queue *queue, uint32_t index)
Definition: as_queue.h:156
uint32_t capacity
Definition: as_queue.h:43
static uint32_t as_queue_size(as_queue *queue)
Definition: as_queue.h:114
static bool as_queue_pop_tail(as_queue *queue, void *ptr)
Definition: as_queue.h:185
AS_EXTERN bool as_queue_push_head_limit(as_queue *queue, const void *ptr)
AS_EXTERN bool as_queue_push_limit(as_queue *queue, const void *ptr)
uint32_t total
Definition: as_queue.h:63
uint32_t flags
Definition: as_queue.h:68
static bool as_queue_empty(as_queue *queue)
Definition: as_queue.h:123
static bool as_queue_incr_total(as_queue *queue)
Definition: as_queue.h:204
AS_EXTERN void as_queue_destroy(as_queue *queue)
AS_EXTERN as_queue * as_queue_create(uint32_t item_size, uint32_t capacity)
static void as_queue_decr_total(as_queue *queue)
Definition: as_queue.h:217