summaryrefslogtreecommitdiff
path: root/evthread_pthread.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2010-08-17 13:15:34 -0400
committerNick Mathewson <nickm@torproject.org>2010-08-17 13:15:34 -0400
commitd4977b52f07d61e215e5d5e98af2216719c06d16 (patch)
treec126cef2414554f44b0b1e9d85fe732da4ce50f3 /evthread_pthread.c
parent3920172821c2ad7862c2e4dab4d45adb1356a724 (diff)
downloadlibevent-d4977b52f07d61e215e5d5e98af2216719c06d16.tar.gz
Add a condition variable backend, with implementations for pthreads and win32
The interface from the user's POV is similar to the locking implementation: either provide a structure full of function pointers, or just call evthread_use_*_threads() and everything will be okay. The internal interface is meant to vaguely resemble pthread_cond_*, which Windows people will better recognize as *ConditionVariable*.
Diffstat (limited to 'evthread_pthread.c')
-rw-r--r--evthread_pthread.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/evthread_pthread.c b/evthread_pthread.c
index c5f4c537..59433737 100644
--- a/evthread_pthread.c
+++ b/evthread_pthread.c
@@ -34,6 +34,7 @@ struct event_base;
#include <stdlib.h>
#include "mm-internal.h"
+#include "evthread-internal.h"
static pthread_mutexattr_t attr_recursive;
@@ -89,6 +90,66 @@ evthread_posix_get_id(void)
return r.id;
}
+static void *
+evthread_posix_cond_alloc(unsigned condflags)
+{
+ pthread_cond_t *cond = mm_malloc(sizeof(pthread_cond_t));
+ if (!cond)
+ return NULL;
+ if (pthread_cond_init(cond, NULL)) {
+ mm_free(cond);
+ return NULL;
+ }
+ return cond;
+}
+
+static void
+evthread_posix_cond_free(void *_cond)
+{
+ pthread_cond_t *cond = _cond;
+ pthread_cond_destroy(cond);
+ mm_free(cond);
+}
+
+static int
+evthread_posix_cond_signal(void *_cond, int broadcast)
+{
+ pthread_cond_t *cond = _cond;
+ int r;
+ if (broadcast)
+ r = pthread_cond_broadcast(cond);
+ else
+ r = pthread_cond_signal(cond);
+ return r ? -1 : 0;
+}
+
+static int
+evthread_posix_cond_wait(void *_cond, void *_lock, const struct timeval *tv)
+{
+ int r;
+ pthread_cond_t *cond = _cond;
+ pthread_mutex_t *lock = _lock;
+
+ if (tv) {
+ struct timeval now, abstime;
+ struct timespec ts;
+ evutil_gettimeofday(&now, NULL);
+ evutil_timeradd(&now, tv, &abstime);
+ ts.tv_sec = abstime.tv_sec;
+ ts.tv_nsec = abstime.tv_usec*1000;
+ r = pthread_cond_timedwait(cond, lock, &ts);
+ if (r == ETIMEDOUT)
+ return 1;
+ else if (r)
+ return -1;
+ else
+ return 0;
+ } else {
+ r = pthread_cond_wait(cond, lock);
+ return r ? -1 : 0;
+ }
+}
+
int
evthread_use_pthreads(void)
{
@@ -100,6 +161,13 @@ evthread_use_pthreads(void)
evthread_posix_lock,
evthread_posix_unlock
};
+ struct evthread_condition_callbacks cond_cbs = {
+ EVTHREAD_CONDITION_API_VERSION,
+ evthread_posix_cond_alloc,
+ evthread_posix_cond_free,
+ evthread_posix_cond_signal,
+ evthread_posix_cond_wait
+ };
/* Set ourselves up to get recursive locks. */
if (pthread_mutexattr_init(&attr_recursive))
return -1;
@@ -107,6 +175,7 @@ evthread_use_pthreads(void)
return -1;
evthread_set_lock_callbacks(&cbs);
+ evthread_set_condition_callbacks(&cond_cbs);
evthread_set_id_callback(evthread_posix_get_id);
return 0;
}