Files
dusk/.claude/threading.md
T
2026-06-16 10:15:59 -05:00

101 lines
2.9 KiB
Markdown

# 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.