(because like. advancing a coroutine through a foreign call is a very useful thing to be able to do. that is how pants works with rust and python)
Post
oh goodness me these threads have a lot of stuff attached. sitting my ass down and learning
coroutine threads seem to have such wildly divergent semantics that it still really shocks me that they're interchangeable. like (thread-receive) would seem to either yield execution of the current coroutine, or to block an OS thread (risking e.g. deadlock). and then there's this:
Unless otherwise noted, all constant-time procedures and operations provided by Racket are thread-safe in the sense that they are atomic
it's technically true that operations which are atomic for a single-threaded coroutine are also atomic in the sense of the processor memory model, but i think that comparison obscures more than it enlightens. is there a way to do a multithreaded coroutine executor?
this docs paragraph from the C API seems outdated now? https://docs.racket-lang.org/inside/cs-overview.html#(part._.Racket_.C.S_and_.Threads)
Racket implements threads for Racket programs without aid from the operating system or Chez Scheme’s threads, so that Racket threads are cooperative from the perspective of C code. Stand-alone Racket uses a few private OS-implemented threads for background tasks, but these OS-implemented threads are never exposed by the Racket API.
i'm also really miffed by the "racket's road to parallelism" section failing to describe when and why racket got the coroutine thread abstraction and what considerations motivated its design
oh nvm
Racket has always included threads for concurrency
i guess if it's a very old feature that might explain why it's not integrated with general coroutines? i also don't understand how "a coroutine swap cannot take place during a foreign call" and "to the C API, racket threads are cooperative" don't contradict—oh oops the C API is not the same as the foreign function interface
i'm also doing this evil cackle reading
but I/O remains a direction for improvement.
i/o is so hard!!! rust async is (i believe) really unsuited for filesystem i/o because the latencies and work queues tend to be extremely predictable, so explicit threading and buffering doesn't end up polling and tends to keep the cores as busy as possible. i spent several months trying to get async zip crate competitive and FAILED!!!!