Commit fa9fc74f authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

threads: add one-time initializer vlc_once()

parent a60834c4
......@@ -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_INIT
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_INIT
typedef pthread_key_t vlc_threadvar_t;
typedef struct vlc_timer *vlc_timer_t;
......@@ -308,6 +313,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_INIT
/**
* Thread-local key handle.
*/
......@@ -584,6 +602,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.
*
......
......@@ -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;
......
......@@ -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);
......
......@@ -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
......
......@@ -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);
......
......@@ -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
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment