Data Structures | |
| struct | cnd_t |
Macros | |
| #define | OBJC_PLATFORM_API_CALL WINAPI |
| #define | thrd_debug_breakpoint() |
Typedefs | |
| typedef CRITICAL_SECTION | mtx_t |
| typedef DWORD | thrd_retval_t |
| typedef PTHREAD_START_ROUTINE | thrd_start_t |
| typedef DWORD | thrd_t |
| typedef void * | tss_dtor_t |
| typedef DWORD | tss_t |
Enumerations | |
| enum | { mtx_recursive = 1 } |
Functions | |
| intptr_t | cnd_broadcast (cnd_t *p_cond) |
| void | cnd_destroy (cnd_t *p_cond) |
| intptr_t | cnd_init (cnd_t *p_cond) |
| intptr_t | cnd_signal (cnd_t *p_cond) |
| intptr_t | cnd_wait (cnd_t *p_cond, mtx_t *p_mutex) |
| static void | mtx_destroy (mtx_t *p_mutex) |
| static intptr_t | mtx_init (mtx_t *p_mutex, intptr_t tp_mutex) |
| static intptr_t | mtx_lock (mtx_t *p_mutex) |
| static intptr_t | mtx_trylock (mtx_t *p_mutex) |
| static intptr_t | mtx_unlock (mtx_t *p_mutex) |
| void | polar_platform_threading_finalize (void) |
| intptr_t | polar_platform_threading_init (void) |
| intptr_t | thrd_create (thrd_t *out_thread_id, thrd_start_t thread_func, void *thread_data) |
| static thrd_t | thrd_current (void) |
| static intptr_t | thrd_detach (thrd_t id_thread_target) |
| static void | thrd_exit (intptr_t __value_unused) |
| intptr_t | thrd_join (thrd_t id_thread_target, intptr_t *__p_retval_unused) |
| static void | thrd_process_abort (void) |
| static void | thrd_yield (void) |
| intptr_t | tss_create (tss_t *out_tss_id, tss_dtor_t __func_destructor_unused) |
| static void | tss_delete (tss_t id_tss_target) |
| static void * | tss_get (tss_t id_tss_target) |
| static intptr_t | tss_set (tss_t id_tss_target, void *value_new) |
These platform-specific types and routines provide support for handling threads, condition variables, and mutexes. They are patterned after the types and routines defined by ISO C threads and adapt the platform types and routines to that standard – so that, when the runtime is compiled for a generic platform where a more specific thread interface is not provided, the runtime threading code still functions without requiring revision.
As presented here, the types shown are those used by the Polar runtime when compiling for Windows. These types may be defined differently when the runtime is compiled for POSIX or generic targets, but the names will remain the same.
Where possible, these functions are inlined and call the underlying threading routines directly. For some platforms and circumstances, it is necessary to emulate some of the functionality desired by the Polar runtime, however, and in such cases these functions may not be inlined.
| struct cnd_t |
Represents a condition variable.
Although more recent versions of Windows include native support for condition variables, the Polar runtime currently emulates the behavior of a condition variable using events instead. On systems using POSIX threads, this type maps directly to pthread_cond_t.
| Data Fields | ||
|---|---|---|
| intptr_t | count_waiters | |
| HANDLE | event_condition | |
| CRITICAL_SECTION | lock_condition | |
| #define OBJC_PLATFORM_API_CALL WINAPI |
Represents the calling convention used by the underlying platform.
This macro is primarily used to define callback functions that are passed to underlying platform API. For the moment, this means that, although the macro is defined on all platforms supported the runtime, an associated value is set only on Windows, since POSIX and other systems use standard C function calls to interact with the underlying platform API. On Windows, this macro resolves to WINAPI.
| #define thrd_debug_breakpoint | ( | ) |
Insert a debug breakpoint into code at the designated location.
This macro is not part of the ISO C Threads standard, but is included here because POSIX threads provide pthread_kill() for raising signals from within a thread.
The macro provides a way to add a debug breakpoint to code prior to debugging it. On Windows, it resolves to the DebugBreak() function. On systems that use POSIX threads, it resolves to pthread_kill() and raises SIGTRAP. On other systems, it resolves to raise() and raises SIGTRAP.
| typedef CRITICAL_SECTION mtx_t |
Represents a mutual exclusion lock (a mutex).
This type maps directly to CRITICAL_SECTION on Windows. On systems using POSIX threads, the type maps to a runtime-defined structure in which the first member is a pthread_mutex_t. The remaining members of the structure are used to emulate recursive mutexes in the event the pthreads implementation does not natively support them.
| typedef DWORD thrd_retval_t |
Represents the type of value returned by the threaded function which is passed to thrd_create().
This typedef is not part of the ISO C Threads standard, but it provides a useful abstraction because the type of value returned by threaded functions varies from one threading system to the next and we need to be able to declare a function that matches the signature of thrd_start_t.
| typedef PTHREAD_START_ROUTINE thrd_start_t |
Represents the signature of a function that will be executed in the thread created by a call to thrd_create().
The function signature varies between threading systems, but typically the function will accept a single void * value and will return either an integer or pointer value. On Windows, this type maps directly to PTHREAD_START_ROUTINE.
Represents a thread ID.
This type varies based on the underlying threading system, but is typically an unsigned integer value of varying width.
| typedef void* tss_dtor_t |
Represents the signature of a function that is passed to tss_create() as a destructor for the associated thread variable.
On Windows, this type is unused because Windows does not natively provide for thread variable destructors. On other systems, the type defines the signature of a standard C function that returns no value and that takes a single void * value: the current value of the associated thread variable. This allows a thread variable which represents a dynamic memory location or object, and which has been allocated by a thread, to be freed when that thread ends.
Represents the type of value used to store a thread variable identifier.
The type of value used to identify a thread variable differs on different platforms, but is typically an integer value of varying width.
On Windowss, this type is equivalent to a DWORD. On systems using POSIX threads, it resolves to pthread_key_t.
| anonymous enum |
| Enumerator | |
|---|---|
| mtx_recursive | This definition exists to support mtx_init() in cases where the runtime is not using ISO C threads. ISO C threads already defines this constant. On Windows, all mutexes are recursive – but on other platforms it is sometimes necessary to explicitly request a recursive mutex. The Polar runtime uses recursive mutexes exclusively, implementing them itself where they are not provided by the underlying threading system. As such, this value is used only when the runtime is compiled with ISO C threads and is ignored otherwise. |
| intptr_t cnd_broadcast | ( | cnd_t * | p_cond | ) |
Signal to all waiting threads that the condition represented by p_cond has been met.
All threads that have been blocked while waiting for p_cond will be unblocked and scheduled for execution again. If no threads are currently waiting for p_cond, this call will have no effect.
| [in] | p_cond | Points to the condition variable that will be set to a signaled state. This variable should have previously been initialized by cnd_init(). |
| void cnd_destroy | ( | cnd_t * | p_cond | ) |
Finalize a condition variable that was previously initialized by cnd_init().
| [in] | p_cond | Points to the condition variable to finalize. After this call, p_cond is invalid and should not be used again without initialization. |
| intptr_t cnd_init | ( | cnd_t * | p_cond | ) |
Initialize a new condition variable.
| [out] | p_cond | Points to the memory location that will receive the initialized condition variable data |
| intptr_t cnd_signal | ( | cnd_t * | p_cond | ) |
Signal to the next waiting thread that the condition represented by p_cond has been met.
If no threads are currently waiting for p_cond, this call will have no effect.
| [in] | p_cond | Points to the condition variable that will be set to a signaled state. This variable should have previously been initialized by cnd_init(). |
Wait for the condition represented by p_cond to be met.
This function will suspend execution of the calling thread until p_cond is set to a signaled state. Spurious wakeups of the calling thread may occur, which is why the calling thread should also make use of data protected by p_mutex to verify that the condition is still met when the thread is resumed.
The calling thread should hold the exclusive lock represented by p_mutex before calling this function. This function will unlock p_mutex while waiting for p_cond to be set. When the function returns successfully to the calling thread, p_mutex will be locked again and owned by the calling thread.
| [in] | p_cond | Points to the condition variable that represents the condition for which the calling thread will wait. This variable should have previously been initialized by cnd_init(). |
| [in] | p_mutex | Points to the mutex protecting the data that the calling thread will access when the condition is met. This variable should have previously been initialized by mtx_init(), and the calling thread should have successfully called mtx_lock() or mtx_trylock() on it prior to calling this function. |
|
inlinestatic |
Finalize a mutex that was previously initialized with a call to mtx_init().
| [in] | p_mutex | Points to the mutex to be finalized. After this call, p_mutex is invalid and should not be used again without initialization. |
|
inlinestatic |
Initialize a new mutex of the specified type.
| [out] | p_mutex | Points to the memory location that will receive the initialized mutex data |
| [in] | tp_mutex | Indicates the type of mutex requested. For polar-objc, this will always be mtx_recursive. |
|
inlinestatic |
Acquire an exclusive lock on the specified mutex. The current thread will be suspended, if necessary, until the exclusive lock can be granted.
To attempt to acquire a lock on a mutex without causing the current thread to be suspended, use mtx_trylock() instead.
If this function is called on a mutex for which the current thread already holds a lock – a recursive use of the mutex – the function will succeed, but it will be necessary to call mtx_unlock() more than once in order to release the cumulative locks obtained on p_mutex.
| [in] | p_mutex | Points to the mutex that will be locked. This should be a memory location that was previously supplied to mtx_init(). |
|
inlinestatic |
Attempt to acquire an exclusive lock on the specified mutex without blocking the caurrent thread.
If this function is called on a mutex for which the current thread already holds a lock – a recursive use of the mutex – the function will succeed, but it will be necessary to call mtx_unlock() more than once in order to release the cumulative locks obtained on p_mutex.
| [in] | p_mutex | Points to the mutex that will be locked. This should be a memory location that was previously supplied to mtx_init(). |
|
inlinestatic |
Release an exclusive lock on the specified mutex so that other threads may acquire it.
It may be necessary to call this function more than once, if p_mutex has been locked more than once by the calling thread. It is the responsibility of the programmer to determine if this is the case.
| [in] | p_mutex | Points to the mutex that will be unlocked. This should be a memory location what was previously supplied to mtx_lock() or mtx_trylock(). |
| void polar_platform_threading_finalize | ( | void | ) |
Finalize platform-specific threading code.
This function is called by polar_finalize() as part of the runtime finalization process.
This function is defined and implemented for all platforms supported by the Polar runtime. Its workings differ across platforms. On Windows, it does nothing.
On systems using POSIX threads, it releases the attributes allocated for threads and mutexes by polar_platform_threading_init().
| intptr_t polar_platform_threading_init | ( | void | ) |
Initialize platform-specific threading code.
This function is called by polar_init() as part of the runtime initialization process.
This function is defined and implemented for all platforms supported by the Polar runtime. Its workings differ across platforms. On Windows, it does nothing.
On systems using POSIX threads, it sets up the default thread and mutex attributes, and tests whether the underlying implementation of pthreads supports recursive mutexes: if so, it points the implementations of mtx_lock(), mtx_trylock(), and mtx_unlock() at their pthreads counterparts; otherwise, it points the implementations of these functions at internal routines that emulate recursive mutex functionality.
| intptr_t thrd_create | ( | thrd_t * | out_thread_id, |
| thrd_start_t | thread_func, | ||
| void * | thread_data ) |
Create a new thread in the current process that will execute thread_func.
This function will create a new thread of execution in the current process, within which thread_func will run. thread_data is passed as the sole parameter to thread_func. The thread is scheduled for immediate execution and may begin running before this function returns to the caller.
On systems other than Windows, the new thread is created in a joinable state and is not detached, meaning you will either need to call thrd_join() or thrd_detach(), depending on whether you need to wait for the thread to exit or not.
| [out] | out_thread_id | Points to a memory location that will receive the platform ID assigned to the new thread, if it is successfully created. |
| [in] | thread_func | Indicates the function that will run in the context of the new thread. |
| [in] | thread_data | Specifies data that will be passed to thread_func when it begins execution. This parameter may be #NULL if there is no need to pass data to the function. |
|
inlinestatic |
Return the platform-assigned ID of the calling thread.
On Windows, this function is equivalent to GetCurrentThreadId(). On systems using POSIX threads, it resolves to pthread_self().
|
inlinestatic |
Indicate to the threading system that system resources for the specified thread can be automatically reclaimed when the thread ends.
Typically you can call thrd_detach() or thrd_join() on a given thread – but calling both may lead to program errors.
The resources assigned to id_thread_target will be freed automatically when the thread terminates. The parent thread will not be notified when the threaad ends.
This function has no effect on Windows. On systems using POSIX threads, it resolves to pthread_detach().
| [in] | id_thread_target | Specifies the ID of the thread that is to be detached from its parent thread. This ID should have previously been returned by a call to thrd_create(). |
|
inlinestatic |
End execution of the calling thread.
This function will exit the calling thread. If another thread is waiting for the completion of the calling thread by way of thrd_join(), then that thread will be resumed.
This function does not return to the caller.
| [in] | __value_unused | Unused. Because the type of value returned from a threaded function varies across platforms, the Polar runtime does not make use of this value. |
| intptr_t thrd_join | ( | thrd_t | id_thread_target, |
| intptr_t * | __p_retval_unused ) |
Await the completion of the specified thread.
Typically you can call thrd_detach() or thrd_join() on a given thread – but calling both may lead to program errors.
This function will suspend the calling thread until execution of the thread identified by id_thread_target has ended. On Windows, this function makes use of WaitForSingleObject(); on systems using POSIX threads, it calls pthread_join().
| [in] | id_thread_target | The ID of the thread for which to wait, which will have been returned by thrd_create() when the thread was successfully created. |
| [out] | __p_retval_unused | Unused. Because the type of value returned from a threaded function varies across platforms – DWORD for Windows, void * for POSIX threads – the Polar runtime does not make use of this value. |
|
inlinestatic |
Abort the running process.
This function is not part of the ISO C Threads standard, but is included here since it relates to process and thread control. The function makes use of thrd_debug_breakpoint() before calling abort(); doing this provides the opportunity, when debugging the runtime, of catching and investigating a fatal error before it causes the program to terminate.
This function does not return to the caller.
|
inlinestatic |
Yield the remaining execution time that has been allocated to the calling thread.
This function can be useful when spinning while waiting for the results of an asynchronous operation, so long as it is used carefully. It is used for such a purpose by polar_thread_message_queue_message_wait(). It does not suspend the calling thread the way mtx_lock() and cnd_wait() might do; it merely allows other threads to run while the calling thread waits.
On Windows, this function resolves to SwitchToThread(). On other systems, it resolves to sched_yield().
| intptr_t tss_create | ( | tss_t * | out_tss_id, |
| tss_dtor_t | __func_destructor_unused ) |
Allocate a thread variable slot for use across all threads.
Note that there are platform-defined limits to the number of thread variable slots that can be allocated, so this function should be used sparingly. It should also be called for each thread variable slot that is needed before any threads are created.
On Windows, this function makes use of TlsAlloc(). On systems using POSIX threads, it calls pthread_key_create().
| [out] | out_tss_id | Points to the memory location where the new thread variable's identifier will be stored. |
| [in] | __func_destructor_unused | Provides an optional destructor for the value of the new thread variable. If #NULL is not passed here, then the associated function is called in the context of each thread just before it exits, and typically only when the value of the associated thread variable is not #NULL for that thread. This allows any memory represented by that thread variable to be correctly deallocated. This parameter is not used on Windows, as Windows does not natively support the notion of thread variable destructors. |
|
inlinestatic |
Deallocate a thread variable slot that was previously allocated by tss_create().
This function makes the thread variable slot inaccessible to all running threads; as such, it is typically used on process shutdown, or when a dynamic library that has allocated a slot is being unloaded.
Note that using this function will not cause any destructor associated with the thread variable to be called.
On Windows, this function calls TlsFree(). On systems using POSIX threads, it calls pthread_key_delete().
| [in] | id_tss_target | Specifies the identifier of the thread variable that will have its slot deallocated. This value should have previously been returned by a call to tss_create(). |
|
inlinestatic |
Retrieve the value of the given thread variable for the calling thread.
On Windows, this function calls TlsGetValue(). On systems using POSIX threads, it calls pthread_getspecific().
| [in] | id_tss_target | Specifies the identifier of the thread variable to obtain. This value should should have previously been returned by a call to tss_create(). |
|
inlinestatic |
Set the value of the given thread variable for the calling thread.
On Windows, this function calls TlsSetValue(). On systems using POSIX threads, it calls pthread_setspecific().
| [in] | id_tss_target | Specifies the identifier of the thread variable to obtain. This value should should have previously been returned by a call to tss_create(). |
| [in] | value_new | The new value to assign to the thread variable. This value will be private to the calling thread. |