[vlc-devel] commit: vlc_cond_init_daytime: condition variable with the wall clock ( Rémi Denis-Courmont )

git version control git at videolan.org
Mon Feb 8 17:46:36 CET 2010


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Mon Feb  8 18:46:02 2010 +0200| [a160b8589331960e47702e382794d492ee480946] | committer: Rémi Denis-Courmont 

vlc_cond_init_daytime: condition variable with the wall clock

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=a160b8589331960e47702e382794d492ee480946
---

 include/vlc_threads.h |    8 ++++++-
 src/libvlccore.sym    |    1 +
 src/misc/pthread.c    |   25 +++++++++++++++++++----
 src/win32/thread.c    |   51 ++++++++++++++++++++++++++++++++++++++----------
 4 files changed, 68 insertions(+), 17 deletions(-)

diff --git a/include/vlc_threads.h b/include/vlc_threads.h
index c303420..8bff238 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 d608ab3..e0c53b3 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 4522db0..ca422cf 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;
 
@@ -280,6 +280,17 @@ void vlc_cond_init( vlc_cond_t *p_condvar )
 }
 
 /**
+ * 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.
  * @param p_condvar condition variable to destroy
@@ -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 f231e49..08de712 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;
 }




More information about the vlc-devel mailing list