Commit a160b858 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

vlc_cond_init_daytime: condition variable with the wall clock

parent 3f628821
......@@ -134,7 +134,12 @@ typedef struct
} vlc_mutex_t;
#define VLC_STATIC_MUTEX { false, { { false, 0 } } }
typedef HANDLE vlc_cond_t;
typedef struct
{
HANDLE handle;
unsigned clock;
} vlc_cond_t;
typedef HANDLE vlc_sem_t;
typedef struct
......@@ -165,6 +170,7 @@ VLC_EXPORT( void, vlc_mutex_lock, ( vlc_mutex_t * ) );
VLC_EXPORT( int, vlc_mutex_trylock, ( vlc_mutex_t * ) LIBVLC_USED );
VLC_EXPORT( void, vlc_mutex_unlock, ( vlc_mutex_t * ) );
VLC_EXPORT( void, vlc_cond_init, ( vlc_cond_t * ) );
VLC_EXPORT( void, vlc_cond_init_daytime, ( vlc_cond_t * ) );
VLC_EXPORT( void, vlc_cond_destroy, ( vlc_cond_t * ) );
VLC_EXPORT( void, vlc_cond_signal, (vlc_cond_t *) );
VLC_EXPORT( void, vlc_cond_broadcast, (vlc_cond_t *) );
......
......@@ -476,6 +476,7 @@ VLC_Compiler
vlc_cond_broadcast
vlc_cond_destroy
vlc_cond_init
vlc_cond_init_daytime
vlc_cond_signal
vlc_cond_timedwait
vlc_cond_wait
......
......@@ -256,10 +256,10 @@ void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
VLC_THREAD_ASSERT ("unlocking mutex");
}
/*****************************************************************************
* vlc_cond_init: initialize a condition variable
*****************************************************************************/
void vlc_cond_init( vlc_cond_t *p_condvar )
/**
* Initializes a condition variable.
*/
void vlc_cond_init (vlc_cond_t *p_condvar)
{
pthread_condattr_t attr;
......@@ -279,6 +279,17 @@ void vlc_cond_init( vlc_cond_t *p_condvar )
pthread_condattr_destroy (&attr);
}
/**
* Initializes a condition variable.
* Contrary to vlc_cond_init(), the wall clock will be used as a reference for
* the vlc_cond_timedwait() time-out parameter.
*/
void vlc_cond_init_daytime (vlc_cond_t *p_condvar)
{
if (unlikely(pthread_cond_init (p_condvar, NULL)))
abort ();
}
/**
* Destroys a condition variable. No threads shall be waiting or signaling the
* condition.
......@@ -351,7 +362,11 @@ void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex)
/**
* Waits for a condition variable up to a certain date.
* This works like vlc_cond_wait(), except for the additional timeout.
* This works like vlc_cond_wait(), except for the additional time-out.
*
* If the variable was initialized with vlc_cond_init(), the timeout has the
* same arbitrary origin as mdate(). If the variable was initialized with
* vlc_cond_init_daytime(), the timeout is expressed from the Unix epoch.
*
* @param p_condvar condition variable to wait on
* @param p_mutex mutex which is unlocked while waiting,
......
......@@ -247,17 +247,34 @@ void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
}
/*** Condition variables ***/
void vlc_cond_init( vlc_cond_t *p_condvar )
enum
{
CLOCK_MONOTONIC,
CLOCK_REALTIME,
};
static void vlc_cond_init_common (vlc_cond_t *p_condvar, unsigned clock)
{
/* Create a manual-reset event (manual reset is needed for broadcast). */
*p_condvar = CreateEvent (NULL, TRUE, FALSE, NULL);
if (!*p_condvar)
p_condvar->handle = CreateEvent (NULL, TRUE, FALSE, NULL);
if (!p_condvar->handle)
abort();
p_condvar->clock = clock;
}
void vlc_cond_init (vlc_cond_t *p_condvar)
{
vlc_cond_init_common (p_condvar, CLOCK_MONOTONIC);
}
void vlc_cond_init_daytime (vlc_cond_t *p_condvar)
{
vlc_cond_init_common (p_condvar, CLOCK_REALTIME);
}
void vlc_cond_destroy (vlc_cond_t *p_condvar)
{
CloseHandle (*p_condvar);
CloseHandle (p_condvar->handle);
}
void vlc_cond_signal (vlc_cond_t *p_condvar)
......@@ -267,12 +284,12 @@ void vlc_cond_signal (vlc_cond_t *p_condvar)
* waiting, which is also wrong. However both of these issues are allowed
* by the provision for spurious wakeups. Better have too many wakeups
* than too few (= deadlocks). */
SetEvent (*p_condvar);
SetEvent (p_condvar->handle);
}
void vlc_cond_broadcast (vlc_cond_t *p_condvar)
{
SetEvent (*p_condvar);
SetEvent (p_condvar->handle);
}
void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex)
......@@ -284,14 +301,14 @@ void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex)
{
vlc_testcancel ();
LeaveCriticalSection (&p_mutex->mutex);
result = WaitForSingleObjectEx (*p_condvar, INFINITE, TRUE);
result = WaitForSingleObjectEx (p_condvar->handle, INFINITE, TRUE);
EnterCriticalSection (&p_mutex->mutex);
}
while (result == WAIT_IO_COMPLETION);
assert (result != WAIT_ABANDONED); /* another thread failed to cleanup! */
assert (result != WAIT_FAILED);
ResetEvent (*p_condvar);
ResetEvent (p_condvar->handle);
}
int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
......@@ -304,20 +321,32 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
{
vlc_testcancel ();
mtime_t total = (deadline - mdate ())/1000;
mtime_t total;
switch (p_condvar->clock)
{
case CLOCK_MONOTONIC:
total = mdate();
break;
case CLOCK_REALTIME: /* FIXME? sub-second precision */
total = CLOCK_FREQ * time (NULL);
break;
default:
assert (0);
}
total = (deadline - total) / 1000;
if( total < 0 )
total = 0;
DWORD delay = (total > 0x7fffffff) ? 0x7fffffff : total;
LeaveCriticalSection (&p_mutex->mutex);
result = WaitForSingleObjectEx (*p_condvar, delay, TRUE);
result = WaitForSingleObjectEx (p_condvar->handle, delay, TRUE);
EnterCriticalSection (&p_mutex->mutex);
}
while (result == WAIT_IO_COMPLETION);
assert (result != WAIT_ABANDONED);
assert (result != WAIT_FAILED);
ResetEvent (*p_condvar);
ResetEvent (p_condvar->handle);
return (result == WAIT_OBJECT_0) ? 0 : ETIMEDOUT;
}
......
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