tur/r7rs/thread
the C half of SRFI 18 (stdlib/srfi/18.scm) for #lang r7rs.
Spliced in with (import (srfi 18)) (scheme_lower.c SRFI_HELPERS), and written, like the prelude, in Turmeric shapes -- which can call a Scheme procedure value, so a new thread runs its thunk directly and nothing calls back into the SRFI by name. What is here:
- starting a detached OS thread on a thunk; - one monitor (a mutex and a condition variable) that every SRFI 18 mutex, condition variable and join is built on, in Scheme; - the wall clock, a sleep and a yield.
Every blocking call below (the monitor's lock and waits, the handoff's wait, nanosleep) is one of the collector's release points: r7gc.c routes them through wrappers that park the thread around the call, so a collection never waits on a thread that is waiting on SRFI 18.
Interpreter twins of these primitives are T2 of docs/archive/r7rs-srfi-18-216-sicp-plan.md.
Since: r7rs-srfi-18-216-sicp-plan T1
r7rs-thread-monitor__
(r7rs-thread-monitor__ :ptr<void>)
internal: the monitor's address.
r7rs-thread-spawn-c__
(r7rs-thread-spawn-c__ [entry :ptr<void> thunk] :bool)
internal: start a detached thread at entry (r7rs-thread-entry__) on thunk; #f when the OS refuses one. Returns once the child holds the thunk.
r7rs-thread-take__
(r7rs-thread-take__ [arg :ptr<void>] :any)
internal: the child's side of the handoff.
r7rs-thread-entry__
(r7rs-thread-entry__ [arg :ptr<void>] :ptr<void>)
internal: a new thread's first frame. The thunk (18.scm's) catches everything the program's thunk raises.
r7rs-thread-spawn__
(r7rs-thread-spawn__ [thunk] :bool)
internal: start a thread running thunk.
r7rs-thread-lock-c__
(r7rs-thread-lock-c__ [mon :ptr<void>] :nil)
internal: the monitor.
r7rs-thread-unlock-c__
(r7rs-thread-unlock-c__ [mon :ptr<void>] :nil)
r7rs-thread-lock__
(r7rs-thread-lock__ :nil)
r7rs-thread-unlock__
(r7rs-thread-unlock__ :nil)
r7rs-thread-wait-c__
(r7rs-thread-wait-c__ [mon :ptr<void> deadline :float] :bool)
internal: with the monitor held, wait for a change until deadline (wall-clock seconds; negative: none). #t when the deadline passed. A return without one is not a promise that anything changed: the caller looks again.
r7rs-thread-wait__
(r7rs-thread-wait__ [deadline :float] :bool)
r7rs-thread-notify-c__
(r7rs-thread-notify-c__ [mon :ptr<void>] :nil)
internal: with the monitor held, wake every waiter to look again.
r7rs-thread-notify__
(r7rs-thread-notify__ :nil)
r7rs-thread-now__
(r7rs-thread-now__ :float)
internal: the wall clock, in seconds.
r7rs-thread-sleep__
(r7rs-thread-sleep__ [secs :float] :nil)
internal: sleep secs seconds (none if <= 0).
r7rs-thread-yield__
(r7rs-thread-yield__ :nil)
internal: let another thread run.