+++ /dev/null
-/*
-
- silcthreadqueue.c
-
- Author: Pekka Riikonen <priikone@silcnet.org>
-
- Copyright (C) 2008 Pekka Riikonen
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
-*/
-
-#include "silcruntime.h"
-
-/************************** Types and definitions ***************************/
-
-/* Thread queue context */
-struct SilcThreadQueueStruct {
- SilcDList queue; /* The queue */
- SilcMutex lock; /* Queue lock */
- SilcCond cond; /* Condition for waiting */
- SilcAtomic32 connected; /* Number of connected threads */
-};
-
-/************************** SILC Thread Queue API ***************************/
-
-/* Allocate thread queue */
-
-SilcThreadQueue silc_thread_queue_alloc(void)
-{
- SilcThreadQueue queue;
-
- queue = silc_calloc(1, sizeof(*queue));
- if (!queue)
- return NULL;
-
- SILC_LOG_DEBUG(("Allocated thread queue %p", queue));
-
- if (!silc_mutex_alloc(&queue->lock)) {
- silc_free(queue);
- return NULL;
- }
-
- if (!silc_cond_alloc(&queue->cond)) {
- silc_mutex_free(queue->lock);
- silc_free(queue);
- return NULL;
- }
-
- queue->queue = silc_dlist_init();
- if (!queue->queue) {
- silc_cond_free(queue->cond);
- silc_mutex_free(queue->lock);
- silc_free(queue);
- return NULL;
- }
-
- silc_atomic_init32(&queue->connected, 1);
-
- return queue;
-}
-
-/* Connect current thread to queue */
-
-void silc_thread_queue_connect(SilcThreadQueue queue)
-{
- silc_atomic_add_int32(&queue->connected, 1);
-}
-
-/* Disconnect current thread from queue */
-
-void silc_thread_queue_disconnect(SilcThreadQueue queue)
-{
- if (silc_atomic_sub_int32(&queue->connected, 1) > 0)
- return;
-
- /* Free queue */
- SILC_LOG_DEBUG(("Free thread queue %p", queue));
- silc_cond_free(queue->cond);
- silc_mutex_free(queue->lock);
- silc_dlist_uninit(queue->queue);
- silc_atomic_uninit32(&queue->connected);
- silc_free(queue);
-}
-
-/* Push data to queue */
-
-void silc_thread_queue_push(SilcThreadQueue queue, void *data)
-{
- if (silc_unlikely(!data))
- return;
-
- SILC_LOG_DEBUG(("Push data %p to thread queue %p", data, queue));
-
- silc_mutex_lock(queue->lock);
- silc_dlist_start(queue->queue);
- silc_dlist_insert(queue->queue, data);
- silc_cond_broadcast(queue->cond);
- silc_mutex_unlock(queue->lock);
-}
-
-/* Get data or wait if wanted or return NULL. */
-
-void *silc_thread_queue_pop(SilcThreadQueue queue, SilcBool block)
-{
- void *data;
-
- if (block)
- return silc_thread_queue_timed_pop(queue, 0);
-
- silc_mutex_lock(queue->lock);
-
- silc_dlist_start(queue->queue);
- data = silc_dlist_get(queue->queue);
- if (data)
- silc_dlist_del(queue->queue, data);
-
- SILC_LOG_DEBUG(("Pop data %p from thread queue %p", data, queue));
-
- silc_mutex_unlock(queue->lock);
-
- return data;
-}
-
-/* Get data or wait for a while */
-
-void *silc_thread_queue_timed_pop(SilcThreadQueue queue,
- int timeout_msec)
-{
- void *data;
-
- silc_mutex_lock(queue->lock);
-
- silc_dlist_start(queue->queue);
- while ((data = silc_dlist_get(queue->queue)) == SILC_LIST_END) {
- if (!silc_cond_timedwait(queue->cond, queue->lock, timeout_msec))
- break;
- silc_dlist_start(queue->queue);
- }
-
- if (data)
- silc_dlist_del(queue->queue, data);
-
- SILC_LOG_DEBUG(("Pop data %p from thread queue %p", data, queue));
-
- silc_mutex_unlock(queue->lock);
-
- return data;
-}
-
-/* Pop entire queue */
-
-SilcDList silc_thread_queue_pop_list(SilcThreadQueue queue, SilcBool block)
-{
- SilcDList list;
-
- silc_mutex_lock(queue->lock);
-
- if (block)
- while (silc_dlist_count(queue->queue) == 0)
- silc_cond_wait(queue->cond, queue->lock);
-
- list = queue->queue;
- queue->queue = silc_dlist_init();
-
- silc_mutex_unlock(queue->lock);
-
- silc_dlist_start(list);
-
- return list;
-}