|
|
|
@ -115,9 +115,12 @@ static inline int pthread_mutex_unlock(pthread_mutex_t *m) |
|
|
|
|
/* for pre-Windows 6.0 platforms we need to define and use our own condition
|
|
|
|
|
* variable and api */ |
|
|
|
|
typedef struct { |
|
|
|
|
pthread_mutex_t mtx_broadcast; |
|
|
|
|
pthread_mutex_t mtx_waiter_count; |
|
|
|
|
volatile int waiter_count; |
|
|
|
|
HANDLE semaphore; |
|
|
|
|
HANDLE waiters_done; |
|
|
|
|
int is_broadcast; |
|
|
|
|
} win32_cond_t; |
|
|
|
|
|
|
|
|
|
static void pthread_cond_init(pthread_cond_t *cond, const void *unused_attr) |
|
|
|
@ -136,8 +139,12 @@ static void pthread_cond_init(pthread_cond_t *cond, const void *unused_attr) |
|
|
|
|
win32_cond->semaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); |
|
|
|
|
if (!win32_cond->semaphore) |
|
|
|
|
return; |
|
|
|
|
win32_cond->waiters_done = CreateEvent(NULL, FALSE, FALSE, NULL); |
|
|
|
|
if (!win32_cond->waiters_done) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
pthread_mutex_init(&win32_cond->mtx_waiter_count, NULL); |
|
|
|
|
pthread_mutex_init(&win32_cond->mtx_broadcast, NULL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void pthread_cond_destroy(pthread_cond_t *cond) |
|
|
|
@ -149,7 +156,9 @@ static void pthread_cond_destroy(pthread_cond_t *cond) |
|
|
|
|
|
|
|
|
|
/* non native condition variables */ |
|
|
|
|
CloseHandle(win32_cond->semaphore); |
|
|
|
|
CloseHandle(win32_cond->waiters_done); |
|
|
|
|
pthread_mutex_destroy(&win32_cond->mtx_waiter_count); |
|
|
|
|
pthread_mutex_destroy(&win32_cond->mtx_broadcast); |
|
|
|
|
av_freep(&win32_cond); |
|
|
|
|
cond->ptr = NULL; |
|
|
|
|
} |
|
|
|
@ -157,41 +166,70 @@ static void pthread_cond_destroy(pthread_cond_t *cond) |
|
|
|
|
static void pthread_cond_broadcast(pthread_cond_t *cond) |
|
|
|
|
{ |
|
|
|
|
win32_cond_t *win32_cond = cond->ptr; |
|
|
|
|
int have_waiter; |
|
|
|
|
|
|
|
|
|
if (cond_broadcast) { |
|
|
|
|
cond_broadcast(cond); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* non native condition variables */ |
|
|
|
|
pthread_mutex_lock(&win32_cond->mtx_broadcast); |
|
|
|
|
pthread_mutex_lock(&win32_cond->mtx_waiter_count); |
|
|
|
|
have_waiter = 0; |
|
|
|
|
|
|
|
|
|
if (win32_cond->waiter_count) { |
|
|
|
|
ReleaseSemaphore(win32_cond->semaphore, win32_cond->waiter_count, NULL); |
|
|
|
|
win32_cond->waiter_count = 0; |
|
|
|
|
win32_cond->is_broadcast = 1; |
|
|
|
|
have_waiter = 1; |
|
|
|
|
} |
|
|
|
|
pthread_mutex_unlock(&win32_cond->mtx_waiter_count); |
|
|
|
|
|
|
|
|
|
if (have_waiter) { |
|
|
|
|
ReleaseSemaphore(win32_cond->semaphore, win32_cond->waiter_count, NULL); |
|
|
|
|
pthread_mutex_unlock(&win32_cond->mtx_waiter_count); |
|
|
|
|
WaitForSingleObject(win32_cond->waiters_done, INFINITE); |
|
|
|
|
win32_cond->is_broadcast = 0; |
|
|
|
|
} else |
|
|
|
|
pthread_mutex_unlock(&win32_cond->mtx_waiter_count); |
|
|
|
|
pthread_mutex_unlock(&win32_cond->mtx_broadcast); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) |
|
|
|
|
{ |
|
|
|
|
win32_cond_t *win32_cond = cond->ptr; |
|
|
|
|
int last_waiter; |
|
|
|
|
if (cond_wait) { |
|
|
|
|
cond_wait(cond, mutex, INFINITE); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* non native condition variables */ |
|
|
|
|
pthread_mutex_lock(&win32_cond->mtx_broadcast); |
|
|
|
|
pthread_mutex_unlock(&win32_cond->mtx_broadcast); |
|
|
|
|
|
|
|
|
|
pthread_mutex_lock(&win32_cond->mtx_waiter_count); |
|
|
|
|
win32_cond->waiter_count++; |
|
|
|
|
pthread_mutex_unlock(&win32_cond->mtx_waiter_count); |
|
|
|
|
|
|
|
|
|
// unlock the external mutex
|
|
|
|
|
pthread_mutex_unlock(mutex); |
|
|
|
|
WaitForSingleObject(win32_cond->semaphore, INFINITE); |
|
|
|
|
pthread_mutex_lock(mutex); |
|
|
|
|
|
|
|
|
|
pthread_mutex_lock(&win32_cond->mtx_waiter_count); |
|
|
|
|
win32_cond->waiter_count--; |
|
|
|
|
last_waiter = !win32_cond->waiter_count && win32_cond->is_broadcast; |
|
|
|
|
pthread_mutex_unlock(&win32_cond->mtx_waiter_count); |
|
|
|
|
|
|
|
|
|
if (last_waiter) |
|
|
|
|
SetEvent(win32_cond->waiters_done); |
|
|
|
|
|
|
|
|
|
// lock the external mutex
|
|
|
|
|
return pthread_mutex_lock(mutex); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void pthread_cond_signal(pthread_cond_t *cond) |
|
|
|
|
{ |
|
|
|
|
win32_cond_t *win32_cond = cond->ptr; |
|
|
|
|
int have_waiter; |
|
|
|
|
if (cond_signal) { |
|
|
|
|
cond_signal(cond); |
|
|
|
|
return; |
|
|
|
@ -199,11 +237,11 @@ static void pthread_cond_signal(pthread_cond_t *cond) |
|
|
|
|
|
|
|
|
|
/* non-native condition variables */ |
|
|
|
|
pthread_mutex_lock(&win32_cond->mtx_waiter_count); |
|
|
|
|
if (win32_cond->waiter_count) { |
|
|
|
|
ReleaseSemaphore(win32_cond->semaphore, 1, NULL); |
|
|
|
|
win32_cond->waiter_count--; |
|
|
|
|
} |
|
|
|
|
have_waiter = win32_cond->waiter_count; |
|
|
|
|
pthread_mutex_unlock(&win32_cond->mtx_waiter_count); |
|
|
|
|
|
|
|
|
|
if (have_waiter) |
|
|
|
|
ReleaseSemaphore(win32_cond->semaphore, 1, NULL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void w32thread_init(void) |
|
|
|
|