Commit 52894f2f authored by Rémi Denis-Courmont's avatar 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.
parent 8459d808
...@@ -61,10 +61,11 @@ typedef struct ...@@ -61,10 +61,11 @@ typedef struct
#define VLC_STATIC_MUTEX { false, { { false, 0 } } } #define VLC_STATIC_MUTEX { false, { { false, 0 } } }
typedef struct typedef struct
{ {
HANDLE handle; HANDLE semaphore;
LONG waiters;
unsigned clock; unsigned clock;
} vlc_cond_t; } vlc_cond_t;
#define VLC_STATIC_COND { 0, 0 } #define VLC_STATIC_COND { NULL, 0, 0 }
typedef HANDLE vlc_sem_t; typedef HANDLE vlc_sem_t;
#define LIBVLC_NEED_RWLOCK #define LIBVLC_NEED_RWLOCK
typedef struct vlc_threadvar *vlc_threadvar_t; typedef struct vlc_threadvar *vlc_threadvar_t;
......
...@@ -201,13 +201,13 @@ enum ...@@ -201,13 +201,13 @@ enum
VLC_CLOCK_REALTIME, 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). */ wait->semaphore = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
p_condvar->handle = CreateEvent (NULL, TRUE, FALSE, NULL); if (unlikely(wait->semaphore == NULL))
if (!p_condvar->handle)
abort(); abort();
p_condvar->clock = clock; wait->waiters = 0;
wait->clock = clock;
} }
void vlc_cond_init (vlc_cond_t *p_condvar) void vlc_cond_init (vlc_cond_t *p_condvar)
...@@ -220,9 +220,9 @@ void vlc_cond_init_daytime (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); 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) void vlc_cond_signal (vlc_cond_t *p_condvar)
...@@ -231,75 +231,69 @@ 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); 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; return;
/* Wake all threads up (as the event HANDLE has manual reset) */ LONG waiters = InterlockedExchange(&wait->waiters, 0);
SetEvent (p_condvar->handle); 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 */ { /* FIXME FIXME FIXME */
msleep (50000); msleep (50000);
return; return;
} }
do InterlockedIncrement(&wait->waiters);
{ vlc_mutex_unlock(lock);
vlc_testcancel (); vlc_WaitForSingleObject(wait->semaphore, INFINITE);
vlc_mutex_unlock (p_mutex); vlc_mutex_lock(lock);
result = vlc_WaitForSingleObject (p_condvar->handle, INFINITE);
vlc_mutex_lock (p_mutex);
}
while (result == WAIT_IO_COMPLETION);
ResetEvent (p_condvar->handle);
} }
int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex, int vlc_cond_timedwait(vlc_cond_t *wait, vlc_mutex_t *lock, mtime_t deadline)
mtime_t deadline)
{ {
mtime_t total;
DWORD result; DWORD result;
do vlc_testcancel();
{
vlc_testcancel ();
mtime_t total; switch (wait->clock)
switch (p_condvar->clock) {
{ case VLC_CLOCK_MONOTONIC:
case VLC_CLOCK_MONOTONIC: total = mdate();
total = mdate(); break;
break; case VLC_CLOCK_REALTIME: /* FIXME? sub-second precision */
case VLC_CLOCK_REALTIME: /* FIXME? sub-second precision */ total = CLOCK_FREQ * time(NULL);
total = CLOCK_FREQ * time (NULL); break;
break; default:
default: assert(!wait->clock);
assert (!p_condvar->clock); /* FIXME FIXME FIXME */
/* FIXME FIXME FIXME */ msleep(50000);
msleep (50000); return 0;
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);
} }
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 ***/ /*** Semaphore ***/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment