FreeRDP
Loading...
Searching...
No Matches
Queue.c
1
20#include <winpr/config.h>
21
22#include <winpr/crt.h>
23#include <winpr/assert.h>
24
25#include <winpr/collections.h>
26
27struct s_wQueue
28{
29 size_t capacity;
30 size_t growthFactor;
31 BOOL synchronized;
32
33 BYTE padding[4];
34
35 size_t head;
36 size_t tail;
37 size_t size;
38 void** array;
40 HANDLE event;
41
42 wObject object;
43 BOOL haveLock;
44
45 BYTE padding2[4];
46};
47
61size_t Queue_Count(wQueue* queue)
62{
63 size_t ret = 0;
64
65 Queue_Lock(queue);
66
67 ret = queue->size;
68
69 Queue_Unlock(queue);
70
71 return ret;
72}
73
78void Queue_Lock(wQueue* queue)
79{
80 WINPR_ASSERT(queue);
81 if (queue->synchronized)
82 EnterCriticalSection(&queue->lock);
83}
84
89void Queue_Unlock(wQueue* queue)
90{
91 WINPR_ASSERT(queue);
92 if (queue->synchronized)
93 LeaveCriticalSection(&queue->lock);
94}
95
100HANDLE Queue_Event(wQueue* queue)
101{
102 WINPR_ASSERT(queue);
103 return queue->event;
104}
105
106wObject* Queue_Object(wQueue* queue)
107{
108 WINPR_ASSERT(queue);
109 return &queue->object;
110}
111
120void Queue_Clear(wQueue* queue)
121{
122 Queue_Lock(queue);
123
124 for (size_t index = queue->head; index != queue->tail; index = (index + 1) % queue->capacity)
125 {
126 if (queue->object.fnObjectFree)
127 queue->object.fnObjectFree(queue->array[index]);
128
129 queue->array[index] = NULL;
130 }
131
132 queue->size = 0;
133 queue->head = queue->tail = 0;
134 (void)ResetEvent(queue->event);
135 Queue_Unlock(queue);
136}
137
142BOOL Queue_Contains(wQueue* queue, const void* obj)
143{
144 BOOL found = FALSE;
145
146 Queue_Lock(queue);
147
148 for (size_t index = 0; index < queue->tail; index++)
149 {
150 if (queue->object.fnObjectEquals(queue->array[index], obj))
151 {
152 found = TRUE;
153 break;
154 }
155 }
156
157 Queue_Unlock(queue);
158
159 return found;
160}
161
162static BOOL Queue_EnsureCapacity(wQueue* queue, size_t count)
163{
164 WINPR_ASSERT(queue);
165
166 if (queue->size + count >= queue->capacity)
167 {
168 const size_t old_capacity = queue->capacity;
169 size_t new_capacity = queue->capacity * queue->growthFactor;
170 void** newArray = NULL;
171 if (new_capacity < queue->size + count)
172 new_capacity = queue->size + count;
173 newArray = (void**)realloc((void*)queue->array, sizeof(void*) * new_capacity);
174
175 if (!newArray)
176 return FALSE;
177
178 queue->capacity = new_capacity;
179 queue->array = newArray;
180 ZeroMemory((void*)&(queue->array[old_capacity]),
181 (new_capacity - old_capacity) * sizeof(void*));
182
183 /* rearrange wrapped entries */
184 if (queue->tail <= queue->head)
185 {
186 CopyMemory((void*)&(queue->array[old_capacity]), (void*)queue->array,
187 queue->tail * sizeof(void*));
188 queue->tail += old_capacity;
189 }
190 }
191 return TRUE;
192}
193
198BOOL Queue_Enqueue(wQueue* queue, const void* obj)
199{
200 BOOL ret = TRUE;
201
202 Queue_Lock(queue);
203
204 if (!Queue_EnsureCapacity(queue, 1))
205 goto out;
206
207 if (queue->object.fnObjectNew)
208 queue->array[queue->tail] = queue->object.fnObjectNew(obj);
209 else
210 {
211 union
212 {
213 const void* cv;
214 void* v;
215 } cnv;
216 cnv.cv = obj;
217 queue->array[queue->tail] = cnv.v;
218 }
219 queue->tail = (queue->tail + 1) % queue->capacity;
220
221 {
222 const BOOL signalSet = queue->size == 0;
223 queue->size++;
224
225 if (signalSet)
226 (void)SetEvent(queue->event);
227 }
228out:
229
230 Queue_Unlock(queue);
231
232 return ret;
233}
234
239void* Queue_Dequeue(wQueue* queue)
240{
241 void* obj = NULL;
242
243 Queue_Lock(queue);
244
245 if (queue->size > 0)
246 {
247 obj = queue->array[queue->head];
248 queue->array[queue->head] = NULL;
249 queue->head = (queue->head + 1) % queue->capacity;
250 queue->size--;
251 }
252
253 if (queue->size < 1)
254 (void)ResetEvent(queue->event);
255
256 Queue_Unlock(queue);
257
258 return obj;
259}
260
265void* Queue_Peek(wQueue* queue)
266{
267 void* obj = NULL;
268
269 Queue_Lock(queue);
270
271 if (queue->size > 0)
272 obj = queue->array[queue->head];
273
274 Queue_Unlock(queue);
275
276 return obj;
277}
278
279void Queue_Discard(wQueue* queue)
280{
281 void* obj = NULL;
282
283 Queue_Lock(queue);
284 obj = Queue_Dequeue(queue);
285
286 if (queue->object.fnObjectFree)
287 queue->object.fnObjectFree(obj);
288 Queue_Unlock(queue);
289}
290
291static BOOL default_queue_equals(const void* obj1, const void* obj2)
292{
293 return (obj1 == obj2);
294}
295
300wQueue* Queue_New(BOOL synchronized, SSIZE_T capacity, SSIZE_T growthFactor)
301{
302 wObject* obj = NULL;
303 wQueue* queue = NULL;
304 queue = (wQueue*)calloc(1, sizeof(wQueue));
305
306 if (!queue)
307 return NULL;
308
309 queue->synchronized = synchronized;
310
311 queue->growthFactor = 2;
312 if (growthFactor > 0)
313 queue->growthFactor = (size_t)growthFactor;
314
315 if (capacity <= 0)
316 capacity = 32;
317 if (!InitializeCriticalSectionAndSpinCount(&queue->lock, 4000))
318 goto fail;
319 queue->haveLock = TRUE;
320 if (!Queue_EnsureCapacity(queue, (size_t)capacity))
321 goto fail;
322
323 queue->event = CreateEvent(NULL, TRUE, FALSE, NULL);
324
325 if (!queue->event)
326 goto fail;
327
328 obj = Queue_Object(queue);
329 obj->fnObjectEquals = default_queue_equals;
330
331 return queue;
332fail:
333 WINPR_PRAGMA_DIAG_PUSH
334 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
335 Queue_Free(queue);
336 WINPR_PRAGMA_DIAG_POP
337 return NULL;
338}
339
340void Queue_Free(wQueue* queue)
341{
342 if (!queue)
343 return;
344
345 if (queue->haveLock)
346 {
347 Queue_Clear(queue);
348 DeleteCriticalSection(&queue->lock);
349 }
350 (void)CloseHandle(queue->event);
351 free((void*)queue->array);
352 free(queue);
353}
This struct contains function pointer to initialize/free objects.
Definition collections.h:57