20 #include <winpr/config.h>
22 #include <winpr/crt.h>
23 #include <winpr/sysinfo.h>
24 #include <winpr/assert.h>
26 #include <winpr/collections.h>
28 struct s_wMessageQueue
51 wObject* MessageQueue_Object(wMessageQueue* queue)
54 return &queue->object;
61 HANDLE MessageQueue_Event(wMessageQueue* queue)
71 size_t MessageQueue_Size(wMessageQueue* queue)
74 EnterCriticalSection(&queue->lock);
75 const size_t ret = queue->size;
76 LeaveCriticalSection(&queue->lock);
84 BOOL MessageQueue_Wait(wMessageQueue* queue)
89 if (WaitForSingleObject(queue->event, INFINITE) == WAIT_OBJECT_0)
95 static BOOL MessageQueue_EnsureCapacity(wMessageQueue* queue,
size_t count)
99 if (queue->size + count >= queue->capacity)
101 wMessage* new_arr = NULL;
102 size_t old_capacity = queue->capacity;
103 size_t new_capacity = queue->capacity * 2;
105 if (new_capacity < queue->size + count)
106 new_capacity = queue->size + count;
108 new_arr = (wMessage*)realloc(queue->array,
sizeof(wMessage) * new_capacity);
111 queue->array = new_arr;
112 queue->capacity = new_capacity;
113 ZeroMemory(&(queue->array[old_capacity]), (new_capacity - old_capacity) *
sizeof(wMessage));
116 if (queue->tail <= queue->head)
118 CopyMemory(&(queue->array[old_capacity]), queue->array, queue->tail *
sizeof(wMessage));
119 queue->tail += old_capacity;
126 BOOL MessageQueue_Dispatch(wMessageQueue* queue,
const wMessage* message)
128 wMessage* dst = NULL;
136 EnterCriticalSection(&queue->lock);
141 if (!MessageQueue_EnsureCapacity(queue, 1))
144 dst = &(queue->array[queue->tail]);
146 dst->time = GetTickCount64();
148 queue->tail = (queue->tail + 1) % queue->capacity;
152 (void)SetEvent(queue->event);
154 if (message->id == WMQ_QUIT)
155 queue->closed = TRUE;
159 LeaveCriticalSection(&queue->lock);
163 BOOL MessageQueue_Post(wMessageQueue* queue,
void* context, UINT32 type,
void* wParam,
void* lParam)
165 wMessage message = { 0 };
167 message.context = context;
169 message.wParam = wParam;
170 message.lParam = lParam;
173 return MessageQueue_Dispatch(queue, &message);
176 BOOL MessageQueue_PostQuit(wMessageQueue* queue,
int nExitCode)
178 return MessageQueue_Post(queue, NULL, WMQ_QUIT, (
void*)(
size_t)nExitCode, NULL);
181 int MessageQueue_Get(wMessageQueue* queue, wMessage* message)
185 if (!MessageQueue_Wait(queue))
188 EnterCriticalSection(&queue->lock);
192 CopyMemory(message, &(queue->array[queue->head]),
sizeof(wMessage));
193 ZeroMemory(&(queue->array[queue->head]),
sizeof(wMessage));
194 queue->head = (queue->head + 1) % queue->capacity;
198 (void)ResetEvent(queue->event);
200 status = (message->id != WMQ_QUIT) ? 1 : 0;
203 LeaveCriticalSection(&queue->lock);
208 int MessageQueue_Peek(wMessageQueue* queue, wMessage* message, BOOL remove)
213 EnterCriticalSection(&queue->lock);
217 CopyMemory(message, &(queue->array[queue->head]),
sizeof(wMessage));
222 ZeroMemory(&(queue->array[queue->head]),
sizeof(wMessage));
223 queue->head = (queue->head + 1) % queue->capacity;
227 (void)ResetEvent(queue->event);
231 LeaveCriticalSection(&queue->lock);
240 wMessageQueue* MessageQueue_New(
const wObject* callback)
242 wMessageQueue* queue = NULL;
244 queue = (wMessageQueue*)calloc(1,
sizeof(wMessageQueue));
248 if (!InitializeCriticalSectionAndSpinCount(&queue->lock, 4000))
251 if (!MessageQueue_EnsureCapacity(queue, 32))
254 queue->event = CreateEvent(NULL, TRUE, FALSE, NULL);
259 queue->object = *callback;
264 WINPR_PRAGMA_DIAG_PUSH
265 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
266 MessageQueue_Free(queue);
267 WINPR_PRAGMA_DIAG_POP
271 void MessageQueue_Free(wMessageQueue* queue)
277 MessageQueue_Clear(queue);
279 (void)CloseHandle(queue->event);
280 DeleteCriticalSection(&queue->lock);
286 int MessageQueue_Clear(wMessageQueue* queue)
291 WINPR_ASSERT(queue->event);
293 EnterCriticalSection(&queue->lock);
295 while (queue->size > 0)
297 wMessage* msg = &(queue->array[queue->head]);
300 if (queue->object.fnObjectUninit)
301 queue->object.fnObjectUninit(msg);
302 if (queue->object.fnObjectFree)
303 queue->object.fnObjectFree(msg);
305 ZeroMemory(msg,
sizeof(wMessage));
307 queue->head = (queue->head + 1) % queue->capacity;
310 (void)ResetEvent(queue->event);
311 queue->closed = FALSE;
313 LeaveCriticalSection(&queue->lock);
This struct contains function pointer to initialize/free objects.