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
#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;
......
......@@ -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)
switch (wait->clock)
{
case VLC_CLOCK_MONOTONIC:
total = mdate();
break;
case VLC_CLOCK_REALTIME: /* FIXME? sub-second precision */
total = CLOCK_FREQ * time (NULL);
total = CLOCK_FREQ * time(NULL);
break;
default:
assert (!p_condvar->clock);
assert(!wait->clock);
/* FIXME FIXME FIXME */
msleep (50000);
msleep(50000);
return 0;
}
total = (deadline - total) / 1000;
if( total < 0 )
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);
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 ***/
......
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