diff options
author | Junio C Hamano <gitster@pobox.com> | 2018-11-18 18:23:57 +0900 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2018-11-18 18:23:57 +0900 |
commit | 06a2d241cf7c0efb91960875715c4d3241f4dbff (patch) | |
tree | da0eb74a29a036a39bec64c33c2f5bed4cd3f2b0 | |
parent | Merge branch 'nd/command-list-gen-fix' (diff) | |
parent | win32: replace pthread_cond_*() with much simpler code (diff) | |
download | tgif-06a2d241cf7c0efb91960875715c4d3241f4dbff.tar.xz |
Merge branch 'lj/mingw-pthread-cond'
Code simplification.
* lj/mingw-pthread-cond:
win32: replace pthread_cond_*() with much simpler code
-rw-r--r-- | compat/win32/pthread.c | 138 | ||||
-rw-r--r-- | compat/win32/pthread.h | 28 |
2 files changed, 7 insertions, 159 deletions
diff --git a/compat/win32/pthread.c b/compat/win32/pthread.c index e18f5c6e2e..2e7eead42c 100644 --- a/compat/win32/pthread.c +++ b/compat/win32/pthread.c @@ -56,141 +56,3 @@ pthread_t pthread_self(void) t.tid = GetCurrentThreadId(); return t; } - -int pthread_cond_init(pthread_cond_t *cond, const void *unused) -{ - cond->waiters = 0; - cond->was_broadcast = 0; - InitializeCriticalSection(&cond->waiters_lock); - - cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL); - if (!cond->sema) - die("CreateSemaphore() failed"); - - cond->continue_broadcast = CreateEvent(NULL, /* security */ - FALSE, /* auto-reset */ - FALSE, /* not signaled */ - NULL); /* name */ - if (!cond->continue_broadcast) - die("CreateEvent() failed"); - - return 0; -} - -int pthread_cond_destroy(pthread_cond_t *cond) -{ - CloseHandle(cond->sema); - CloseHandle(cond->continue_broadcast); - DeleteCriticalSection(&cond->waiters_lock); - return 0; -} - -int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex) -{ - int last_waiter; - - EnterCriticalSection(&cond->waiters_lock); - cond->waiters++; - LeaveCriticalSection(&cond->waiters_lock); - - /* - * Unlock external mutex and wait for signal. - * NOTE: we've held mutex locked long enough to increment - * waiters count above, so there's no problem with - * leaving mutex unlocked before we wait on semaphore. - */ - LeaveCriticalSection(mutex); - - /* let's wait - ignore return value */ - WaitForSingleObject(cond->sema, INFINITE); - - /* - * Decrease waiters count. If we are the last waiter, then we must - * notify the broadcasting thread that it can continue. - * But if we continued due to cond_signal, we do not have to do that - * because the signaling thread knows that only one waiter continued. - */ - EnterCriticalSection(&cond->waiters_lock); - cond->waiters--; - last_waiter = cond->was_broadcast && cond->waiters == 0; - LeaveCriticalSection(&cond->waiters_lock); - - if (last_waiter) { - /* - * cond_broadcast was issued while mutex was held. This means - * that all other waiters have continued, but are contending - * for the mutex at the end of this function because the - * broadcasting thread did not leave cond_broadcast, yet. - * (This is so that it can be sure that each waiter has - * consumed exactly one slice of the semaphor.) - * The last waiter must tell the broadcasting thread that it - * can go on. - */ - SetEvent(cond->continue_broadcast); - /* - * Now we go on to contend with all other waiters for - * the mutex. Auf in den Kampf! - */ - } - /* lock external mutex again */ - EnterCriticalSection(mutex); - - return 0; -} - -/* - * IMPORTANT: This implementation requires that pthread_cond_signal - * is called while the mutex is held that is used in the corresponding - * pthread_cond_wait calls! - */ -int pthread_cond_signal(pthread_cond_t *cond) -{ - int have_waiters; - - EnterCriticalSection(&cond->waiters_lock); - have_waiters = cond->waiters > 0; - LeaveCriticalSection(&cond->waiters_lock); - - /* - * Signal only when there are waiters - */ - if (have_waiters) - return ReleaseSemaphore(cond->sema, 1, NULL) ? - 0 : err_win_to_posix(GetLastError()); - else - return 0; -} - -/* - * DOUBLY IMPORTANT: This implementation requires that pthread_cond_broadcast - * is called while the mutex is held that is used in the corresponding - * pthread_cond_wait calls! - */ -int pthread_cond_broadcast(pthread_cond_t *cond) -{ - EnterCriticalSection(&cond->waiters_lock); - - if ((cond->was_broadcast = cond->waiters > 0)) { - /* wake up all waiters */ - ReleaseSemaphore(cond->sema, cond->waiters, NULL); - LeaveCriticalSection(&cond->waiters_lock); - /* - * At this point all waiters continue. Each one takes its - * slice of the semaphor. Now it's our turn to wait: Since - * the external mutex is held, no thread can leave cond_wait, - * yet. For this reason, we can be sure that no thread gets - * a chance to eat *more* than one slice. OTOH, it means - * that the last waiter must send us a wake-up. - */ - WaitForSingleObject(cond->continue_broadcast, INFINITE); - /* - * Since the external mutex is held, no thread can enter - * cond_wait, and, hence, it is safe to reset this flag - * without cond->waiters_lock held. - */ - cond->was_broadcast = 0; - } else { - LeaveCriticalSection(&cond->waiters_lock); - } - return 0; -} diff --git a/compat/win32/pthread.h b/compat/win32/pthread.h index 1c164088fb..c6cb8dd219 100644 --- a/compat/win32/pthread.h +++ b/compat/win32/pthread.h @@ -32,27 +32,13 @@ typedef int pthread_mutexattr_t; #define pthread_mutexattr_settype(a, t) 0 #define PTHREAD_MUTEX_RECURSIVE 0 -/* - * Implement simple condition variable for Windows threads, based on ACE - * implementation. - * - * See original implementation: http://bit.ly/1vkDjo - * ACE homepage: http://www.cse.wustl.edu/~schmidt/ACE.html - * See also: http://www.cse.wustl.edu/~schmidt/win32-cv-1.html - */ -typedef struct { - LONG waiters; - int was_broadcast; - CRITICAL_SECTION waiters_lock; - HANDLE sema; - HANDLE continue_broadcast; -} pthread_cond_t; - -extern int pthread_cond_init(pthread_cond_t *cond, const void *unused); -extern int pthread_cond_destroy(pthread_cond_t *cond); -extern int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex); -extern int pthread_cond_signal(pthread_cond_t *cond); -extern int pthread_cond_broadcast(pthread_cond_t *cond); +#define pthread_cond_t CONDITION_VARIABLE + +#define pthread_cond_init(a,b) InitializeConditionVariable((a)) +#define pthread_cond_destroy(a) do {} while (0) +#define pthread_cond_wait(a,b) return_0(SleepConditionVariableCS((a), (b), INFINITE)) +#define pthread_cond_signal WakeConditionVariable +#define pthread_cond_broadcast WakeAllConditionVariable /* * Simple thread creation implementation using pthread API |