Coroutines, goroutines

"Scott L. Burson" <[email protected]> Wed, 25 Feb 2026 18:54:10 -0800
Newsgroups gmane.lisp.steel-bank.devel
Message-ID <CAF5LJ4CjehsveWi0pCVxEcVBeTR+bX-TLbqxYkyuc-R3MVLdww@mail.gmail.com>
Hi all,

I tried to contact Kartik Singh directly about this, but got a "you are not
an authorized sender" bounce.  Since Kartik is on this list, I assume this
will get through.  The discussion is likely of wider interest anyway.

I've seen the video of Kartik's lightning talk
<https://www.youtube.com/watch?v=S2nVKfYJykw> at ELS 2024 titled "Proof of
Concept: Coroutines in SBCL".  He ported over some old CMUCL threading
support, without the scheduler.  But the work is still sitting in a GitHub
fork and doesn't seem to have gone anywhere.  I would like to encourage,
support, and if needed, participate in getting it ready for general use and
into SBCL, at least as a contrib module, if that's possible.

I do think it should have a scheduler, though.  I will take the liberty of
quoting Pascal Costanza (from a message to the Common Lisp Pro mailing
list, [email protected], 2025-12-28):

Something that is very relevant to understand in the Go context: Go
> channels are not based on pthreads, but they are based around Go’s own
> tasking model (which of course are in turn based on pthreads, but’s not
> that relevant). Go’s tasking model is an alternative to previous async
> programming models, where async code and sync code had to be written in
> different programming styles - that made such code very difficult to write,
> read and refactor. (I believe
> https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/ is
> the text that made that insight popular.)
>
> In Go, async code looks exactly the same as sync code, and you don’t even
> have to think about that distinction anymore. This is achieved by ensuring
> that all potentially blocking operations are effectively not blocking, but
> instead play nicely with the work-stealing scheduler that handles Go’s
> tasking model. So, for example, if a task tries to take a lock on a mutex,
> and that is currently not possible, the task gets swapped out and replaced
> by a different task that can continue its execution. This integration
> exists for all kinds of potentially blocking operations, including channels.
>
> With pthreads, a lock / mailbox / etc. that blocks can have the
> corresponding pthread replaced by another one, but that is much more
> expensive. Go’s tasks are handled completely in user space, not in kernel
> space. (And work stealing gives a number of very beneficial guarantees as
> well.)
>
> This nuance may or may not matter in your application, but it’s worth
> pointing out nonetheless.
>
> It would be really nice if Common Lisp had this as well, in place of a
> pthreads-based model, because it would solve a lot of issues in a very
> elegant way...
>

I do see people on Hacker News, Reddit, and elsewhere saying that they
would love to use CL, but it needs to have lightweight threads in order to
work for their use cases.

I wonder as well if it might be possible, while such code is being touched,
to work in firstclass delimited continuations.  These would be for people
writing solvers, such as Screamer.  (Yes, I'm aware of CL-Cont
<https://gitlab.common-lisp.net/cl-cont/cl-cont>; but it heap-allocates
every continuation.)  Something to think about, anyway.

So — what do the SBCL team think about this?  Is it something you would
support, or even help out with?

And for Kartik — how much work do you think remains to get coroutine
functionality into a generally usable state?

-- Scott

_______________________________________________
Sbcl-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sbcl-devel