[vlc-commits] win32: fix vlc_cond_broadcast()
Rémi Denis-Courmont
git at videolan.org
Sun May 17 16:04:24 CEST 2015
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | 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 ***/
More information about the vlc-commits
mailing list