Interesting about SBCL CAS.
I do no use CAS directly in my mailboxes, but rely on Posix for them - both LW and SBCL.
CAS is used only for mutation of the indirection pointer inside the 1-slot Actor structs.
Some implementations allow only one thread inside an Actor behavior at a time. I have no restrictions in my implementations, so that I gain true parallel concurrency on multi-core architectures. Parallelism is automatic, and lock-free, but requires careful purely functional coding.
Mailboxes in my system are of indefinite length. Placing restrictions on the allowable length of a mailbox queue means that you cannot offer Transactional behavior. But in practice, I rarely see more than 4 threads running at once. I use a Dispatch Pool of 8 threads against my 8 CPU Cores. Of course you could make a Fork-Bomb that exhausts system resources.
On Dec 27, 2025, at 10:18, Manfred Bergmann <manfred.bergmann@me.com> wrote:
Am 27.12.2025 um 18:00 schrieb David McClain <dbm@refined-audiometrics.com>:
I've reached the conclusion that if you have first-class functions and the ability to create FIFO queue classes, you have everything you need. You don't need Go channels, or operating system threads, etc. Those are just inefficient, Greenspunian implementations of a simpler idea. In fact, you can draw diagrams of Software LEGO parts, as mentioned by dbm, just with draw.io and OhmJS and a fairly flexible PL. [I'd be happy to elaborate further, but wonder if this would be appropriate on this mailing list]
This is essentially what the Transactional Hewitt Actors really are. We use “Dispatch” threads to extract messages (function args and function address) from a community mailbox queue. The Dispatchers use a CAS protocol among themselves to effect staged BECOME and message SENDS, with automatic retry on losing CAS.
Messages and BECOME are staged for commit at successful exit of the functions, or simply tossed if the function errors out - making an unsuccessful call into an effective non-delivery of a message.
Message originators are generally unknown to the Actors, unless you use a convention of providing a continuation Actor back to the sender, embedded in the messages.
An Actor is nothing more than an indirection pointer to a functional closure - the closure contains code and local state data. The indirection allows BECOME to mutate the behavior of an Actor without altering its identity to the outside world.
But it all comes down to FIFO Queues and Functional Closures. The Dispatchers and Transactional behavior is simply an organizing principle.
Yeah, that’s exactly what Sento Actors (https://github.com/mdbergmann/cl-gserver/) are also about.Additionally, one may notice is that Sento has a nice async API called ’Tasks’ that’s designed after the Elixir example (https://mdbergmann.github.io/cl-gserver/index.html#SENTO.TASKS:@TASKS%20MGL-PAX:SECTION).On another note is that Sento uses locking with Bordeaux threads (for the message box) rather than CAS, because the CAS implementations I tried (https://github.com/cosmos72/stmx and an CAS based mailbox implementation in SBCL) were not satisfactory. The SBCL CAS mailbox being extremely fast but had a high idle CPU usage, so I dropped it.Cheers