24 #include "syncml_internals.h" 25 #include "sml_queue_internals.h" 26 #include "sml_error_internals.h" 28 #ifndef DOXYGEN_SHOULD_SKIP_THIS 30 static gboolean _queue_prepare(GSource *source, gint *timeout_)
32 smlTrace(TRACE_INTERNAL,
"%s(%p, %p)", __func__, source, timeout_);
41 smlAssert(queue->
head);
44 smlAssert(queue->
head);
47 smlAssert(queue->tail);
50 if (g_list_length(queue->
head) == 1) {
51 smlAssert(queue->tail == queue->
head);
54 smlAssert(g_list_last(queue->
head) == queue->tail);
57 static gboolean _queue_check(GSource *source)
60 return smlQueueCheck(queue);
63 static gboolean _queue_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
65 smlTrace(TRACE_INTERNAL,
"%s(%p, %p, %p)", __func__, source, callback, user_data);
69 while (smlQueueCheck(queue))
70 smlQueueDispatch(queue);
88 if (!g_thread_supported ()) g_thread_init (NULL);
90 queue->mutex = g_mutex_new();
98 smlQueueDetach(queue);
101 g_list_free(queue->
head);
103 g_mutex_free(queue->mutex);
105 smlSafeFree((gpointer *)&queue);
110 g_mutex_lock(queue->mutex);
112 smlQueueAssert(queue);
115 g_list_free(queue->
head);
119 smlQueueAssert(queue);
121 g_mutex_unlock(queue->mutex);
124 SmlBool smlQueueCheckPrio(
SmlQueue *queue)
126 g_mutex_lock(queue->mutex);
127 SmlBool ret = (queue->prio == NULL) ? FALSE : TRUE;
128 g_mutex_unlock(queue->mutex);
133 SmlBool smlQueueCheck(
SmlQueue *queue)
135 g_mutex_lock(queue->mutex);
136 SmlBool ret = (queue->
head == NULL) ? FALSE : TRUE;
137 g_mutex_unlock(queue->mutex);
142 unsigned int smlQueueLength(
SmlQueue *queue)
144 g_mutex_lock(queue->mutex);
145 unsigned int ret = g_list_length(queue->
head);
146 g_mutex_unlock(queue->mutex);
151 unsigned int smlQueueLengthPrio(
SmlQueue *queue)
153 g_mutex_lock(queue->mutex);
154 unsigned int ret = g_list_length(queue->prio);
155 g_mutex_unlock(queue->mutex);
160 void *smlQueueTryPop(
SmlQueue *queue)
163 void *message = NULL;
165 g_mutex_lock(queue->mutex);
167 smlQueueAssert(queue);
170 message = queue->
head->data;
171 if (queue->
head == queue->tail)
173 if (queue->prio && message == queue->prio->data)
174 queue->prio = g_list_delete_link(queue->prio, queue->prio);
175 queue->
head = g_list_delete_link(queue->
head, queue->
head);
178 smlQueueAssert(queue);
180 g_mutex_unlock(queue->mutex);
185 void *smlQueueTryPopPrio(
SmlQueue *queue)
188 void *message = NULL;
190 g_mutex_lock(queue->mutex);
192 smlQueueAssert(queue);
194 message = queue->prio ? queue->prio->data : NULL;
195 queue->prio = g_list_delete_link(queue->prio, queue->prio);
198 queue->
head = g_list_remove(queue->
head, message);
199 queue->tail = g_list_last(queue->
head);
202 smlQueueAssert(queue);
204 g_mutex_unlock(queue->mutex);
212 g_mutex_lock(queue->mutex);
215 void smlQueueUnlock(
SmlQueue *queue)
218 g_mutex_unlock(queue->mutex);
224 return queue->
head ? queue->
head->data : NULL;
227 void *smlQueuePeekPrio(
SmlQueue *queue)
230 void *message = NULL;
232 g_mutex_lock(queue->mutex);
234 message = queue->prio ? queue->prio->data : NULL;
236 smlQueueAssert(queue);
238 g_mutex_unlock(queue->mutex);
247 g_mutex_lock(queue->mutex);
249 GString *info = g_string_new(
"Contents of queue ");
250 g_string_append_printf(info,
"%p:", queue);
253 for (m = queue->
head; m; m = m->next) {
254 g_string_append_printf(info,
", %p (list %p)", m->data, m);
256 smlTrace(TRACE_INTERNAL,
"%s: %s", __func__, VA_STRING(info->str));
257 g_string_free(info, TRUE);
259 info = g_string_new(
"Contents of prio queue:");
260 for (m = queue->prio; m; m = m->next) {
261 g_string_append_printf(info,
", %p (list %p)", m->data, m);
263 smlTrace(TRACE_INTERNAL,
"%s: %s", __func__, VA_STRING(info->str));
264 g_string_free(info, TRUE);
265 smlTrace(TRACE_INTERNAL,
"%s: Tail of queue: %p (list %p)", __func__, queue->tail ? queue->tail->data : NULL, queue->tail);
267 g_mutex_unlock(queue->mutex);
270 GList *smlQueuePeekNext(
SmlQueue *queue, GList *prev)
280 void smlQueuePushHeadPrio(
SmlQueue *queue,
void *data)
285 g_mutex_lock(queue->mutex);
287 smlQueueAssert(queue);
289 queue->
head = g_list_prepend(queue->
head, data);
291 queue->tail = queue->
head;
292 queue->prio = g_list_prepend(queue->prio, data);
294 smlQueueAssert(queue);
296 g_mutex_unlock(queue->mutex);
299 void smlQueuePushHead(
SmlQueue *queue,
void *data)
304 g_mutex_lock(queue->mutex);
306 smlQueueAssert(queue);
308 queue->
head = g_list_prepend(queue->
head, data);
310 queue->tail = queue->
head;
312 smlQueueAssert(queue);
314 g_mutex_unlock(queue->mutex);
328 g_mutex_lock(queue->mutex);
330 smlQueueAssert(queue);
333 queue->tail = g_list_append(queue->tail, data);
334 queue->tail = queue->tail->next;
336 queue->
head = g_list_append(queue->
head, data);
337 queue->tail = queue->
head;
339 queue->prio = g_list_append(queue->prio, data);
341 smlQueueAssert(queue);
343 g_mutex_unlock(queue->mutex);
358 g_mutex_lock(queue->mutex);
360 smlQueueAssert(queue);
363 queue->tail = g_list_append(queue->tail, data);
364 queue->tail = queue->tail->next;
366 queue->
head = g_list_append(queue->
head, data);
367 queue->tail = queue->
head;
370 smlQueueAssert(queue);
372 g_mutex_unlock(queue->mutex);
402 smlTrace(TRACE_ENTRY,
"%s(%p, %p)", __func__, queue, context);
405 smlAssert(queue->
source == NULL);
407 GSourceFuncs *functions = g_malloc0(
sizeof(GSourceFuncs));
408 functions->prepare = _queue_prepare;
409 functions->check = _queue_check;
410 functions->dispatch = _queue_dispatch;
411 functions->finalize = NULL;
413 GSource *source = g_source_new(functions,
sizeof(GSource) +
sizeof(
SmlQueue *));
416 g_source_set_callback(source, NULL, queue, NULL);
418 queue->functions = functions;
419 g_source_attach(source, context);
422 g_main_context_ref(context);
424 smlTrace(TRACE_EXIT,
"%s", __func__);
427 void smlQueueDetach(
SmlQueue *queue)
429 smlTrace(TRACE_ENTRY,
"%s(%p)", __func__, queue);
434 g_source_destroy(queue->
source);
435 g_source_unref(queue->
source);
437 smlSafeFree((gpointer *)&(queue->functions));
442 g_main_context_unref(queue->
context);
446 smlTrace(TRACE_EXIT,
"%s", __func__);
449 SmlBool smlQueueIsAttached(
SmlQueue *queue)
451 return queue->
source ? TRUE : FALSE;
454 void smlQueueDispatch(
SmlQueue *queue)
456 void *message = smlQueueTryPop(queue);
461 void smlQueueDispatchPrio(
SmlQueue *queue)
464 void *message = smlQueueTryPopPrio(queue);
void smlQueueSend(SmlQueue *queue, void *data)
Sends a message down a queue.
void smlQueueSetHandler(SmlQueue *queue, SmlQueueHandler handler, void *userdata)
Sets the message handler for a queue.
SmlQueue * smlQueueNew(SmlError **error)
Creates a new asynchronous queue.
Represents a Queue which can be used to receive messages.
void smlTrace(SmlTraceType type, const char *message,...)
Used for tracing the application.
void smlQueueAttach(SmlQueue *queue, GMainContext *context)
Sets the queue to use the gmainloop with the given context.
void * smlTryMalloc0(long n_bytes, SmlError **error)
Safely mallocs.
void smlQueueSendPrio(SmlQueue *queue, void *data)
Sends a message down a queue.