ThreadHandle
struct ThreadHandleAn owning handle to one live OS thread.
Movable but deliberately not Copyable. A pthread_t names one
kernel thread and POSIX forbids joining the same one twice, so
"exactly one owner, exactly one join" belongs in the type system rather
than in a comment.
As defence in depth, join() also zeroes the stored id, so a second
join() on the same handle short-circuits instead of calling
pthread_join on a stale id (which is undefined behaviour, not an error
return).
Implements Movable
spawn
def spawn[start: def(Pointer[UInt8, MutUntrackedOrigin]) thin -> OpaquePtr](arg: Pointer[UInt8, MutUntrackedOrigin]) -> Self Start a thread running start(arg).
- Parameters
start: The thread body. Thin (non-capturing) and non-raising — pthread has no exception channel, so convert any failure into a value the caller can read out ofarg.
- Args
arg: The context pointer handed tostart. Must stay valid until the thread is joined.
Raises Error: If pthread_create fails, carrying its POSIX return code
(EAGAIN when the process is out of threads, EPERM for
scheduling-attribute refusals).
join
def join(mut self) Wait for the thread to finish; discard its return value.
Idempotent: after a successful join the handle's id is zeroed, so
calling join() again returns immediately instead of re-entering
pthread_join with a stale id.
Raises Error: If pthread_join fails. The handle is left untouched so the
caller can retry or propagate.
detach
def detach(mut self) Release the thread without waiting for it; it cleans itself up when it returns.
After this the handle is inert — join() becomes a no-op. Only detach
a thread whose context outlives the whole process, or one that owns its
context outright: nothing is left to tell you when it stopped reading.
Raises Error: If pthread_detach fails.
is_joinable
def is_joinable(self) -> Bool Whether this handle still names a thread.
pin_to_cpu
def pin_to_cpu(self, cpu: Int) Pin the thread to one logical CPU.
On Linux this is a real, hard affinity set via
pthread_setaffinity_np. On macOS it is a documented no-op: Darwin
exposes only thread_policy_set(THREAD_AFFINITY_POLICY), which is an
affinity hint used to group threads onto a shared cache, not a pin,
and pretending otherwise would be worse than doing nothing.
- Args
cpu: Zero-based logical CPU index.
Raises Error: On Linux if pthread_setaffinity_np fails — typically
EINVAL for a cpu index outside the process's cpuset, which is
what happens inside a restricted container. Never raises on
macOS.