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 ...@@ -134,7 +134,12 @@ typedef struct
} vlc_mutex_t; } vlc_mutex_t;
#define VLC_STATIC_MUTEX { false, { { false, 0 } } } #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 HANDLE vlc_sem_t;
typedef struct typedef struct
...@@ -165,6 +170,7 @@ VLC_EXPORT( void, vlc_mutex_lock, ( vlc_mutex_t * ) ); ...@@ -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( int, vlc_mutex_trylock, ( vlc_mutex_t * ) LIBVLC_USED );
VLC_EXPORT( void, vlc_mutex_unlock, ( vlc_mutex_t * ) ); VLC_EXPORT( void, vlc_mutex_unlock, ( vlc_mutex_t * ) );
VLC_EXPORT( void, vlc_cond_init, ( vlc_cond_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_destroy, ( vlc_cond_t * ) );
VLC_EXPORT( void, vlc_cond_signal, (vlc_cond_t *) ); VLC_EXPORT( void, vlc_cond_signal, (vlc_cond_t *) );
VLC_EXPORT( void, vlc_cond_broadcast, (vlc_cond_t *) ); VLC_EXPORT( void, vlc_cond_broadcast, (vlc_cond_t *) );
......
...@@ -476,6 +476,7 @@ VLC_Compiler ...@@ -476,6 +476,7 @@ VLC_Compiler
vlc_cond_broadcast vlc_cond_broadcast
vlc_cond_destroy vlc_cond_destroy
vlc_cond_init vlc_cond_init
vlc_cond_init_daytime
vlc_cond_signal vlc_cond_signal
vlc_cond_timedwait vlc_cond_timedwait
vlc_cond_wait vlc_cond_wait
......
...@@ -256,10 +256,10 @@ void vlc_mutex_unlock (vlc_mutex_t *p_mutex) ...@@ -256,10 +256,10 @@ void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
VLC_THREAD_ASSERT ("unlocking mutex"); VLC_THREAD_ASSERT ("unlocking mutex");
} }
/***************************************************************************** /**
* vlc_cond_init: initialize a condition variable * Initializes a condition variable.
*****************************************************************************/ */
void vlc_cond_init( vlc_cond_t *p_condvar ) void vlc_cond_init (vlc_cond_t *p_condvar)
{ {
pthread_condattr_t attr; pthread_condattr_t attr;
...@@ -279,6 +279,17 @@ void vlc_cond_init( vlc_cond_t *p_condvar ) ...@@ -279,6 +279,17 @@ void vlc_cond_init( vlc_cond_t *p_condvar )
pthread_condattr_destroy (&attr); 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 * Destroys a condition variable. No threads shall be waiting or signaling the
* condition. * condition.
...@@ -351,7 +362,11 @@ void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex) ...@@ -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. * 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_condvar condition variable to wait on
* @param p_mutex mutex which is unlocked while waiting, * @param p_mutex mutex which is unlocked while waiting,
......
...@@ -247,17 +247,34 @@ void vlc_mutex_unlock (vlc_mutex_t *p_mutex) ...@@ -247,17 +247,34 @@ void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
} }
/*** Condition variables ***/ /*** 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). */ /* Create a manual-reset event (manual reset is needed for broadcast). */
*p_condvar = CreateEvent (NULL, TRUE, FALSE, NULL); p_condvar->handle = CreateEvent (NULL, TRUE, FALSE, NULL);
if (!*p_condvar) if (!p_condvar->handle)
abort(); 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) 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) void vlc_cond_signal (vlc_cond_t *p_condvar)
...@@ -267,12 +284,12 @@ 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 * waiting, which is also wrong. However both of these issues are allowed
* by the provision for spurious wakeups. Better have too many wakeups * by the provision for spurious wakeups. Better have too many wakeups
* than too few (= deadlocks). */ * than too few (= deadlocks). */
SetEvent (*p_condvar); SetEvent (p_condvar->handle);
} }
void vlc_cond_broadcast (vlc_cond_t *p_condvar) 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) 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) ...@@ -284,14 +301,14 @@ void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex)
{ {
vlc_testcancel (); vlc_testcancel ();
LeaveCriticalSection (&p_mutex->mutex); LeaveCriticalSection (&p_mutex->mutex);
result = WaitForSingleObjectEx (*p_condvar, INFINITE, TRUE); result = WaitForSingleObjectEx (p_condvar->handle, INFINITE, TRUE);
EnterCriticalSection (&p_mutex->mutex); EnterCriticalSection (&p_mutex->mutex);
} }
while (result == WAIT_IO_COMPLETION); while (result == WAIT_IO_COMPLETION);
assert (result != WAIT_ABANDONED); /* another thread failed to cleanup! */ assert (result != WAIT_ABANDONED); /* another thread failed to cleanup! */
assert (result != WAIT_FAILED); 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, 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, ...@@ -304,20 +321,32 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
{ {
vlc_testcancel (); 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 ) if( total < 0 )
total = 0; total = 0;
DWORD delay = (total > 0x7fffffff) ? 0x7fffffff : total; DWORD delay = (total > 0x7fffffff) ? 0x7fffffff : total;
LeaveCriticalSection (&p_mutex->mutex); LeaveCriticalSection (&p_mutex->mutex);
result = WaitForSingleObjectEx (*p_condvar, delay, TRUE); result = WaitForSingleObjectEx (p_condvar->handle, delay, TRUE);
EnterCriticalSection (&p_mutex->mutex); EnterCriticalSection (&p_mutex->mutex);
} }
while (result == WAIT_IO_COMPLETION); while (result == WAIT_IO_COMPLETION);
assert (result != WAIT_ABANDONED); assert (result != WAIT_ABANDONED);
assert (result != WAIT_FAILED); assert (result != WAIT_FAILED);
ResetEvent (*p_condvar); ResetEvent (p_condvar->handle);
return (result == WAIT_OBJECT_0) ? 0 : ETIMEDOUT; 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