[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