@LINK=silchashtable.html:SILC Hash Table Interface
@LINK=silclog.html:SILC Logging Interface
@LINK=silcmemory.html:SILC Memory Interface
-@LINK=silcmutex.html:SILC Mutex Interface
@LINK=silcthread.html:SILC Thread Interface
+@LINK=silcmutex.html:SILC Mutex Interface
+@LINK=silccondvar.html:SILC Conditional Variable Interface
@LINK=silcnet.html:SILC Network Interface
@LINK=silcschedule.html:SILC Schedule Interface
@LINK=silcsockconn.html:SILC Socket Interface
--- /dev/null
+/*
+
+ silccondvar.h
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2006 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.
+
+*/
+
+/****h* silcutil/SILC Conditional Variable Interface
+ *
+ * DESCRIPTION
+ *
+ * A conditional variable interface for multi-thread synchronization.
+ * Conditional variables enable threads to suspend execution and yield
+ * the processors until some predicate on some shared data is satisfied.
+ *
+ ***/
+
+#ifndef SILCCONDVAR_H
+#define SILCCONDVAR_H
+
+/****s* silcutil/SilcCondVarAPI/SilcCondVar
+ *
+ * NAME
+ *
+ * typedef struct SilcCondVarStruct *SilcCondVar;
+ *
+ * DESCRIPTION
+ *
+ * This context is the actual conditional variable and is allocated
+ * by silc_condvar_alloc and given as argument to all silc_condvar_*
+ * functions. It is freed by the silc_condvar_free function.
+ *
+ ***/
+typedef struct SilcCondVarStruct *SilcCondVar;
+
+/****s* silcutil/SilcCondVarAPI/silc_condvar_alloc
+ *
+ * SYNOPSIS
+ *
+ * SilcBool silc_condvar_alloc(SilcCondVar *cond);
+ *
+ * DESCRIPTION
+ *
+ * Allocates SILC Conditional variable context. The conditional must
+ * be allocated before it can be used. It is freed by the
+ * silc_condvar_free function. This returns TRUE and allocated
+ * conditional in to the `cond' pointer and FALSE on error.
+ *
+ ***/
+SilcBool silc_condvar_alloc(SilcCondVar *cond);
+
+/****s* silcutil/SilcCondVarAPI/silc_condvar_free
+ *
+ * SYNOPSIS
+ *
+ * void silc_condvar_free(SilcCondVar cond);
+ *
+ * DESCRIPTION
+ *
+ * Free conditional variable context. If `cond' is NULL this function
+ * has no effect.
+ *
+ ***/
+void silc_condvar_free(SilcCondVar cond);
+
+/****s* silcutil/SilcCondVarAPI/silc_condvar_wait
+ *
+ * SYNOPSIS
+ *
+ * void silc_condvar_wait(SilcCondVar cond, SilcMutex mutex);
+ *
+ * DESCRIPTION
+ *
+ * Waits for conditional variable `cond' to be signalled. This function
+ * will block the calling thread until the conditional variable is
+ * signalled. The `mutex' must be locked before calling this function.
+ * The `mutex' will be unlocked inside this function. After this
+ * function returns the `mutex' is in locked state again.
+ *
+ * EXAMPLE
+ *
+ * silc_mutex_lock(lock);
+ * while (c->a == NULL)
+ * silc_condvar_wait(cond, lock);
+ * ...
+ * silc_mutex_unlock(lock);
+ *
+ ***/
+void silc_condvar_wait(SilcCondVar cond, SilcMutex mutex);
+
+/****s* silcutil/SilcCondVarAPI/silc_condvar_timedwait
+ *
+ * SYNOPSIS
+ *
+ * void silc_condvar_timedwait(SilcCondVar cond, SilcMutex mutex,
+ * struct timespec *timeout);
+ *
+ * DESCRIPTION
+ *
+ * Waits for conditional variable `cond' to be signalled or for the
+ * `timeout' to expire. The timeout is in milliseconds. If it is 0
+ * no timeout exist. Returns FALSE if timeout expired, TRUE when
+ * signalled. This function will block the calling thread until the
+ * conditional variable is signalled. The `mutex' must be locked before
+ * calling this function. The `mutex' will be unlocked inside this
+ * function. After this function returns the `mutex' is in locked
+ * state again.
+ *
+ ***/
+SilcBool silc_condvar_timedwait(SilcCondVar cond, SilcMutex mutex,
+ int timeout);
+
+/****s* silcutil/SilcCondVarAPI/silc_condvar_signal
+ *
+ * SYNOPSIS
+ *
+ * void silc_condvar_signal(SilcCondVar cond);
+ *
+ * DESCRIPTION
+ *
+ * Signals a waiting thread and wakes it up. If there are no waiters
+ * this function has no effect. In case of multiple waiters only one
+ * is signalled. To signal all of them use silc_condvar_broadcast.
+ *
+ * NOTES
+ *
+ * Before calling this function the mutex used with the silc_condvar_wait
+ * must be acquired.
+ *
+ * EXAMPLE
+ *
+ * silc_mutex_lock(lock);
+ * c->a = context;
+ * silc_condvar_signal(cond);
+ * silc_mutex_unlock(lock);
+ *
+ ***/
+void silc_condvar_signal(SilcCondVar cond);
+
+/****s* silcutil/SilcCondVarAPI/silc_condvar_broadcast
+ *
+ * SYNOPSIS
+ *
+ * void silc_condvar_broadcast(SilcCondVar cond);
+ *
+ * DESCRIPTION
+ *
+ * Signals and wakes up all waiters. If there are no waiters this
+ * function has no effect.
+ *
+ * NOTES
+ *
+ * Before calling this function the mutex used with the silc_condvar_wait
+ * must be acquired.
+ *
+ ***/
+void silc_condvar_broadcast(SilcCondVar cond);
+
+#endif /* SILCCONDVAR_H */
#
# Author: Pekka Riikonen <priikone@silcnet.org>
#
-# Copyright (C) 2001 Pekka Riikonen
+# Copyright (C) 2001 - 2006 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
silcunixnet.c \
silcunixutil.c \
silcunixsocketstream.c \
- silcunixmutex.c \
silcunixthread.c
include $(top_srcdir)/Makefile.defines.in
+++ /dev/null
-/*
-
- silcunixmutex.c
-
- Author: Pekka Riikonen <priikone@silcnet.org>
-
- Copyright (C) 2001 - 2005 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.
-
-*/
-/* $Id$ */
-
-#include "silc.h"
-
-/* SILC Mutex structure */
-struct SilcMutexStruct {
-#ifdef SILC_THREADS
- pthread_mutex_t mutex;
-#else
- void *tmp;
-#endif /* SILC_THREADS */
-};
-
-SilcBool silc_mutex_alloc(SilcMutex *mutex)
-{
-#ifdef SILC_THREADS
- *mutex = silc_calloc(1, sizeof(**mutex));
- if (*mutex == NULL)
- return FALSE;
- pthread_mutex_init(&(*mutex)->mutex, NULL);
- return TRUE;
-#else
- return FALSE;
-#endif /* SILC_THREADS */
-}
-
-void silc_mutex_free(SilcMutex mutex)
-{
-#ifdef SILC_THREADS
- if (mutex) {
- pthread_mutex_destroy(&mutex->mutex);
- silc_free(mutex);
- }
-#endif /* SILC_THREADS */
-}
-
-void silc_mutex_lock(SilcMutex mutex)
-{
-#ifdef SILC_THREADS
- if (mutex) {
- if (pthread_mutex_lock(&mutex->mutex))
- assert(FALSE);
- }
-#endif /* SILC_THREADS */
-}
-
-void silc_mutex_unlock(SilcMutex mutex)
-{
-#ifdef SILC_THREADS
- if (mutex) {
- if (pthread_mutex_unlock(&mutex->mutex))
- assert(FALSE);
- }
-#endif /* SILC_THREADS */
-}
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 - 2005 Pekka Riikonen
+ Copyright (C) 2001 - 2006 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
#include "silc.h"
+/**************************** SILC Thread API *******************************/
+
SilcThread silc_thread_create(SilcThreadStart start_func, void *context,
SilcBool waitable)
{
}
if (pthread_attr_setdetachstate(&attr,
- waitable ? PTHREAD_CREATE_JOINABLE :
+ waitable ? PTHREAD_CREATE_JOINABLE :
PTHREAD_CREATE_DETACHED)) {
SILC_LOG_ERROR(("Thread error: %s", strerror(errno)));
pthread_attr_destroy(&attr);
return NULL;
}
- ret = pthread_create(&thread, &attr, (void * (*)(void *))start_func,
+ ret = pthread_create(&thread, &attr, (void * (*)(void *))start_func,
context);
if (ret) {
SILC_LOG_ERROR(("Thread error: %s", strerror(errno)));
return FALSE;
#endif
}
+
+
+/***************************** SILC Mutex API *******************************/
+
+/* SILC Mutex structure */
+struct SilcMutexStruct {
+#ifdef SILC_THREADS
+ pthread_mutex_t mutex;
+#else
+ void *tmp;
+#endif /* SILC_THREADS */
+};
+
+SilcBool silc_mutex_alloc(SilcMutex *mutex)
+{
+#ifdef SILC_THREADS
+ *mutex = silc_calloc(1, sizeof(**mutex));
+ if (*mutex == NULL)
+ return FALSE;
+ pthread_mutex_init(&(*mutex)->mutex, NULL);
+ return TRUE;
+#else
+ return FALSE;
+#endif /* SILC_THREADS */
+}
+
+void silc_mutex_free(SilcMutex mutex)
+{
+#ifdef SILC_THREADS
+ if (mutex) {
+ pthread_mutex_destroy(&mutex->mutex);
+ silc_free(mutex);
+ }
+#endif /* SILC_THREADS */
+}
+
+void silc_mutex_lock(SilcMutex mutex)
+{
+#ifdef SILC_THREADS
+ if (mutex) {
+ if (pthread_mutex_lock(&mutex->mutex))
+ assert(FALSE);
+ }
+#endif /* SILC_THREADS */
+}
+
+void silc_mutex_unlock(SilcMutex mutex)
+{
+#ifdef SILC_THREADS
+ if (mutex) {
+ if (pthread_mutex_unlock(&mutex->mutex))
+ assert(FALSE);
+ }
+#endif /* SILC_THREADS */
+}
+
+
+/**************************** SILC CondVar API ******************************/
+
+/* SILC Conditional Variable context */
+struct SilcCondVarStruct {
+#ifdef SILC_THREADS
+ pthread_cond_t cond;
+#else
+ void *tmp;
+#endif /* SILC_THREADS*/
+};
+
+SilcBool silc_condvar_alloc(SilcCondVar *cond)
+{
+#ifdef SILC_THREADS
+ *cond = silc_calloc(1, sizeof(**cond));
+ if (*cond == NULL)
+ return FALSE;
+ pthread_cond_init(&(*cond)->cond, NULL);
+ return TRUE;
+#else
+ return FALSE;
+#endif /* SILC_THREADS*/
+}
+
+void silc_condvar_free(SilcCondVar cond)
+{
+#ifdef SILC_THREADS
+ pthread_cond_destroy(&cond->cond);
+ silc_free(cond);
+#endif /* SILC_THREADS*/
+}
+
+void silc_condvar_signal(SilcCondVar cond)
+{
+#ifdef SILC_THREADS
+ pthread_cond_signal(&cond->cond);
+#endif /* SILC_THREADS*/
+}
+
+void silc_condvar_broadcast(SilcCondVar cond)
+{
+#ifdef SILC_THREADS
+ pthread_cond_broadcast(&cond->cond);
+#endif /* SILC_THREADS*/
+}
+
+void silc_condvar_wait(SilcCondVar cond, SilcMutex mutex)
+{
+#ifdef SILC_THREADS
+ pthread_cond_wait(&cond->cond, &mutex->mutex);
+#endif /* SILC_THREADS*/
+}
+
+SilcBool silc_condvar_timedwait(SilcCondVar cond, SilcMutex mutex,
+ int timeout)
+{
+#ifdef SILC_THREADS
+ struct timespec t;
+ if (timeout) {
+ t.tv_sec = timeout / 1000;
+ t.tv_nsec = (timeout % 1000) * 1000;
+ return pthread_cond_timedwait(&cond->cond, &mutex->mutex, &t) == 0;
+ }
+
+ return pthread_cond_wait(&cond->cond, &mutex->mutex) == 0;
+#endif /* SILC_THREADS*/
+}
#
# Author: Pekka Riikonen <priikone@silcnet.org>
#
-# Copyright (C) 2001 Pekka Riikonen
+# Copyright (C) 2001 - 2006 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
silcwin32schedule.c \
silcwin32sockconn.c \
silcwin32util.c \
- silcwin32mutex.c \
silcwin32thread.c
include $(top_srcdir)/Makefile.defines.in
+++ /dev/null
-/*
-
- silcwin32mutex.c
-
- Author: Pekka Riikonen <priikone@silcnet.org>
-
- Copyright (C) 2001 - 2005 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.
-
-*/
-/* $Id$ */
-
-#include "silc.h"
-
-/* SILC Mutex structure */
-struct SilcMutexStruct {
-#ifdef SILC_THREADS
- CRITICAL_SECTION mutex;
- BOOL locked;
-#else
- void *tmp;
-#endif /* SILC_THREADS */
-};
-
-SilcBool silc_mutex_alloc(SilcMutex *mutex)
-{
-#ifdef SILC_THREADS
- *mutex = silc_calloc(1, sizeof(**mutex));
- if (!(*mutex))
- return FALSE;
- InitializeCriticalSection(&((*mutex)->mutex));
- return TRUE;
-#else
- return FALSE;
-#endif /* SILC_THREADS */
-}
-
-void silc_mutex_free(SilcMutex mutex)
-{
-#ifdef SILC_THREADS
- if (mutex) {
- DeleteCriticalSection(&mutex->mutex);
- silc_free(mutex);
- }
-#endif /* SILC_THREADS */
-}
-
-void silc_mutex_lock(SilcMutex mutex)
-{
-#ifdef SILC_THREADS
- if (mutex) {
- EnterCriticalSection(&mutex->mutex);
- assert(mutex->locked == FALSE);
- mutex->locked = TRUE;
- }
-#endif /* SILC_THREADS */
-}
-
-void silc_mutex_unlock(SilcMutex mutex)
-{
-#ifdef SILC_THREADS
- if (mutex) {
- assert(mutex->locked == TRUE);
- mutex->locked = FALSE;
- LeaveCriticalSection(&mutex->mutex);
- }
-#endif /* SILC_THREADS */
-}
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 - 2005 Pekka Riikonen
+ Copyright (C) 2001 - 2006 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
#include "silc.h"
+/**************************** SILC Thread API *******************************/
+
#ifdef SILC_THREADS
/* Thread structure for WIN32 */
{
#ifdef SILC_THREADS
SilcWin32Thread thread = TlsGetValue(silc_thread_tls);
-
+
if (thread) {
/* If the thread is waitable the memory is freed only in silc_thread_wait
by another thread. If not waitable, free it now. */
HANDLE handle = GetCurrentThread ();
HANDLE process = GetCurrentProcess ();
self = silc_calloc(1, sizeof(*self));
- DuplicateHandle(process, handle, process,
- &self->thread, 0, FALSE,
+ DuplicateHandle(process, handle, process,
+ &self->thread, 0, FALSE,
DUPLICATE_SAME_ACCESS);
TlsSetValue(silc_thread_tls, self);
}
return FALSE;
#endif
}
+
+
+/***************************** SILC Mutex API *******************************/
+
+/* SILC Mutex structure */
+struct SilcMutexStruct {
+#ifdef SILC_THREADS
+ CRITICAL_SECTION mutex;
+ BOOL locked;
+#else
+ void *tmp;
+#endif /* SILC_THREADS */
+};
+
+SilcBool silc_mutex_alloc(SilcMutex *mutex)
+{
+#ifdef SILC_THREADS
+ *mutex = silc_calloc(1, sizeof(**mutex));
+ if (!(*mutex))
+ return FALSE;
+ InitializeCriticalSection(&((*mutex)->mutex));
+ return TRUE;
+#else
+ return FALSE;
+#endif /* SILC_THREADS */
+}
+
+void silc_mutex_free(SilcMutex mutex)
+{
+#ifdef SILC_THREADS
+ if (mutex) {
+ DeleteCriticalSection(&mutex->mutex);
+ silc_free(mutex);
+ }
+#endif /* SILC_THREADS */
+}
+
+void silc_mutex_lock(SilcMutex mutex)
+{
+#ifdef SILC_THREADS
+ if (mutex) {
+ EnterCriticalSection(&mutex->mutex);
+ assert(mutex->locked == FALSE);
+ mutex->locked = TRUE;
+ }
+#endif /* SILC_THREADS */
+}
+
+void silc_mutex_unlock(SilcMutex mutex)
+{
+#ifdef SILC_THREADS
+ if (mutex) {
+ assert(mutex->locked == TRUE);
+ mutex->locked = FALSE;
+ LeaveCriticalSection(&mutex->mutex);
+ }
+#endif /* SILC_THREADS */
+}
+
+
+/**************************** SILC CondVar API ******************************/
+
+/* SILC Conditional Variable context */
+struct SilcCondVarStruct {
+#ifdef SILC_THREADS
+ HANDLE event;
+#endif /* SILC_THREADS*/
+ unsigned int waiters : 23;
+ unsigned int signal : 1;
+};
+
+SilcBool silc_condvar_alloc(SilcCondVar *cond)
+{
+#ifdef SILC_THREADS
+ *cond = silc_calloc(1, sizeof(**cond));
+ if (*cond == NULL)
+ return FALSE;
+ (*cond)->event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ return TRUE;
+#else
+ return FALSE;
+#endif /* SILC_THREADS*/
+}
+
+void silc_condvar_free(SilcCondVar cond)
+{
+#ifdef SILC_THREADS
+ CloseHandle(cond->event);
+ silc_free(cond);
+#endif /* SILC_THREADS*/
+}
+
+void silc_condvar_signal(SilcCondVar cond)
+{
+#ifdef SILC_THREADS
+ cond->signal = TRUE;
+ SetEvent(cond->event);
+#endif /* SILC_THREADS*/
+}
+
+void silc_condvar_broadcast(SilcCondVar cond)
+{
+#ifdef SILC_THREADS
+ cond->signal = TRUE;
+ SetEvent(cond->event);
+#endif /* SILC_THREADS*/
+}
+
+void silc_condvar_wait(SilcCondVar cond, SilcMutex mutex)
+{
+#ifdef SILC_THREADS
+ silc_condvar_timedwait(cond, mutex, NULL);
+#endif /* SILC_THREADS*/
+}
+
+SilcBool silc_condvar_timedwait(SilcCondVar cond, SilcMutex mutex,
+ int timeout)
+{
+#ifdef SILC_THREADS
+ DWORD ret, t = INFINITE;
+
+ if (timeout)
+ t = timeout;
+
+ while (TRUE) {
+ cond->waiters++;
+ silc_mutex_unlock(mutex);
+
+ ret = WaitForSingleObject(cond->event, t);
+
+ silc_mutex_lock(mutex);
+ cond->waiters--;
+
+ if (ret != WAIT_OBJECT_0)
+ return FALSE;
+
+ if (cond->signal) {
+ cond->signal = FALSE;
+ ResetEvent(cond->event);
+ break;
+ }
+ }
+#endif /* SILC_THREADS*/
+}