avutil/thread: Add pthread_cond_timedwait function
authorMatt Oliver <protogonoi@gmail.com>
Wed, 7 Dec 2016 05:55:35 +0000 (16:55 +1100)
committerMarton Balint <cus@passwd.hu>
Tue, 21 Jan 2020 21:34:15 +0000 (22:34 +0100)
v2: fix calculating milisecond times and use SleepConditionVariableSRW.

Signed-off-by: Matt Oliver <protogonoi@gmail.com>
compat/os2threads.h
compat/w32pthreads.h
libavutil/thread.h

index 2177a03..eec6f40 100644 (file)
 
 #undef __STRICT_ANSI__          /* for _beginthread() */
 #include <stdlib.h>
+#include <time.h>
 
 #include <sys/builtin.h>
 #include <sys/fmutex.h>
 
 #include "libavutil/attributes.h"
+#include "libavutil/common.h"
+#include "libavutil/time.h"
 
 typedef struct {
     TID tid;
@@ -163,6 +166,28 @@ static av_always_inline int pthread_cond_broadcast(pthread_cond_t *cond)
     return 0;
 }
 
+static av_always_inline int pthread_cond_timedwait(pthread_cond_t *cond,
+                                                   pthread_mutex_t *mutex,
+                                                   const struct timespec *abstime)
+{
+    int64_t abs_milli = abstime->tv_sec * 1000LL + abstime->tv_nsec / 1000000;
+    ULONG t = av_clip64(abs_milli - av_gettime() / 1000, 0, ULONG_MAX);
+
+    __atomic_increment(&cond->wait_count);
+
+    pthread_mutex_unlock(mutex);
+
+    APIRET ret = DosWaitEventSem(cond->event_sem, t);
+
+    __atomic_decrement(&cond->wait_count);
+
+    DosPostEventSem(cond->ack_sem);
+
+    pthread_mutex_lock(mutex);
+
+    return (ret == ERROR_TIMEOUT) ? ETIMEDOUT : 0;
+}
+
 static av_always_inline int pthread_cond_wait(pthread_cond_t *cond,
                                               pthread_mutex_t *mutex)
 {
index 21acfd2..7df33b7 100644 (file)
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #include <process.h>
+#include <time.h>
 
 #include "libavutil/attributes.h"
 #include "libavutil/common.h"
 #include "libavutil/internal.h"
 #include "libavutil/mem.h"
+#include "libavutil/time.h"
 
 typedef struct pthread_t {
     void *handle;
@@ -156,6 +158,22 @@ static inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex
     return 0;
 }
 
+static inline int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+                                         const struct timespec *abstime)
+{
+    int64_t abs_milli = abstime->tv_sec * 1000LL + abstime->tv_nsec / 1000000;
+    DWORD t = av_clip64(abs_milli - av_gettime() / 1000, 0, UINT32_MAX);
+
+    if (!SleepConditionVariableSRW(cond, mutex, t, 0)) {
+        DWORD err = GetLastError();
+        if (err == ERROR_TIMEOUT)
+            return ETIMEDOUT;
+        else
+            return EINVAL;
+    }
+    return 0;
+}
+
 static inline int pthread_cond_signal(pthread_cond_t *cond)
 {
     WakeConditionVariable(cond);
index cc5272d..65b97ef 100644 (file)
@@ -109,6 +109,12 @@ static inline int strict_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t
     ASSERT_PTHREAD(pthread_cond_wait, cond, mutex);
 }
 
+static inline int strict_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+                                                const struct timespec *abstime)
+{
+    ASSERT_PTHREAD(pthread_cond_timedwait, cond, mutex, abstime);
+}
+
 static inline int strict_pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
 {
     ASSERT_PTHREAD(pthread_once, once_control, init_routine);
@@ -124,6 +130,7 @@ static inline int strict_pthread_once(pthread_once_t *once_control, void (*init_
 #define pthread_cond_signal    strict_pthread_cond_signal
 #define pthread_cond_broadcast strict_pthread_cond_broadcast
 #define pthread_cond_wait      strict_pthread_cond_wait
+#define pthread_cond_timedwait strict_pthread_cond_timedwait
 #define pthread_once           strict_pthread_once
 #endif