From: RĂ©mi Denis-Courmont Date: Mon, 8 Feb 2010 16:46:02 +0000 (+0200) Subject: vlc_cond_init_daytime: condition variable with the wall clock X-Git-Tag: 1.1.0-ff~298 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=a160b8589331960e47702e382794d492ee480946;p=vlc vlc_cond_init_daytime: condition variable with the wall clock --- diff --git a/include/vlc_threads.h b/include/vlc_threads.h index c303420d25..8bff2382d6 100644 --- a/include/vlc_threads.h +++ b/include/vlc_threads.h @@ -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 *) ); diff --git a/src/libvlccore.sym b/src/libvlccore.sym index d608ab34de..e0c53b3d51 100644 --- a/src/libvlccore.sym +++ b/src/libvlccore.sym @@ -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 diff --git a/src/misc/pthread.c b/src/misc/pthread.c index 4522db07e9..ca422cf697 100644 --- a/src/misc/pthread.c +++ b/src/misc/pthread.c @@ -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, diff --git a/src/win32/thread.c b/src/win32/thread.c index f231e496f8..08de7125c6 100644 --- a/src/win32/thread.c +++ b/src/win32/thread.c @@ -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; }