# Threading System Source: `src/dusk/thread/` ## Platform support Threading currently requires **pthreads** (`DUSK_THREAD_PTHREAD`). The implementation lives in the core thread files and is guarded by that compile-time flag -- there are no separate per-platform thread directories. Thread-local storage uses the `THREAD_LOCAL` macro, which maps to `__thread` when pthreads is available. This is used by the error system to give each thread its own `ERROR_STATE`. ## Thread lifecycle Threads follow a strict state machine: ``` STOPPED -> STARTING -> RUNNING -> STOP_REQUESTED -> STOPPED ``` - `threadStart()` -- blocking: starts the thread and waits until it reaches RUNNING. - `threadStop()` -- blocking: requests stop and waits until STOPPED. - `threadStartRequest()` -- non-blocking equivalent of `threadStart`. - `threadStopRequest()` -- non-blocking equivalent of `threadStop`. The thread callback polls `threadShouldStop()` to know when to exit. Never kill a thread forcefully -- always let it stop cooperatively. ## Thread API ```c void threadInit(thread_t *thread, errorret_t (*callback)(thread_t *t)); // Initialise; callback is the thread entry point. errorret_t threadStart(thread_t *thread); // Start and block until RUNNING. errorret_t threadStop(thread_t *thread); // Request stop, block until STOPPED. void threadStartRequest(thread_t *thread); void threadStopRequest(thread_t *thread); // Non-blocking variants. bool_t threadShouldStop(const thread_t *thread); // Call from inside the thread callback to know when to exit. ``` ## Mutex API (`threadmutex.h`) Each `threadmutex_t` wraps a pthread mutex and a condition variable. ```c void threadMutexInit(threadmutex_t *mutex); void threadMutexDispose(threadmutex_t *mutex); void threadMutexLock(threadmutex_t *mutex); void threadMutexUnlock(threadmutex_t *mutex); bool_t threadMutexTryLock(threadmutex_t *mutex); // Returns true if the lock was acquired; false if already held. void threadMutexWaitLock(threadmutex_t *mutex); // Block until signalled (like pthread_cond_wait). // Must be called while holding the lock. void threadMutexSignal(threadmutex_t *mutex); // Wake one waiter. ``` ## Usage example ```c static errorret_t workerCallback(thread_t *t) { while(!threadShouldStop(t)) { // do work } errorOk(); } thread_t worker; threadInit(&worker, workerCallback); errorChain(threadStart(&worker)); // ... later ... errorChain(threadStop(&worker)); ``` ## Thread safety rules - The error system (`ERROR_STATE`) is thread-local -- each thread has its own error state. Do not pass `errorret_t` across thread boundaries without copying the message and lines strings first. - Asset loading: the background thread calls `loadAsync`; the main thread calls `loadSync`. Never call GPU or SDL functions from the loader background thread. - Use `assertIsMainThread()` / `assertNotMainThread()` to guard functions that have thread affinity requirements.