Mstdlib-1.24.0
m_thread.h
1/* The MIT License (MIT)
2 *
3 * Copyright (c) 2015 Monetra Technologies, LLC.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24#ifndef __M_THREAD_H__
25#define __M_THREAD_H__
26
27/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
28
29#include <mstdlib/base/m_defs.h>
30#include <mstdlib/base/m_types.h>
31
32/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
33
34__BEGIN_DECLS
35
36/*! \addtogroup m_thread_common Common Threading Functions
37 * \ingroup m_thread
38 *
39 * Thread handling.
40 *
41 * System specific threading model as well as a cooperative threading model
42 * is available. Cooperative should only be used on system that do not natively
43 * support threads. Such as some embedded systems.
44 *
45 * By default threads are created in a detached state. M_thread_attr_t must be
46 * used in order to have a thread created in a joinable state.
47 *
48 * Example:
49 *
50 * \code{.c}
51 * static M_uint32 count = 0;
52 *
53 * static void td(void)
54 * {
55 * M_printf("Thread finished\n");
56 * }
57 *
58 * static void *runner(void *arg)
59 * {
60 * M_thread_mutex_t *m = arg;
61 *
62 * M_thread_mutex_lock(m);
63 * count++;
64 * M_thread_mutex_unlock(m);
65 * }
66 *
67 * int main(int argc, char **argv)
68 * {
69 * M_threadid_t t1;
70 * M_threadid_t t2;
71 * M_thread_attr_t *tattr;
72 * M_thread_mutex_t *m
73 *
74 * M_thread_destructor_insert(td);
75 *
76 * tattr = M_thread_attr_create();
77 * M_thread_attr_set_create_joinable(tattr, M_TRUE);
78 *
79 * m = M_thread_mutex_create(M_THREAD_MUTEXATTR_NONE);
80 *
81 * t1 = M_thread_create(tattr, runner, m);
82 * t2 = M_thread_create(tattr, runner, m);
83 *
84 * M_thread_attr_destroy(tattr);
85 * M_thread_join(t1, NULL);
86 * M_thread_join(t2, NULL);
87 *
88 * M_thread_mutex_destroy(m);
89 *
90 * M_printf("count='%u'\n", count);
91 *
92 * return 0;
93 * }
94 * \endcode
95 *
96 */
97
98/*! \addtogroup m_thread_common_main Thread System Initialization, Destruction, and Information
99 * \ingroup m_thread_common
100 *
101 * Thread System Initialization, Destruction, and Information
102 *
103 * @{
104 */
105
106
107/*! Thread model. */
108typedef enum {
109 M_THREAD_MODEL_INVALID = -1, /*!< Invalid/no model. */
110 M_THREAD_MODEL_NATIVE = 0, /*!< System's native thread model. */
111 M_THREAD_MODEL_COOP /*!< Cooperative threads. */
113
114
115/*! Initialize the thread model (system).
116 *
117 * This should be called before any other thread function is used. This will initialize
118 * the specified threading system. If this is not called before a thread function
119 * is used then the native threading model will be automatically initialized.
120 *
121 * Only one thread model can be use at any given time.
122 *
123 * \param[in] model The thread model that should be used for threading.
124 *
125 * \return M_TRUE if the model was successfully initialized. Otherwise M_FALSE.
126 * This can fail if called after a model has already been initialized.
127 */
128M_API M_bool M_thread_init(M_thread_model_t model);
129
130
131/*! Get the active thread model.
132 *
133 * \param[out] model The active model.
134 * \param[out] model_name The textual name of the model. This will provide descriptive information
135 * such as what is the underlying native threading model.
136 *
137 * \return M_TRUE if a thread model is active otherwise M_FALSE.
138 */
139M_API M_bool M_thread_active_model(M_thread_model_t *model, const char **model_name);
140
141
142/*! Adds a function to be called each time a thread finishes.
143 *
144 * Some libraries (OpenSSL in particular) keep their own per thread memory
145 * store. This allows registering functions to be called to handle this situation.
146 *
147 * OpenSSL keeps a per-thread error state which must be cleaned up at thread
148 * destruction otherwise it will leak memory like crazy. Wrap
149 * ERR_remove_state(0); in a function that doesn't take any arugments, then
150 * register the function and this problem is solved.
151 *
152 * Registered functions will be called in the order they were added.
153 *
154 * \param[in] destructor The function to register.
155 *
156 * \return M_TRUE if the function was added. Otherwise M_FALSE. This can fail
157 * if the function was already registered. A function can only be
158 * registered once.
159 */
160M_API M_bool M_thread_destructor_insert(void (*destructor)(void));
161
162
163/*! Remove a function from the list of function to be called each time a thread finished.
164 *
165 * \param[in] destructor The function to remove.
166 */
167M_API void M_thread_destructor_remove(void (*destructor)(void));
168
169
170/*! Thread-safe library cleanup.
171 *
172 * Cleans up any initialized static/global members by the library. Useful to
173 * be called at the end of program execution to free memory or other resources,
174 * especially if running under a leak checker such as Valgrind.
175 *
176 */
177M_API void M_library_cleanup(void);
178
179
180/*! Registers a callback to be called during M_library_cleanup().
181 *
182 * There is no way to 'unregister' a callback, so it must be ensured the callback
183 * will remain valid until the end of program execution.
184 *
185 * \param[in] cleanup_cb Callback to call for cleanup
186 * \param[in] arg Optional argument to be passed to the callback.
187 */
188M_API void M_library_cleanup_register(void (*cleanup_cb)(void *arg), void *arg);
189
190
191/*! Get the number of actively running threads. This count includes the main process thread.
192 *
193 * This count does not include the threads that have finished but are still joinable.
194 *
195 * \return Thread count.
196 */
197M_API size_t M_thread_count(void);
198
199
200/*! Retrieve the count of CPU cores that are online and usable. When using
201 * cooperative threading, only 1 cpu core is usable.
202 *
203 * \return count of cores or 0 on failure.
204 */
205M_API size_t M_thread_num_cpu_cores(void);
206
207
208/*! @} */
209
210/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
211
212/*! \addtogroup m_thread_common_create Thread Creation and Management
213 * \ingroup m_thread_common
214 *
215 * Thread Creation and Management
216 *
217 * @{
218 */
219
220/*! Thread id used to identify a thread.
221 *
222 * This can be compared with >, <, == and !=. */
223typedef M_uintptr M_threadid_t;
224
225
226/*! Thread attribute object used for thread creation. */
227struct M_thread_attr;
228typedef struct M_thread_attr M_thread_attr_t;
229
230
231
232/*! Create and run a thread.
233 *
234 * Threads are created detached by default.
235 * To create it joinable use a M_thread_attr_t and set
236 * it to joinable.
237 *
238 * \param[in] attr Thread creation attributes.
239 * \param[in] func The function to run.
240 * \param[in,out] arg Argument to pass to func.
241 *
242 * \return Threadid identifying the thread on success. Threadid will be 0 on failure.
243 */
244M_API M_threadid_t M_thread_create(const M_thread_attr_t *attr, void *(*func)(void *), void *arg);
245
246
247/*! Wait for a thread to finish.
248 *
249 * Only threads that were created with the joinable attribute set to M_TRUE can be used with this function.
250 *
251 * \param[in] id The threadid to wait on.
252 * \param[out] value_ptr The return value from the thread.
253 *
254 * \return M_TRUE if the thread was successfully joined. Otherwise M_FALSE.
255 */
256M_API M_bool M_thread_join(M_threadid_t id, void **value_ptr);
257
258
259/*! Get the threadid of the running thread.
260 *
261 * \return The threadid.
262 */
264
265/*! Minimum thread priority value */
266#define M_THREAD_PRIORITY_MIN 1
267
268/*! Normal thread priority value */
269#define M_THREAD_PRIORITY_NORMAL 5
270
271/*! Maximum thread priority value */
272#define M_THREAD_PRIORITY_MAX 9
273
274/*! Set the priority a given thread should be created with.
275 *
276 * \param[in] tid ThreadID returned from M_thread_create() or M_thread_self()
277 * \param[in] priority The priority to set. Valid range is 1-9 with 1 being the
278 * lowest priority and 9 being the highest. The default value
279 * is 5. Some systems, like Linux, do not support thread scheduling
280 * in relation to the process as a whole, but rather the system as
281 * a whole, and therefore require RLIMIT_NICE to be configured on
282 * the process in order to successfully increase a thread's priority
283 * above '5'.
284 * \return M_TRUE on success, or M_FALSE on usage error
285 */
286M_API M_bool M_thread_set_priority(M_threadid_t tid, M_uint8 priority);
287
288/*! Set the processor to assign the thread to run on (aka affinity). The range is
289 * 0 to M_thread_num_cpu_cores()-1, or -1 to unassign.
290 *
291 * \param[in] tid ThreadID returned from M_thread_create() or M_thread_self()
292 * \param[in] processor_id -1 to unset prior value.
293 * Otherwise 0 to M_thread_num_cpu_cores()-1 is the valid range.
294 * \return M_TRUE on success, or M_FALSE on usage error */
295M_API M_bool M_thread_set_processor(M_threadid_t tid, int processor_id);
296
297
298/*! Sleep for the specified amount of time.
299 *
300 * \param[in] usec Number of microseconds to sleep.
301 */
302M_API void M_thread_sleep(M_uint64 usec);
303
304
305/*! Inform the scheduler that we want to relinquish the CPU and allow other threads to process.
306 *
307 * \param[in] force Force rescheduling of this thread. When M_FALSE the thread model will determine
308 * if the thread needs to be rescheduled or not. A preemtive model will typically
309 * ignore this call when M_FALSE and rely on its scheduler. A non-preemptive model
310 * (COOP) will always yield.
311 */
312M_API void M_thread_yield(M_bool force);
313
314
315/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
316
317/*! Create a thread attribute object.
318 *
319 * \return Thread attribute object.
320 */
322
323
324/*! Destroy a thread attribute object.
325 *
326 * \param[in] attr Attribute object.
327 */
329
330
331/*! Get whether a given thread should be created joinable.
332 *
333 * \param[in] attr Attribute object.
334 *
335 * return M_TRUE if the thread should be joinable. Otherwise M_FALSE.
336 */
338
339
340/*! Get the stack size a given thread should use when created.
341 *
342 * This may not be used by all threading models.
343 *
344 * \param[in] attr Attribute object.
345 *
346 * return The requested stack size.
347 */
349
350
351/*! Get the priority a given thread should be created with.
352 *
353 * Thread priorities are 1-9, with 1 being the lowest priority and 9 being
354 * the highest. The default value is 5.
355 *
356 * \param[in] attr Attribute object.
357 *
358 * \return The requested priority, or 0 on usage error.
359 */
361
362
363/*! Set whether a given thread should be created joinable.
364 *
365 * The default is to create threads detached (not joinable) unless this is called
366 * and set to M_TRUE.
367 *
368 * \param[in] attr Attribute object.
369 * \param[in] val The value to set.
370 */
372
373
374/*! Set the stack size a given thread should be created with.
375 *
376 * \param[in] attr Attribute object.
377 * \param[in] val The value to set.
378 */
379M_API void M_thread_attr_set_stack_size(M_thread_attr_t *attr, size_t val);
380
381
382/*! Set the priority a given thread should be created with.
383 *
384 * \param[in] attr Attribute object.
385 * \param[in] priority The priority to set. Valid range is 1-9 with 1 being the
386 * lowest priority and 9 being the highest. The default value
387 * is 5. Some systems, like Linux, do not support thread scheduling
388 * in relation to the process as a whole, but rather the system as
389 * a whole, and therefore require RLIMIT_NICE to be configured on
390 * the process in order to successfully increase a thread's priority
391 * above '5'.
392 * \return M_TRUE on success, or M_FALSE on usage error
393 */
394M_API M_bool M_thread_attr_set_priority(M_thread_attr_t *attr, M_uint8 priority);
395
396/*! Get the currently assigned processor for thread.
397 *
398 * \param[in] attr Attribute object
399 * \return -1 if none specified, otherwise 0 to M_thread_num_cpu_cores()-1
400 */
402
403/*! Set the processor to assign the thread to run on (aka affinity). The range is
404 * 0 to M_thread_num_cpu_cores()-1.
405 *
406 * \param[in] attr Attribute object
407 * \param[in] processor_id -1 to unset prior value.
408 * Otherwise 0 to M_thread_num_cpu_cores()-1 is the valid range.
409 * \return M_TRUE on success, or M_FALSE on usage error */
410M_API M_bool M_thread_attr_set_processor(M_thread_attr_t *attr, int processor_id);
411
412/*! @} */
413
414
415
416/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
417/*! \addtogroup m_thread_common_mutex Thread Mutexes (Locks/Critical Sections)
418 * \ingroup m_thread_common
419 *
420 * Thread Mutexes (Locks/Critical Sections)
421 *
422 * @{
423 */
424
425/*! Mutex. */
426struct M_thread_mutex;
427typedef struct M_thread_mutex M_thread_mutex_t;
428
429
430/*! Mutex attributes.
431 * Used for mutex creation. */
432typedef enum {
433 M_THREAD_MUTEXATTR_NONE = 0, /*!< None. */
434 M_THREAD_MUTEXATTR_RECURSIVE = 1 << 0 /*!< Mutex is recursive. */
436
437
438/*! Mutex create.
439 *
440 * \param[in] attr M_thread_mutexattr_t attributes which control how the mutex should behave.
441 *
442 * \return Mutex on success otherwise NULL on error.
443 */
445
446
447/*! Destroy a mutex.
448 *
449 * \param[in] mutex The mutex.
450 */
452
453
454/*! Lock a mutex.
455 *
456 * This will block until the mutex can be locked.
457 *
458 * \param[in] mutex The mutex.
459 *
460 * \return M_TRUE if the function returns due to a successful mutex lock. Otherwise M_FALSE on error.
461 * This can fail for a number of reasons, for example:
462 * - The mutex was already locked by this thread.
463 * - The mutex is invalid.
464 * - The mutex has exceeded the maximum number of recursive locks.
465 */
467
468
469/*! Try to lock the mutex.
470 *
471 * Does not block waiting to lock the mutex.
472 *
473 * \param[in] mutex The mutex.
474 *
475 * \return M_TRUE if the mutex was locked. Otherwise M_FALSE.
476 */
478
479
480/*! Unlock a locked mutex.
481 *
482 * \param[in] mutex The mutex.
483 *
484 * \return M_TRUE if the mutex was unlocked. Otherwise M_FALSE.
485 */
487
488
489/*! @} */
490
491
492/*! \addtogroup m_thread_common_cond Thread Conditionals
493 * \ingroup m_thread_common
494 *
495 * Thread Conditionals
496 *
497 * @{
498 */
499
500/*! Conditional. */
501struct M_thread_cond;
502typedef struct M_thread_cond M_thread_cond_t;
503
504
505
506/*! Conditional attributes.
507 * Used for conditional creation. */
508typedef enum {
509 M_THREAD_CONDATTR_NONE = 0 /*!< None. */
511
512
513
514/*! Conditional create.
515 *
516 * \param[in] attr M_thread_condattr_t attributes which control how the conditional should behave.
517 *
518 * \return Conditional on success otherwise NULL on error.
519 */
521
522
523/*! Destroy a conditional.
524 *
525 * \param[in] cond The conditional.
526 */
528
529/*! Wait on conditional with a timeout of now + millisec.
530 *
531 * \param[in] cond The conditional.
532 * \param[in,out] mutex The mutex to operate on.
533 * \param[in] millisec The amount of time wait from now in milliseconds.
534 *
535 * \return M_TRUE if the conditional was activated. M_FALSE on timeout or other error.
536 *
537 * \see M_thread_cond_wait
538 * \see M_thread_cond_timedwait_abs
539 */
540M_API M_bool M_thread_cond_timedwait(M_thread_cond_t *cond, M_thread_mutex_t *mutex, M_uint64 millisec);
541
542
543/*! Wait on conditional until a specified time.
544 *
545 * \param[in] cond The conditional.
546 * \param[in,out] mutex The mutex to operate on.
547 * \param[in] abstime Time to wait until.
548 *
549 * \return M_TRUE if the conditional was activated. M_FALSE on timeout or other error.
550 *
551 * \see M_thread_cond_wait
552 * \see M_thread_cond_timedwait
553 */
555
556
557/*! Wait on conditional
558 *
559 * Blocks the thread until the conditional is activated.
560 *
561 * The mutex must be locked before calling this function. This will unlock the mutex and block
562 * on the conditional. When the conditional is activated the mutex will be locked.
563 *
564 * \param[in] cond The conditional.
565 * \param[in,out] mutex The mutex to operate on.
566 *
567 * \return M_TRUE if the conditional was activated. M_FALSE on error.
568 *
569 * \see M_thread_cond_timedwait
570 * \see M_thread_cond_timedwait_abs
571 */
573
574
575/*! Activate all waiting conditionals.
576 *
577 * \param[in] cond The conditional.
578 */
580
581
582/*! Activate a waiting conditional (single).
583 *
584 * \param[in] cond The conditional.
585 */
587
588/*! @} */
589
590
591/*! \addtogroup m_thread_common_rwlock Read/Write locks
592 * \ingroup m_thread_common
593 *
594 * Read/Write locks
595 *
596 * @{
597 */
598
599/*! Read/Write lock. */
600struct M_thread_rwlock;
601typedef struct M_thread_rwlock M_thread_rwlock_t;
602
603
604/*! Read/Write lock, lock type. */
605typedef enum {
606 M_THREAD_RWLOCK_TYPE_READ = 0, /*!< Lock for read. */
607 M_THREAD_RWLOCK_TYPE_WRITE /*!< Lock for write. */
609
610
611/*! Read/Write lock create.
612 *
613 * Read/Write locks allow multiple readers to be hold the lock at the same time. A
614 * write lock will be allowed once all readers have released their locks.
615 *
616 * For new locks waiting writers are preferred. Meaning a if a writer is waiting
617 * new read locks will not be given until all waiting writers has received and
618 * released their locks.
619 *
620 * \return Read/Write lock on success otherwise NULL on error.
621 */
623
624
625/*! Destroy a read/write lock.
626 *
627 * \param[in] rwlock The lock.
628 */
630
631
632/*! Lock a read/write lock.
633 *
634 * The thread will block waiting to acquire the lock.
635 *
636 * \param[in] rwlock The lock.
637 * \param[in] type The type of lock to acquire.
638 *
639 * \return M_TRUE If the lock was acquired. Otherwise M_FALSE.
640 */
642
643
644/*! Unlock a read/write lock.
645 *
646 * \param[in] rwlock The lock.
647 *
648 * \return M_TRUE If on success. Otherwise M_FALSE.
649 */
651
652
653/*! @} */
654
655
656/*! \addtogroup m_thread_common_tls Thread Local Storage
657 * \ingroup m_thread_common
658 *
659 * Thread Local Storage
660 *
661 * @{
662 */
663
664
665/*! Thread local storage key. */
666typedef M_uint64 M_thread_tls_key_t;
667
668/*! Create a key for storing data in thread local storage.
669 *
670 * \param destructor The destructor to call to destroy the stored value at the
671 * returned key. Optional, use NULL if not needed.
672 *
673 * \return The key to use in tls.
674 */
675M_API M_thread_tls_key_t M_thread_tls_key_create(void (*destructor)(void *));
676
677
678/*! Set the key for the current thread to the given value.
679 *
680 * \param[in] key The key.
681 * \param[in] value The value to store.
682 *
683 * \return M_TRUE if the value was stored. Otherwise M_FALSE.
684 */
685M_API M_bool M_thread_tls_setspecific(M_thread_tls_key_t key, const void *value);
686
687
688/*! Get the value fro a given key.
689 *
690 * \param[in] key The key.
691 *
692 * \return The value or NULL if not value set/invalid key.
693 */
695
696
697/*! @} */
698
699
700
701/*! \addtogroup m_thread_common_spinlock Spinlocks
702 * \ingroup m_thread_common
703 *
704 * Spinlocks
705 *
706 * @{
707 */
708
709/*! Public struct for spinlocks, so static initializers can be used */
710typedef struct M_thread_spinlock {
711 volatile M_uint32 current;
712 volatile M_uint32 queue;
715
716/*! Static initializer for spinlocks */
717#define M_THREAD_SPINLOCK_STATIC_INITIALIZER { 0, 0, 0 }
718
719
720/*! Lock a spinlock.
721 *
722 * A spinlock is similar in usage to a mutex, but should NOT be used in place of a mutex.
723 * When in doubt, use a mutex instead, a spinlock is almost always the wrong thing to use.
724 * Spinlocks can be used protect areas of memory that are very unlikely to have high
725 * contention and should only be held for very short durations, or when the act of
726 * initializing a mutex might itself cause a race condition (such as during an initialization
727 * procedure as mutexes do not support static initializers).
728 *
729 * When lock contention occurs on a spinlock, it will spin, consuming CPU, waiting
730 * for the lock to be released. Spinlocks are purely implemented in userland
731 * using atomics. The implementation uses 'tickets' to try to guarantee lock order
732 * in a first-come first-served manner, and has rudimentary backoff logic to attempt
733 * to reduce resource consumption during periods of high lock contention.
734 *
735 * A spinlock variable must have been initialized using M_THREAD_SPINLOCK_STATIC_INITIALIZER
736 * and passed by reference into this function. There is no initialization or
737 * destruction function.
738 *
739 * \param[in] spinlock Spinlock initialized via M_THREAD_SPINLOCK_STATIC_INITIALIZER
740 * and passed by reference.
741 */
743
744
745/*! Unlock a spinlock
746 *
747 * See M_thread_spinlock_lock() for more information.
748 *
749 * \param[in] spinlock Spinlock initialized via M_THREAD_SPINLOCK_STATIC_INITIALIZER
750 * and passed by reference.
751 */
753
754
755/*! @} */
756
757
758/*! \addtogroup m_thread_common_once Threadsafe initialization helpers (Thread Once)
759 * \ingroup m_thread_common
760 *
761 * Threadsafe initialization helpers (Thread Once)
762 *
763 * @{
764 */
765
766/*! Public struct for M_thread_once, so static initializer can be used */
767typedef struct M_thread_once {
771
772/*! Static initializer for M_thread_once */
773#define M_THREAD_ONCE_STATIC_INITIALIZER { M_FALSE, M_THREAD_SPINLOCK_STATIC_INITIALIZER }
774
775
776/*! Ensure an initialization routine is performed only once, even if called from
777 * multiple threads simultaneously.
778 *
779 * Performing initialization in a multi-threaded program can cause race conditions.
780 *
781 * Take this code example:
782 * static int initialized = 0;
783 * if (!initialized) {
784 * init_routine();
785 * initialized = 1;
786 * }
787 *
788 * If two threads where to enter this simultaneously, before init_routine() was
789 * complete, they would call it twice. The above code example can be replaced
790 * with:
791 *
792 * static M_thread_once_t initialized = M_THREAD_ONCE_STATIC_INITIALIZER;
793 * M_thread_once(&initialized, init_routine);
794 *
795 * \param[in] once_control Once control variable passed by reference, and first set
796 * to M_THREAD_ONCE_STATIC_INITIALIZER;
797 * \param[in] init_routine Initialization routine to be called if it has not yet
798 * been called.
799 * \param[in] init_flags Flags to be passed onto the initialization routine.
800 * \return M_TRUE if init routine was just run, M_FALSE if not run (previously run)
801 */
802M_API M_bool M_thread_once(M_thread_once_t *once_control, void (*init_routine)(M_uint64 flags), M_uint64 init_flags);
803
804
805/*! Reset the once_control object back to an uninitialized state. Useful to be
806 * called in a destructor so an initialization routine can be re-run.
807 *
808 * \param[in] once_control Once control variable passed by reference, and first set
809 * to M_THREAD_ONCE_STATIC_INITIALIZER;
810 * \return M_TRUE if reset, M_FALSE if not initialized.
811 */
812M_API M_bool M_thread_once_reset(M_thread_once_t *once_control);
813
814/*! @} */
815
816__END_DECLS
817
818#endif /* __M_THREAD_H__ */
void M_thread_cond_broadcast(M_thread_cond_t *cond)
M_bool M_thread_cond_timedwait_abs(M_thread_cond_t *cond, M_thread_mutex_t *mutex, const M_timeval_t *abstime)
M_bool M_thread_cond_timedwait(M_thread_cond_t *cond, M_thread_mutex_t *mutex, M_uint64 millisec)
M_bool M_thread_cond_wait(M_thread_cond_t *cond, M_thread_mutex_t *mutex)
M_thread_cond_t * M_thread_cond_create(M_uint32 attr)
struct M_thread_cond M_thread_cond_t
Definition: m_thread.h:502
void M_thread_cond_signal(M_thread_cond_t *cond)
void M_thread_cond_destroy(M_thread_cond_t *cond)
M_thread_condattr_t
Definition: m_thread.h:508
@ M_THREAD_CONDATTR_NONE
Definition: m_thread.h:509
M_uint8 M_thread_attr_get_priority(const M_thread_attr_t *attr)
M_threadid_t M_thread_create(const M_thread_attr_t *attr, void *(*func)(void *), void *arg)
M_bool M_thread_attr_set_processor(M_thread_attr_t *attr, int processor_id)
void M_thread_attr_destroy(M_thread_attr_t *attr)
void M_thread_attr_set_stack_size(M_thread_attr_t *attr, size_t val)
M_thread_attr_t * M_thread_attr_create(void)
int M_thread_attr_get_processor(const M_thread_attr_t *attr)
M_bool M_thread_attr_set_priority(M_thread_attr_t *attr, M_uint8 priority)
size_t M_thread_attr_get_stack_size(const M_thread_attr_t *attr)
struct M_thread_attr M_thread_attr_t
Definition: m_thread.h:228
M_threadid_t M_thread_self(void)
M_bool M_thread_join(M_threadid_t id, void **value_ptr)
M_bool M_thread_set_priority(M_threadid_t tid, M_uint8 priority)
void M_thread_sleep(M_uint64 usec)
M_bool M_thread_attr_get_create_joinable(const M_thread_attr_t *attr)
void M_thread_yield(M_bool force)
M_bool M_thread_set_processor(M_threadid_t tid, int processor_id)
void M_thread_attr_set_create_joinable(M_thread_attr_t *attr, M_bool val)
M_uintptr M_threadid_t
Definition: m_thread.h:223
M_bool M_thread_active_model(M_thread_model_t *model, const char **model_name)
M_thread_model_t
Definition: m_thread.h:108
size_t M_thread_num_cpu_cores(void)
void M_library_cleanup_register(void(*cleanup_cb)(void *arg), void *arg)
M_bool M_thread_init(M_thread_model_t model)
void M_thread_destructor_remove(void(*destructor)(void))
void M_library_cleanup(void)
size_t M_thread_count(void)
M_bool M_thread_destructor_insert(void(*destructor)(void))
@ M_THREAD_MODEL_COOP
Definition: m_thread.h:111
@ M_THREAD_MODEL_INVALID
Definition: m_thread.h:109
@ M_THREAD_MODEL_NATIVE
Definition: m_thread.h:110
M_bool M_thread_mutex_unlock(M_thread_mutex_t *mutex)
M_thread_mutex_t * M_thread_mutex_create(M_uint32 attr)
void M_thread_mutex_destroy(M_thread_mutex_t *mutex)
M_thread_mutexattr_t
Definition: m_thread.h:432
M_bool M_thread_mutex_trylock(M_thread_mutex_t *mutex)
struct M_thread_mutex M_thread_mutex_t
Definition: m_thread.h:427
M_bool M_thread_mutex_lock(M_thread_mutex_t *mutex)
@ M_THREAD_MUTEXATTR_NONE
Definition: m_thread.h:433
@ M_THREAD_MUTEXATTR_RECURSIVE
Definition: m_thread.h:434
M_bool initialized
Definition: m_thread.h:768
M_thread_spinlock_t spinlock
Definition: m_thread.h:769
M_bool M_thread_once(M_thread_once_t *once_control, void(*init_routine)(M_uint64 flags), M_uint64 init_flags)
M_bool M_thread_once_reset(M_thread_once_t *once_control)
Definition: m_thread.h:767
struct M_thread_rwlock M_thread_rwlock_t
Definition: m_thread.h:601
void M_thread_rwlock_destroy(M_thread_rwlock_t *rwlock)
M_thread_rwlock_type_t
Definition: m_thread.h:605
M_bool M_thread_rwlock_lock(M_thread_rwlock_t *rwlock, M_thread_rwlock_type_t type)
M_thread_rwlock_t * M_thread_rwlock_create(void)
M_bool M_thread_rwlock_unlock(M_thread_rwlock_t *rwlock)
@ M_THREAD_RWLOCK_TYPE_READ
Definition: m_thread.h:606
@ M_THREAD_RWLOCK_TYPE_WRITE
Definition: m_thread.h:607
M_threadid_t threadid
Definition: m_thread.h:713
volatile M_uint32 queue
Definition: m_thread.h:712
volatile M_uint32 current
Definition: m_thread.h:711
void M_thread_spinlock_lock(M_thread_spinlock_t *spinlock)
void M_thread_spinlock_unlock(M_thread_spinlock_t *spinlock)
Definition: m_thread.h:710
M_uint64 M_thread_tls_key_t
Definition: m_thread.h:666
M_thread_tls_key_t M_thread_tls_key_create(void(*destructor)(void *))
M_bool M_thread_tls_setspecific(M_thread_tls_key_t key, const void *value)
void * M_thread_tls_getspecific(M_thread_tls_key_t key)
Definition: m_time.h:187