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 <[email protected]> wrote: > > > >> Am 27.12.2025 um 18:00 schrieb David McClain <[email protected]>: >> >>> 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
