From 1d8af5a018282dc6a93b9ed7c87d9d2f87287b14 Mon Sep 17 00:00:00 2001 From: Joel Klinghed Date: Mon, 13 Jul 2015 13:04:24 +0200 Subject: Copy the dependencies from sawmill project --- src/thread.h | 266 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 src/thread.h (limited to 'src/thread.h') diff --git a/src/thread.h b/src/thread.h new file mode 100644 index 0000000..c0a21b0 --- /dev/null +++ b/src/thread.h @@ -0,0 +1,266 @@ +/** + * \file thread.h + * A collection of thread methods. + */ + +#ifndef THREAD_H +#define THREAD_H + +#include "timespec.h" + +#if HAVE_PTHREAD +#include +/** + * Opaque type defining an once variable. + */ +typedef pthread_once_t thread_once_t; +/** + * Init value for an once variable + */ +#define THREAD_ONCE_INIT PTHREAD_ONCE_INIT +#else +# error missing thread_once_t implementation +#endif + +/** + * Opaque type defining a joinable thread. + */ +typedef struct thread_t thread_t; +/** + * Opaque type defining an id. + */ +typedef struct thread_id_t thread_id_t; +/** + * Opaque type defining a lock. + */ +typedef struct thread_lock_t thread_lock_t; +/** + * Opaque type defining a conditional. + */ +typedef struct thread_cond_t thread_cond_t; +/** + * Opaque type defining a thread local variable. + */ +typedef struct thread_data_t thread_data_t; + +/** + * Signature or function type for a thread run method. + * A thread run method is the thread main() if you will. + * When the method returns the thread is terminated. + * @param userdata argument given when starting the thread + */ +typedef void* (* thread_run_t)(void* userdata); + +/** + * Create and start a thread. + * @param run thread run method + * @param userdata argument to run method, may not be NULL + * @return true if thread was started without errors, may be NULL + */ +NONULL_ARGS(1) +bool thread_new(thread_run_t run, void* userdata); + +/** + * Create and start a joinable thread. + * Must call thread_join to free thread resources. + * @param run thread run method, may not be NULL + * @param userdata argument to run method, may be NULL + * @return NULL in case of error + */ +NONULL_ARGS(1) +MALLOC thread_t* thread_joinable_new(thread_run_t run, void* userdata); + +/** + * Wait for a joinable thread to exit, free it and return the result. + * @param thread result from call to thread_joinable_new, may not be NULL + * @return result of the thread run method + */ +NONULL void* thread_join(thread_t* thread); + + +/** + * Create a unique thread id pointing to the given or current thread. + * If no thread is given then a id for the current running thread is returned. + * Returns NULL in case of error. + * @param thread result from call to thread_joinable_new or NULL + * @return a new thread id + */ +MALLOC thread_id_t* thread_id_new(thread_t* thread); + +/** + * Free a thread id. + * @param id thread id to free, may be NULL + */ +void thread_id_free(thread_id_t* id); + +/** + * Return true if the current thread matches the thread id. + * @param id thread id to check, may not be NULL + * @return true if the id matches the current thread + */ +NONULL bool thread_id_is_current(thread_id_t* id); + +/** + * Thread yield, give another thread the chance to run. + */ +void thread_yield(void); + +/** + * Create a possibly non-recursive lock (mutex). + * Returns NULL in case of error. + * @return a new thread lock + */ +MALLOC thread_lock_t* thread_lock_new(void); + +/** + * Create a recursive lock (mutex). + * Returns NULL in case of error. + * @return a new thread lock + */ +MALLOC thread_lock_t* thread_lock_recursive_new(void); + +/** + * Free a lock. + * The lock must not have a owner when freed or undefined behaviour will ensue. + * @param lock lock to free, may be NULL + */ +void thread_lock_free(thread_lock_t* lock); + +/** + * Take ownership of the lock. + * If another thread has ownership of the lock, wait until that thread releases + * the lock. + * If the current thread already has ownership of the lock and the lock is + * recursive the current thread now owns the lock twice. + * Undefined behavior (abort or deadlock probably) if the lock isn't recursive + * and the current thread already has ownership. + * @param lock lock to take ownership of + */ +NONULL void thread_lock_lock(thread_lock_t* lock); +/** + * Release ownership of the lock. + * Only call if the current thread has one or more ownerships of the lock. + * If the lock is recursive only one ownership is released. + * Undefined behaviour (abort or deadlock probably) if the lock isn't owned + * by the current thread. + * @param lock lock to release + */ +NONULL void thread_lock_unlock(thread_lock_t* lock); + +/** + * Create a conditional. Conditionals can be used to signal other threads + * that a condition has been fulfilled if they were waiting for it. + * Returns NULL in case of error. + * @return new conditional + */ +MALLOC thread_cond_t* thread_cond_new(void); +/** + * Free a conditional. No thread may be waiting on the conditional or undefined + * behaviour will ensue. + * @param cond conditional to free, may be NULL + */ +void thread_cond_free(thread_cond_t* cond); + +/** + * Setup the current thread to wait for the condition to be signalled. + * The lock must be owned by the current thread before calling and will be + * release while the current thread is waiting but reclaimed upon return. + * @param cond conditonal to wait upon, may not be NULL + * @param lock lock to release and retake ownership of, may not be NULL + */ +NONULL void thread_cond_wait(thread_cond_t* cond, thread_lock_t* lock); + +/** + * Setup the current thread to wait for the condition to be signalled until + * abstime. + * The lock must be owned by the current thread before calling and will be + * release while the current thread is waiting but reclaimed upon return. + * Use thread_abstime() to fill out the abstime. + * @param cond conditonal to wait upon, may not be NULL + * @param lock lock to release and retake ownership of, may not be NULL + * @param abstime time when to give up and return, may not be NULL + * @return true if the condition was signalled, false if it timed out + */ +NONULL bool thread_cond_timedwait(thread_cond_t* cond, thread_lock_t* lock, + const struct timespec *abstime); + +/** + * Signal one thread that is currently waiting on the given condition. + * The selected thread (which one is random) will be woken up. + * The calling thread may or may not own the lock when calling + * thread_cond_signal but the signalled thread will not wake up before the lock + * is released. + * @param cond conditional to signal, may not be NULL + */ +NONULL void thread_cond_signal(thread_cond_t* cond); + +/** + * Signal all threads that is currently waiting on the given condition. + * All waiting threads will be woken up but only one may get ownership + * of the lock. + * The calling thread may or may not own the lock when calling + * thread_cond_broadcast but the signalled threads will not wake up before the + * lock is released. + * @param cond conditional to signal, may not be NULL + */ +NONULL void thread_cond_broadcast(thread_cond_t* cond); + +/** + * Get the current absolute time and add a certain number of milliseconds + * to it. To be used with thread_cond_timedwait. + * @param abstime struct to file with the current absolute time and the + * extra milliseconds. + * @param add_ms milliseconds to add to the current absolute time + */ +NONULL void thread_abstime(struct timespec *abstime, unsigned long add_ms); + +/** + * Function type for a thread local variable value destructor + */ +typedef void (* thread_data_value_free_t)(void *value); + +/** + * Create a thread local variable. + * Returns NULL in case of error. + * @param free_value destructor for set non-null value at thread exit, + * may be NULL + * @return new thread local variable or NULL + */ +MALLOC thread_data_t *thread_data_new(thread_data_value_free_t free_value); + +/** + * Free a thread local variable. + * Does not call any destructor. + * @param data thread local variable to free, may be NULL + */ +void thread_data_free(thread_data_t *data); + +/** + * Get the thread local value of the variable. + * @param data thread local variable, may not be NULL + * @return thread local value for variable + */ +NONULL void *thread_data_value(thread_data_t *data); + +/** + * Set thread local value for variable. + * @param data thread local variable, may not be NULL + * @param value new value, may be NULL + */ +NONULL_ARGS(1) +void thread_data_set(thread_data_t *data, void *value); + +/** + * Function type for a thread once method + */ +typedef void (* thread_run_once_t)(void); + +/** + * The first thread calling this method will run "run". Any subsequent thread + * calling thread_once for the same once variable will do nothing. + * @param once address to a static once variable, may not be NULL + * @param run method to run if this is the first thread, may not be NULL + */ +NONULL void thread_once(thread_once_t *once, thread_run_once_t run); + +#endif /* THREAD_H */ -- cgit v1.2.3-70-g09d2