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

Reply via email to