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 const BOOL signalSet = queue->size == 0;
222 queue->size++;
223
224 if (signalSet)
225 (void)SetEvent(queue->event);
226out:
227
228 Queue_Unlock(queue);
229
230 return ret;
231}
232
237void* Queue_Dequeue(wQueue* queue)
238{
239 void* obj = NULL;
240
241 Queue_Lock(queue);
242
243 if (queue->size > 0)
244 {
245 obj = queue->array[queue->head];
246 queue->array[queue->head] = NULL;
247 queue->head = (queue->head + 1) % queue->capacity;
248 queue->size--;
249 }
250
251 if (queue->size < 1)
252 (void)ResetEvent(queue->event);
253
254 Queue_Unlock(queue);
255
256 return obj;
257}
258
263void* Queue_Peek(wQueue* queue)
264{
265 void* obj = NULL;
266
267 Queue_Lock(queue);
268
269 if (queue->size > 0)
270 obj = queue->array[queue->head];
271
272 Queue_Unlock(queue);
273
274 return obj;
275}
276
277void Queue_Discard(wQueue* queue)
278{
279 void* obj = NULL;
280
281 Queue_Lock(queue);
282 obj = Queue_Dequeue(queue);
283
284 if (queue->object.fnObjectFree)
285 queue->object.fnObjectFree(obj);
286 Queue_Unlock(queue);
287}
288
289static BOOL default_queue_equals(const void* obj1, const void* obj2)
290{
291 return (obj1 == obj2);
292}
293
298wQueue* Queue_New(BOOL synchronized, SSIZE_T capacity, SSIZE_T growthFactor)
299{
300 wObject* obj = NULL;
301 wQueue* queue = NULL;
302 queue = (wQueue*)calloc(1, sizeof(wQueue));
303
304 if (!queue)
305 return NULL;
306
307 queue->synchronized = synchronized;
308
309 queue->growthFactor = 2;
310 if (growthFactor > 0)
311 queue->growthFactor = (size_t)growthFactor;
312
313 if (capacity <= 0)
314 capacity = 32;
315 if (!InitializeCriticalSectionAndSpinCount(&queue->lock, 4000))
316 goto fail;
317 queue->haveLock = TRUE;
318 if (!Queue_EnsureCapacity(queue, (size_t)capacity))
319 goto fail;
320
321 queue->event = CreateEvent(NULL, TRUE, FALSE, NULL);
322
323 if (!queue->event)
324 goto fail;
325
326 obj = Queue_Object(queue);
327 obj->fnObjectEquals = default_queue_equals;
328
329 return queue;
330fail:
331 WINPR_PRAGMA_DIAG_PUSH
332 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
333 Queue_Free(queue);
334 WINPR_PRAGMA_DIAG_POP
335 return NULL;
336}
337
338void Queue_Free(wQueue* queue)
339{
340 if (!queue)
341 return;
342
343 if (queue->haveLock)
344 {
345 Queue_Clear(queue);
346 DeleteCriticalSection(&queue->lock);
347 }
348 (void)CloseHandle(queue->event);
349 free((void*)queue->array);
350 free(queue);
351}
This struct contains function pointer to initialize/free objects.
Definition collections.h:57