[vlc-commits] win32: avoid broadcast in vlc_cond_signal()
Rémi Denis-Courmont
git at videolan.org
Sun May 17 16:23:59 CEST 2015
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sun May 17 16:03:18 2015 +0300| [8762b9415cbb0ab65b409ee2999e69a94901ab30] | committer: Rémi Denis-Courmont
win32: avoid broadcast in vlc_cond_signal()
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=8762b9415cbb0ab65b409ee2999e69a94901ab30
---
src/win32/thread.c | 32 ++++++++++++++++++++++++++++----
1 file changed, 28 insertions(+), 4 deletions(-)
diff --git a/src/win32/thread.c b/src/win32/thread.c
index 46fa357..c30e67d 100644
--- a/src/win32/thread.c
+++ b/src/win32/thread.c
@@ -225,10 +225,29 @@ void vlc_cond_destroy(vlc_cond_t *wait)
CloseHandle(wait->semaphore);
}
-void vlc_cond_signal (vlc_cond_t *p_condvar)
+static LONG InterlockedDecrementNonZero(LONG volatile *dst)
{
- /* This is suboptimal but works. */
- vlc_cond_broadcast (p_condvar);
+ LONG cmp, val = 1;
+
+ do
+ {
+ cmp = val;
+ val = InterlockedCompareExchange(dst, val - 1, val);
+ if (val == 0)
+ return 0;
+ }
+ while (cmp != val);
+
+ return val;
+}
+
+void vlc_cond_signal(vlc_cond_t *wait)
+{
+ if (!wait->clock)
+ return;
+
+ if (InterlockedDecrementNonZero(&wait->waiters) > 0)
+ ReleaseSemaphore(wait->semaphore, 1, NULL);
}
void vlc_cond_broadcast(vlc_cond_t *wait)
@@ -243,6 +262,8 @@ void vlc_cond_broadcast(vlc_cond_t *wait)
void vlc_cond_wait(vlc_cond_t *wait, vlc_mutex_t *lock)
{
+ DWORD result;
+
vlc_testcancel();
if (!wait->clock)
@@ -253,8 +274,11 @@ void vlc_cond_wait(vlc_cond_t *wait, vlc_mutex_t *lock)
InterlockedIncrement(&wait->waiters);
vlc_mutex_unlock(lock);
- vlc_WaitForSingleObject(wait->semaphore, INFINITE);
+ result = vlc_WaitForSingleObject(wait->semaphore, INFINITE);
vlc_mutex_lock(lock);
+
+ if (result == WAIT_IO_COMPLETION)
+ vlc_testcancel();
}
int vlc_cond_timedwait(vlc_cond_t *wait, vlc_mutex_t *lock, mtime_t deadline)
More information about the vlc-commits
mailing list