瀏覽代碼

implemented pthread_cond_broadcast() better to avoid mg_stop() deadlock on Win32

valenok 15 年之前
父節點
當前提交
2b732a8067
共有 1 個文件被更改,包括 13 次插入25 次删除
  1. 13 25
      mongoose.c

+ 13 - 25
mongoose.c

@@ -125,7 +125,7 @@ typedef long off_t;
 #endif // !fileno MINGW #defines fileno
 #endif // !fileno MINGW #defines fileno
 
 
 typedef HANDLE pthread_mutex_t;
 typedef HANDLE pthread_mutex_t;
-typedef HANDLE pthread_cond_t;
+typedef struct {HANDLE signal, broadcast;} pthread_cond_t;
 typedef DWORD pthread_t;
 typedef DWORD pthread_t;
 #define pid_t HANDLE // MINGW typedefs pid_t to int. Using #define here.
 #define pid_t HANDLE // MINGW typedefs pid_t to int. Using #define here.
 
 
@@ -791,42 +791,30 @@ static int pthread_mutex_unlock(pthread_mutex_t *mutex) {
 
 
 static int pthread_cond_init(pthread_cond_t *cv, const void *unused) {
 static int pthread_cond_init(pthread_cond_t *cv, const void *unused) {
   unused = NULL;
   unused = NULL;
-  *cv = CreateEvent(NULL, FALSE, FALSE, NULL);
-  return *cv == NULL ? -1 : 0;
-}
-
-static int pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mutex,
-                                  const struct timespec *ts) {
-  DWORD status;
-  DWORD msec = INFINITE;
-  time_t now;
-
-  if (ts != NULL) {
-    now = time(NULL);
-    msec = 1000 * (now > ts->tv_sec ? 0 : ts->tv_sec - now);
-  }
-
-  (void) ReleaseMutex(*mutex);
-  status = WaitForSingleObject(*cv, msec);
-  (void) WaitForSingleObject(*mutex, INFINITE);
-
-  return status == WAIT_OBJECT_0 ? 0 : -1;
+  cv->signal = CreateEvent(NULL, FALSE, FALSE, NULL);
+  cv->broadcast = CreateEvent(NULL, TRUE, FALSE, NULL);
+  return cv->signal != NULL && cv->broadcast != NULL ? 0 : -1;
 }
 }
 
 
 static int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex) {
 static int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex) {
-  return pthread_cond_timedwait(cv, mutex, NULL);
+  HANDLE handles[] = {cv->signal, cv->broadcast};
+  ReleaseMutex(*mutex);
+  WaitForMultipleObjects(2, handles, FALSE, INFINITE);
+  return ReleaseMutex(*mutex) == 0 ? -1 : 0;
 }
 }
 
 
 static int pthread_cond_signal(pthread_cond_t *cv) {
 static int pthread_cond_signal(pthread_cond_t *cv) {
-  return SetEvent(*cv) == 0 ? -1 : 0;
+  return SetEvent(cv->signal) == 0 ? -1 : 0;
 }
 }
 
 
 static int pthread_cond_broadcast(pthread_cond_t *cv) {
 static int pthread_cond_broadcast(pthread_cond_t *cv) {
-  return PulseEvent(*cv) == 0 ? -1 : 0;
+  // Implementation with PulseEvent() has race condition, see
+  // http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
+  return PulseEvent(cv->broadcast) == 0 ? -1 : 0;
 }
 }
 
 
 static int pthread_cond_destroy(pthread_cond_t *cv) {
 static int pthread_cond_destroy(pthread_cond_t *cv) {
-  return CloseHandle(*cv) == 0 ? -1 : 0;
+  return CloseHandle(cv->signal) && CloseHandle(cv->broadcast) ? 0 : -1;
 }
 }
 
 
 static pthread_t pthread_self(void) {
 static pthread_t pthread_self(void) {