[vlc-commits] threads: add one-time initializer vlc_once()
Rémi Denis-Courmont
git at videolan.org
Sun Feb 11 16:29:38 CET 2018
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sun Feb 11 17:20:46 2018 +0200| [71d2d7c5a2adcf3cd41118eeba2ad40ee901304f] | committer: Rémi Denis-Courmont
threads: add one-time initializer vlc_once()
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=71d2d7c5a2adcf3cd41118eeba2ad40ee901304f
---
include/vlc_threads.h | 38 +++++++++++++++++++++++++++++++++++++-
src/android/thread.c | 6 ++++++
src/darwin/thread.c | 6 ++++++
src/libvlccore.sym | 1 +
src/posix/thread.c | 6 ++++++
src/win32/thread.c | 16 ++++++++++++++++
6 files changed, 72 insertions(+), 1 deletion(-)
diff --git a/include/vlc_threads.h b/include/vlc_threads.h
index 960d458bb2..f2c6eb3766 100644
--- a/include/vlc_threads.h
+++ b/include/vlc_threads.h
@@ -72,6 +72,8 @@ typedef struct
#define LIBVLC_NEED_CONDVAR
#define LIBVLC_NEED_SEMAPHORE
#define LIBVLC_NEED_RWLOCK
+typedef INIT_ONCE vlc_once_t;
+#define VLC_STATIC_ONCE INIT_ONCE_STATIC_INIT
typedef struct vlc_threadvar *vlc_threadvar_t;
typedef struct vlc_timer *vlc_timer_t;
@@ -171,7 +173,8 @@ typedef struct vlc_thread *vlc_thread_t;
#define VLC_THREAD_CANCELED NULL
typedef pthread_mutex_t vlc_mutex_t;
#define VLC_STATIC_MUTEX PTHREAD_MUTEX_INITIALIZER
-
+typedef pthread_once_t vlc_once_t;
+#define VLC_STATIC_ONCE PTHREAD_ONCE_INITIALIZER
typedef pthread_key_t vlc_threadvar_t;
typedef struct vlc_timer *vlc_timer_t;
@@ -221,6 +224,8 @@ typedef pthread_cond_t vlc_cond_t;
typedef semaphore_t vlc_sem_t;
typedef pthread_rwlock_t vlc_rwlock_t;
#define VLC_STATIC_RWLOCK PTHREAD_RWLOCK_INITIALIZER
+typedef pthread_once_t vlc_once_t;
+#define VLC_STATIC_ONCE PTHREAD_ONCE_INITIALIZER
typedef pthread_key_t vlc_threadvar_t;
typedef struct vlc_timer *vlc_timer_t;
@@ -309,6 +314,19 @@ typedef pthread_rwlock_t vlc_rwlock_t;
#define VLC_STATIC_RWLOCK PTHREAD_RWLOCK_INITIALIZER
/**
+ * One-time initialization.
+ *
+ * A one-time initialization object must always be initialized assigned to
+ * \ref VLC_STATIC_ONCE before use.
+ */
+typedef pthread_once_t vlc_once_t;
+
+/**
+ * Static initializer for one-time initialization.
+ */
+#define VLC_STATIC_ONCE PTHREAD_ONCE_INITIALIZER
+
+/**
* Thread-local key handle.
*/
typedef pthread_key_t vlc_threadvar_t;
@@ -585,6 +603,24 @@ VLC_API void vlc_rwlock_wrlock(vlc_rwlock_t *);
VLC_API void vlc_rwlock_unlock(vlc_rwlock_t *);
/**
+ * Executes a function one time.
+ *
+ * The first time this function is called with a given one-time initialization
+ * object, it executes the provided callback.
+ * Any further call with the same object will be a no-op.
+ *
+ * In the corner case that the first time execution is ongoing in another
+ * thread, then the function will wait for completion on the other thread
+ * (and then synchronize memory) before it returns.
+ * This ensures that, no matter what, the callback has been executed exactly
+ * once and its side effects are visible after the function returns.
+ *
+ * \param once a one-time initialization object
+ * \param cb callback to execute (the first time)
+ */
+VLC_API void vlc_once(vlc_once_t *restrict once, void (*cb)(void));
+
+/**
* Allocates a thread-specific variable.
*
* @param key where to store the thread-specific variable handle
diff --git a/src/android/thread.c b/src/android/thread.c
index 3f8062753e..46e1c27892 100644
--- a/src/android/thread.c
+++ b/src/android/thread.c
@@ -141,6 +141,12 @@ void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
VLC_THREAD_ASSERT ("unlocking mutex");
}
+void vlc_once(vlc_once_t *once, void (*cb)(void))
+{
+ int val = pthread_once(once, cb);
+ VLC_THREAD_ASSERT("initializing once");
+}
+
struct vlc_thread
{
pthread_t thread;
diff --git a/src/darwin/thread.c b/src/darwin/thread.c
index b4991fa4c9..22660c0ee8 100644
--- a/src/darwin/thread.c
+++ b/src/darwin/thread.c
@@ -369,6 +369,12 @@ void vlc_rwlock_unlock (vlc_rwlock_t *lock)
VLC_THREAD_ASSERT ("releasing R/W lock");
}
+void vlc_once(vlc_once_t *once, void (*cb)(void))
+{
+ int val = pthread_once(once, cb);
+ VLC_THREAD_ASSERT("initializing once");
+}
+
int vlc_threadvar_create (vlc_threadvar_t *key, void (*destr) (void *))
{
return pthread_key_create (key, destr);
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index a15ba0d923..e6f3abff34 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -643,6 +643,7 @@ vlc_object_find_name
vlc_object_hold
vlc_object_release
vlc_object_get_name
+vlc_once
vlc_rand_bytes
vlc_drand48
vlc_lrand48
diff --git a/src/posix/thread.c b/src/posix/thread.c
index df7ce867b2..352b37d871 100644
--- a/src/posix/thread.c
+++ b/src/posix/thread.c
@@ -367,6 +367,12 @@ void vlc_rwlock_unlock (vlc_rwlock_t *lock)
VLC_THREAD_ASSERT ("releasing R/W lock");
}
+void vlc_once(vlc_once_t *once, void (*cb)(void))
+{
+ int val = pthread_once(once, cb);
+ VLC_THREAD_ASSERT("initializing once");
+}
+
int vlc_threadvar_create (vlc_threadvar_t *key, void (*destr) (void *))
{
return pthread_key_create (key, destr);
diff --git a/src/win32/thread.c b/src/win32/thread.c
index 9a20af04fa..b40f64cd52 100644
--- a/src/win32/thread.c
+++ b/src/win32/thread.c
@@ -196,6 +196,22 @@ void vlc_sem_wait (vlc_sem_t *sem)
}
#endif
+/*** One-time initialization ***/
+static BOOL CALLBACK vlc_once_callback(INIT_ONCE *once, void *parm, void **ctx)
+{
+ void (*cb)(void) = parm;
+
+ cb();
+ (void) once;
+ (void) ctx;
+ return TRUE;
+}
+
+void vlc_once(vlc_once_t *once, void (*cb)(void))
+{
+ InitOnceExecuteOnce(once, vlc_once_callback, cb, NULL);
+}
+
/*** Thread-specific variables (TLS) ***/
struct vlc_threadvar
{
More information about the vlc-commits
mailing list