twitchapon-anim

Basic Twitchapon Receiver/Visuals
git clone git://bsandro.tech/twitchapon-anim
Log | Files | Refs | README | LICENSE

tinycthread.h (15660B)


      1 /* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; -*-
      2 Copyright (c) 2012 Marcus Geelnard
      3 
      4 This software is provided 'as-is', without any express or implied
      5 warranty. In no event will the authors be held liable for any damages
      6 arising from the use of this software.
      7 
      8 Permission is granted to anyone to use this software for any purpose,
      9 including commercial applications, and to alter it and redistribute it
     10 freely, subject to the following restrictions:
     11 
     12     1. The origin of this software must not be misrepresented; you must not
     13     claim that you wrote the original software. If you use this software
     14     in a product, an acknowledgment in the product documentation would be
     15     appreciated but is not required.
     16 
     17     2. Altered source versions must be plainly marked as such, and must not be
     18     misrepresented as being the original software.
     19 
     20     3. This notice may not be removed or altered from any source
     21     distribution.
     22 */
     23 
     24 #ifndef _TINYCTHREAD_H_
     25 #define _TINYCTHREAD_H_
     26 
     27 /**
     28 * @file
     29 * @mainpage TinyCThread API Reference
     30 *
     31 * @section intro_sec Introduction
     32 * TinyCThread is a minimal, portable implementation of basic threading
     33 * classes for C.
     34 *
     35 * They closely mimic the functionality and naming of the C11 standard, and
     36 * should be easily replaceable with the corresponding standard variants.
     37 *
     38 * @section port_sec Portability
     39 * The Win32 variant uses the native Win32 API for implementing the thread
     40 * classes, while for other systems, the POSIX threads API (pthread) is used.
     41 *
     42 * @section misc_sec Miscellaneous
     43 * The following special keywords are available: #_Thread_local.
     44 *
     45 * For more detailed information, browse the different sections of this
     46 * documentation. A good place to start is:
     47 * tinycthread.h.
     48 */
     49 
     50 /* Which platform are we on? */
     51 #if !defined(_TTHREAD_PLATFORM_DEFINED_)
     52   #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
     53     #define _TTHREAD_WIN32_
     54   #else
     55     #define _TTHREAD_POSIX_
     56   #endif
     57   #define _TTHREAD_PLATFORM_DEFINED_
     58 #endif
     59 
     60 /* Activate some POSIX functionality (e.g. clock_gettime and recursive mutexes) */
     61 #if defined(_TTHREAD_POSIX_)
     62   #undef _FEATURES_H
     63   #if !defined(_GNU_SOURCE)
     64     #define _GNU_SOURCE
     65   #endif
     66   #if !defined(_POSIX_C_SOURCE) || ((_POSIX_C_SOURCE - 0) < 199309L)
     67     #undef _POSIX_C_SOURCE
     68     #define _POSIX_C_SOURCE 199309L
     69   #endif
     70   #if !defined(_XOPEN_SOURCE) || ((_XOPEN_SOURCE - 0) < 500)
     71     #undef _XOPEN_SOURCE
     72     #define _XOPEN_SOURCE 500
     73   #endif
     74 #endif
     75 
     76 /* Generic includes */
     77 #include <time.h>
     78 
     79 /* Platform specific includes */
     80 #if defined(_TTHREAD_POSIX_)
     81   #include <sys/time.h>
     82   #include <pthread.h>
     83 #elif defined(_TTHREAD_WIN32_)
     84   #ifndef WIN32_LEAN_AND_MEAN
     85     #define WIN32_LEAN_AND_MEAN
     86     #define __UNDEF_LEAN_AND_MEAN
     87   #endif
     88   #include <windows.h>
     89   #ifdef __UNDEF_LEAN_AND_MEAN
     90     #undef WIN32_LEAN_AND_MEAN
     91     #undef __UNDEF_LEAN_AND_MEAN
     92   #endif
     93 #endif
     94 
     95 /* Workaround for missing TIME_UTC: If time.h doesn't provide TIME_UTC,
     96    it's quite likely that libc does not support it either. Hence, fall back to
     97    the only other supported time specifier: CLOCK_REALTIME (and if that fails,
     98    we're probably emulating clock_gettime anyway, so anything goes). */
     99 #ifndef TIME_UTC
    100   #ifdef CLOCK_REALTIME
    101     #define TIME_UTC CLOCK_REALTIME
    102   #else
    103     #define TIME_UTC 0
    104   #endif
    105 #endif
    106 
    107 /* Workaround for missing clock_gettime (most Windows compilers, afaik) */
    108 #if defined(_TTHREAD_WIN32_) || defined(__APPLE_CC__)
    109 #define _TTHREAD_EMULATE_CLOCK_GETTIME_
    110 /* Emulate struct timespec */
    111 #if defined(_TTHREAD_WIN32_)
    112 struct _ttherad_timespec {
    113   time_t tv_sec;
    114   long   tv_nsec;
    115 };
    116 #define timespec _ttherad_timespec
    117 #endif
    118 
    119 /* Emulate clockid_t */
    120 typedef int _tthread_clockid_t;
    121 #define clockid_t _tthread_clockid_t
    122 
    123 /* Emulate clock_gettime */
    124 int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts);
    125 #define clock_gettime _tthread_clock_gettime
    126 #ifndef CLOCK_REALTIME
    127   #define CLOCK_REALTIME 0
    128 #endif
    129 #endif
    130 
    131 
    132 /** TinyCThread version (major number). */
    133 #define TINYCTHREAD_VERSION_MAJOR 1
    134 /** TinyCThread version (minor number). */
    135 #define TINYCTHREAD_VERSION_MINOR 1
    136 /** TinyCThread version (full version). */
    137 #define TINYCTHREAD_VERSION (TINYCTHREAD_VERSION_MAJOR * 100 + TINYCTHREAD_VERSION_MINOR)
    138 
    139 /**
    140 * @def _Thread_local
    141 * Thread local storage keyword.
    142 * A variable that is declared with the @c _Thread_local keyword makes the
    143 * value of the variable local to each thread (known as thread-local storage,
    144 * or TLS). Example usage:
    145 * @code
    146 * // This variable is local to each thread.
    147 * _Thread_local int variable;
    148 * @endcode
    149 * @note The @c _Thread_local keyword is a macro that maps to the corresponding
    150 * compiler directive (e.g. @c __declspec(thread)).
    151 * @note This directive is currently not supported on Mac OS X (it will give
    152 * a compiler error), since compile-time TLS is not supported in the Mac OS X
    153 * executable format. Also, some older versions of MinGW (before GCC 4.x) do
    154 * not support this directive.
    155 * @hideinitializer
    156 */
    157 
    158 /* FIXME: Check for a PROPER value of __STDC_VERSION__ to know if we have C11 */
    159 #if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) && !defined(_Thread_local)
    160  #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
    161   #define _Thread_local __thread
    162  #else
    163   #define _Thread_local __declspec(thread)
    164  #endif
    165 #endif
    166 
    167 /* Macros */
    168 #define TSS_DTOR_ITERATIONS 0
    169 
    170 /* Function return values */
    171 #define thrd_error    0 /**< The requested operation failed */
    172 #define thrd_success  1 /**< The requested operation succeeded */
    173 #define thrd_timeout  2 /**< The time specified in the call was reached without acquiring the requested resource */
    174 #define thrd_busy     3 /**< The requested operation failed because a tesource requested by a test and return function is already in use */
    175 #define thrd_nomem    4 /**< The requested operation failed because it was unable to allocate memory */
    176 
    177 /* Mutex types */
    178 #define mtx_plain     1
    179 #define mtx_timed     2
    180 #define mtx_try       4
    181 #define mtx_recursive 8
    182 
    183 /* Mutex */
    184 #if defined(_TTHREAD_WIN32_)
    185 typedef struct {
    186   CRITICAL_SECTION mHandle;   /* Critical section handle */
    187   int mAlreadyLocked;         /* TRUE if the mutex is already locked */
    188   int mRecursive;             /* TRUE if the mutex is recursive */
    189 } mtx_t;
    190 #else
    191 typedef pthread_mutex_t mtx_t;
    192 #endif
    193 
    194 /** Create a mutex object.
    195 * @param mtx A mutex object.
    196 * @param type Bit-mask that must have one of the following six values:
    197 *   @li @c mtx_plain for a simple non-recursive mutex
    198 *   @li @c mtx_timed for a non-recursive mutex that supports timeout
    199 *   @li @c mtx_try for a non-recursive mutex that supports test and return
    200 *   @li @c mtx_plain | @c mtx_recursive (same as @c mtx_plain, but recursive)
    201 *   @li @c mtx_timed | @c mtx_recursive (same as @c mtx_timed, but recursive)
    202 *   @li @c mtx_try | @c mtx_recursive (same as @c mtx_try, but recursive)
    203 * @return @ref thrd_success on success, or @ref thrd_error if the request could
    204 * not be honored.
    205 */
    206 int mtx_init(mtx_t *mtx, int type);
    207 
    208 /** Release any resources used by the given mutex.
    209 * @param mtx A mutex object.
    210 */
    211 void mtx_destroy(mtx_t *mtx);
    212 
    213 /** Lock the given mutex.
    214 * Blocks until the given mutex can be locked. If the mutex is non-recursive, and
    215 * the calling thread already has a lock on the mutex, this call will block
    216 * forever.
    217 * @param mtx A mutex object.
    218 * @return @ref thrd_success on success, or @ref thrd_error if the request could
    219 * not be honored.
    220 */
    221 int mtx_lock(mtx_t *mtx);
    222 
    223 /** NOT YET IMPLEMENTED.
    224 */
    225 int mtx_timedlock(mtx_t *mtx, const struct timespec *ts);
    226 
    227 /** Try to lock the given mutex.
    228 * The specified mutex shall support either test and return or timeout. If the
    229 * mutex is already locked, the function returns without blocking.
    230 * @param mtx A mutex object.
    231 * @return @ref thrd_success on success, or @ref thrd_busy if the resource
    232 * requested is already in use, or @ref thrd_error if the request could not be
    233 * honored.
    234 */
    235 int mtx_trylock(mtx_t *mtx);
    236 
    237 /** Unlock the given mutex.
    238 * @param mtx A mutex object.
    239 * @return @ref thrd_success on success, or @ref thrd_error if the request could
    240 * not be honored.
    241 */
    242 int mtx_unlock(mtx_t *mtx);
    243 
    244 /* Condition variable */
    245 #if defined(_TTHREAD_WIN32_)
    246 typedef struct {
    247   HANDLE mEvents[2];                  /* Signal and broadcast event HANDLEs. */
    248   unsigned int mWaitersCount;         /* Count of the number of waiters. */
    249   CRITICAL_SECTION mWaitersCountLock; /* Serialize access to mWaitersCount. */
    250 } cnd_t;
    251 #else
    252 typedef pthread_cond_t cnd_t;
    253 #endif
    254 
    255 /** Create a condition variable object.
    256 * @param cond A condition variable object.
    257 * @return @ref thrd_success on success, or @ref thrd_error if the request could
    258 * not be honored.
    259 */
    260 int cnd_init(cnd_t *cond);
    261 
    262 /** Release any resources used by the given condition variable.
    263 * @param cond A condition variable object.
    264 */
    265 void cnd_destroy(cnd_t *cond);
    266 
    267 /** Signal a condition variable.
    268 * Unblocks one of the threads that are blocked on the given condition variable
    269 * at the time of the call. If no threads are blocked on the condition variable
    270 * at the time of the call, the function does nothing and return success.
    271 * @param cond A condition variable object.
    272 * @return @ref thrd_success on success, or @ref thrd_error if the request could
    273 * not be honored.
    274 */
    275 int cnd_signal(cnd_t *cond);
    276 
    277 /** Broadcast a condition variable.
    278 * Unblocks all of the threads that are blocked on the given condition variable
    279 * at the time of the call. If no threads are blocked on the condition variable
    280 * at the time of the call, the function does nothing and return success.
    281 * @param cond A condition variable object.
    282 * @return @ref thrd_success on success, or @ref thrd_error if the request could
    283 * not be honored.
    284 */
    285 int cnd_broadcast(cnd_t *cond);
    286 
    287 /** Wait for a condition variable to become signaled.
    288 * The function atomically unlocks the given mutex and endeavors to block until
    289 * the given condition variable is signaled by a call to cnd_signal or to
    290 * cnd_broadcast. When the calling thread becomes unblocked it locks the mutex
    291 * before it returns.
    292 * @param cond A condition variable object.
    293 * @param mtx A mutex object.
    294 * @return @ref thrd_success on success, or @ref thrd_error if the request could
    295 * not be honored.
    296 */
    297 int cnd_wait(cnd_t *cond, mtx_t *mtx);
    298 
    299 /** Wait for a condition variable to become signaled.
    300 * The function atomically unlocks the given mutex and endeavors to block until
    301 * the given condition variable is signaled by a call to cnd_signal or to
    302 * cnd_broadcast, or until after the specified time. When the calling thread
    303 * becomes unblocked it locks the mutex before it returns.
    304 * @param cond A condition variable object.
    305 * @param mtx A mutex object.
    306 * @param xt A point in time at which the request will time out (absolute time).
    307 * @return @ref thrd_success upon success, or @ref thrd_timeout if the time
    308 * specified in the call was reached without acquiring the requested resource, or
    309 * @ref thrd_error if the request could not be honored.
    310 */
    311 int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts);
    312 
    313 /* Thread */
    314 #if defined(_TTHREAD_WIN32_)
    315 typedef HANDLE thrd_t;
    316 #else
    317 typedef pthread_t thrd_t;
    318 #endif
    319 
    320 /** Thread start function.
    321 * Any thread that is started with the @ref thrd_create() function must be
    322 * started through a function of this type.
    323 * @param arg The thread argument (the @c arg argument of the corresponding
    324 *        @ref thrd_create() call).
    325 * @return The thread return value, which can be obtained by another thread
    326 * by using the @ref thrd_join() function.
    327 */
    328 typedef int (*thrd_start_t)(void *arg);
    329 
    330 /** Create a new thread.
    331 * @param thr Identifier of the newly created thread.
    332 * @param func A function pointer to the function that will be executed in
    333 *        the new thread.
    334 * @param arg An argument to the thread function.
    335 * @return @ref thrd_success on success, or @ref thrd_nomem if no memory could
    336 * be allocated for the thread requested, or @ref thrd_error if the request
    337 * could not be honored.
    338 * @note A thread’s identifier may be reused for a different thread once the
    339 * original thread has exited and either been detached or joined to another
    340 * thread.
    341 */
    342 int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
    343 
    344 /** Identify the calling thread.
    345 * @return The identifier of the calling thread.
    346 */
    347 thrd_t thrd_current(void);
    348 
    349 /** NOT YET IMPLEMENTED.
    350 */
    351 int thrd_detach(thrd_t thr);
    352 
    353 /** Compare two thread identifiers.
    354 * The function determines if two thread identifiers refer to the same thread.
    355 * @return Zero if the two thread identifiers refer to different threads.
    356 * Otherwise a nonzero value is returned.
    357 */
    358 int thrd_equal(thrd_t thr0, thrd_t thr1);
    359 
    360 /** Terminate execution of the calling thread.
    361 * @param res Result code of the calling thread.
    362 */
    363 void thrd_exit(int res);
    364 
    365 /** Wait for a thread to terminate.
    366 * The function joins the given thread with the current thread by blocking
    367 * until the other thread has terminated.
    368 * @param thr The thread to join with.
    369 * @param res If this pointer is not NULL, the function will store the result
    370 *        code of the given thread in the integer pointed to by @c res.
    371 * @return @ref thrd_success on success, or @ref thrd_error if the request could
    372 * not be honored.
    373 */
    374 int thrd_join(thrd_t thr, int *res);
    375 
    376 /** Put the calling thread to sleep.
    377 * Suspend execution of the calling thread.
    378 * @param time_point A point in time at which the thread will resume (absolute time).
    379 * @param remaining If non-NULL, this parameter will hold the remaining time until
    380 *                  time_point upon return. This will typically be zero, but if
    381 *                  the thread was woken up by a signal that is not ignored before
    382 *                  time_point was reached @c remaining will hold a positive
    383 *                  time.
    384 * @return 0 (zero) on successful sleep, or -1 if an interrupt occurred.
    385 */
    386 int thrd_sleep(const struct timespec *time_point, struct timespec *remaining);
    387 
    388 /** Yield execution to another thread.
    389 * Permit other threads to run, even if the current thread would ordinarily
    390 * continue to run.
    391 */
    392 void thrd_yield(void);
    393 
    394 /* Thread local storage */
    395 #if defined(_TTHREAD_WIN32_)
    396 typedef DWORD tss_t;
    397 #else
    398 typedef pthread_key_t tss_t;
    399 #endif
    400 
    401 /** Destructor function for a thread-specific storage.
    402 * @param val The value of the destructed thread-specific storage.
    403 */
    404 typedef void (*tss_dtor_t)(void *val);
    405 
    406 /** Create a thread-specific storage.
    407 * @param key The unique key identifier that will be set if the function is
    408 *        successful.
    409 * @param dtor Destructor function. This can be NULL.
    410 * @return @ref thrd_success on success, or @ref thrd_error if the request could
    411 * not be honored.
    412 * @note The destructor function is not supported under Windows. If @c dtor is
    413 * not NULL when calling this function under Windows, the function will fail
    414 * and return @ref thrd_error.
    415 */
    416 int tss_create(tss_t *key, tss_dtor_t dtor);
    417 
    418 /** Delete a thread-specific storage.
    419 * The function releases any resources used by the given thread-specific
    420 * storage.
    421 * @param key The key that shall be deleted.
    422 */
    423 void tss_delete(tss_t key);
    424 
    425 /** Get the value for a thread-specific storage.
    426 * @param key The thread-specific storage identifier.
    427 * @return The value for the current thread held in the given thread-specific
    428 * storage.
    429 */
    430 void *tss_get(tss_t key);
    431 
    432 /** Set the value for a thread-specific storage.
    433 * @param key The thread-specific storage identifier.
    434 * @param val The value of the thread-specific storage to set for the current
    435 *        thread.
    436 * @return @ref thrd_success on success, or @ref thrd_error if the request could
    437 * not be honored.
    438 */
    439 int tss_set(tss_t key, void *val);
    440 
    441 
    442 #endif /* _TINYTHREAD_H_ */
    443