Commit 5e4f2b5faaa86843befadcda2fb784301254e452

Philip Kelley 2012-10-16T13:18:45

Support pthread_cond_* on Win32

diff --git a/src/win32/pthread.c b/src/win32/pthread.c
index 3a186c8..cbed9d9 100644
--- a/src/win32/pthread.c
+++ b/src/win32/pthread.c
@@ -54,6 +54,71 @@ int pthread_mutex_unlock(pthread_mutex_t *mutex)
 	return 0;
 }
 
+int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
+{
+	/* We don't support non-default attributes. */
+	if (attr)
+		return EINVAL;
+
+	/* This is an auto-reset event. */
+	*cond = CreateEventW(NULL, FALSE, FALSE, NULL);
+	assert(*cond);
+
+	/* If we can't create the event, claim that the reason was out-of-memory.
+	 * The actual reason can be fetched with GetLastError(). */
+	return *cond ? 0 : ENOMEM;
+}
+
+int pthread_cond_destroy(pthread_cond_t *cond)
+{
+	BOOL closed;
+
+	if (!cond)
+		return EINVAL;
+
+	closed = CloseHandle(*cond);
+	assert(closed);
+
+	*cond = NULL;
+	return 0;
+}
+
+int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
+{
+	int error;
+	DWORD wait_result;
+
+	if (!cond || !mutex)
+		return EINVAL;
+
+	/* The caller must be holding the mutex. */
+	error = pthread_mutex_unlock(mutex);
+
+	if (error)
+		return error;
+
+	wait_result = WaitForSingleObject(*cond, INFINITE);
+	assert(WAIT_OBJECT_0 == wait_result);
+
+	return pthread_mutex_lock(mutex);
+}
+
+int pthread_cond_signal(pthread_cond_t *cond)
+{
+	BOOL signaled;
+
+	if (!cond)
+		return EINVAL;
+
+	signaled = SetEvent(*cond);
+	assert(signaled);
+
+	return 0;
+}
+
+/* pthread_cond_broadcast is not implemented because doing so with just Win32 events
+ * is quite complicated, and no caller in libgit2 uses it yet. */
+
 int pthread_num_processors_np(void)
 {
 	DWORD_PTR p, s;
diff --git a/src/win32/pthread.h b/src/win32/pthread.h
index b194cbf..136f9b1 100644
--- a/src/win32/pthread.h
+++ b/src/win32/pthread.h
@@ -21,6 +21,7 @@ typedef int pthread_condattr_t;
 typedef int pthread_attr_t;
 typedef CRITICAL_SECTION pthread_mutex_t;
 typedef HANDLE pthread_t;
+typedef HANDLE pthread_cond_t;
 
 #define PTHREAD_MUTEX_INITIALIZER {(void*)-1};
 
@@ -35,6 +36,12 @@ int pthread_mutex_destroy(pthread_mutex_t *);
 int pthread_mutex_lock(pthread_mutex_t *);
 int pthread_mutex_unlock(pthread_mutex_t *);
 
+int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
+int pthread_cond_destroy(pthread_cond_t *);
+int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
+int pthread_cond_signal(pthread_cond_t *);
+/* pthread_cond_broadcast is not supported on Win32 yet. */
+
 int pthread_num_processors_np(void);
 
 #endif