vlc | branch: master | Rémi Denis-Courmont <[email protected]> | Sun May 17 16:00:10 2015 +0300| [52894f2fe97db80e0f6b4fed7ca440c0e590204d] | committer: Rémi Denis-Courmont
win32: fix vlc_cond_broadcast() Signaling an event ensures that at least one thread wakes up, but it does not warrant that all of them do. > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=52894f2fe97db80e0f6b4fed7ca440c0e590204d --- include/vlc_threads.h | 5 ++- src/win32/thread.c | 104 +++++++++++++++++++++++-------------------------- 2 files changed, 52 insertions(+), 57 deletions(-) diff --git a/include/vlc_threads.h b/include/vlc_threads.h index dfe61ed..38bc3a7 100644 --- a/include/vlc_threads.h +++ b/include/vlc_threads.h @@ -61,10 +61,11 @@ typedef struct #define VLC_STATIC_MUTEX { false, { { false, 0 } } } typedef struct { - HANDLE handle; + HANDLE semaphore; + LONG waiters; unsigned clock; } vlc_cond_t; -#define VLC_STATIC_COND { 0, 0 } +#define VLC_STATIC_COND { NULL, 0, 0 } typedef HANDLE vlc_sem_t; #define LIBVLC_NEED_RWLOCK typedef struct vlc_threadvar *vlc_threadvar_t; diff --git a/src/win32/thread.c b/src/win32/thread.c index 2f94fab..46fa357 100644 --- a/src/win32/thread.c +++ b/src/win32/thread.c @@ -201,13 +201,13 @@ enum VLC_CLOCK_REALTIME, }; -static void vlc_cond_init_common (vlc_cond_t *p_condvar, unsigned clock) +static void vlc_cond_init_common(vlc_cond_t *wait, unsigned clock) { - /* Create a manual-reset event (manual reset is needed for broadcast). */ - p_condvar->handle = CreateEvent (NULL, TRUE, FALSE, NULL); - if (!p_condvar->handle) + wait->semaphore = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL); + if (unlikely(wait->semaphore == NULL)) abort(); - p_condvar->clock = clock; + wait->waiters = 0; + wait->clock = clock; } void vlc_cond_init (vlc_cond_t *p_condvar) @@ -220,9 +220,9 @@ void vlc_cond_init_daytime (vlc_cond_t *p_condvar) vlc_cond_init_common (p_condvar, VLC_CLOCK_REALTIME); } -void vlc_cond_destroy (vlc_cond_t *p_condvar) +void vlc_cond_destroy(vlc_cond_t *wait) { - CloseHandle (p_condvar->handle); + CloseHandle(wait->semaphore); } void vlc_cond_signal (vlc_cond_t *p_condvar) @@ -231,75 +231,69 @@ void vlc_cond_signal (vlc_cond_t *p_condvar) vlc_cond_broadcast (p_condvar); } -void vlc_cond_broadcast (vlc_cond_t *p_condvar) +void vlc_cond_broadcast(vlc_cond_t *wait) { - if (!p_condvar->clock) + if (!wait->clock) return; - /* Wake all threads up (as the event HANDLE has manual reset) */ - SetEvent (p_condvar->handle); + LONG waiters = InterlockedExchange(&wait->waiters, 0); + if (waiters > 0) + ReleaseSemaphore(wait->semaphore, waiters, NULL); } -void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex) +void vlc_cond_wait(vlc_cond_t *wait, vlc_mutex_t *lock) { - DWORD result; + vlc_testcancel(); - if (!p_condvar->clock) + if (!wait->clock) { /* FIXME FIXME FIXME */ msleep (50000); return; } - do - { - vlc_testcancel (); - vlc_mutex_unlock (p_mutex); - result = vlc_WaitForSingleObject (p_condvar->handle, INFINITE); - vlc_mutex_lock (p_mutex); - } - while (result == WAIT_IO_COMPLETION); - - ResetEvent (p_condvar->handle); + InterlockedIncrement(&wait->waiters); + vlc_mutex_unlock(lock); + vlc_WaitForSingleObject(wait->semaphore, INFINITE); + vlc_mutex_lock(lock); } -int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex, - mtime_t deadline) +int vlc_cond_timedwait(vlc_cond_t *wait, vlc_mutex_t *lock, mtime_t deadline) { + mtime_t total; DWORD result; - do - { - vlc_testcancel (); + vlc_testcancel(); - mtime_t total; - switch (p_condvar->clock) - { - case VLC_CLOCK_MONOTONIC: - total = mdate(); - break; - case VLC_CLOCK_REALTIME: /* FIXME? sub-second precision */ - total = CLOCK_FREQ * time (NULL); - break; - default: - assert (!p_condvar->clock); - /* FIXME FIXME FIXME */ - msleep (50000); - return 0; - } - total = (deadline - total) / 1000; - if( total < 0 ) - total = 0; - - DWORD delay = (total > 0x7fffffff) ? 0x7fffffff : total; - vlc_mutex_unlock (p_mutex); - result = vlc_WaitForSingleObject (p_condvar->handle, delay); - vlc_mutex_lock (p_mutex); + switch (wait->clock) + { + case VLC_CLOCK_MONOTONIC: + total = mdate(); + break; + case VLC_CLOCK_REALTIME: /* FIXME? sub-second precision */ + total = CLOCK_FREQ * time(NULL); + break; + default: + assert(!wait->clock); + /* FIXME FIXME FIXME */ + msleep(50000); + return 0; } - while (result == WAIT_IO_COMPLETION); - ResetEvent (p_condvar->handle); + total = (deadline - total) / 1000; + if (total < 0) + total = 0; + + DWORD delay = (total > 0x7fffffff) ? 0x7fffffff : total; + + InterlockedIncrement(&wait->waiters); + vlc_mutex_unlock(lock); + result = vlc_WaitForSingleObject(wait->semaphore, delay); + vlc_mutex_lock(lock); + + if (result == WAIT_IO_COMPLETION) + vlc_testcancel(); - return (result == WAIT_OBJECT_0) ? 0 : ETIMEDOUT; + return (result == WAIT_TIMEOUT) ? ETIMEDOUT : 0; } /*** Semaphore ***/ _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
