Closed mdbergmann closed 2 weeks ago
Here's how I do this in my actor.lisp
, which is probably the most notable [ab]user of ChanL.
Also important is where the :halt command gets recv
-ed.
To save you the trouble of distangling all that dense code, I'll paraphrase the highlighted code as follows: the chanl tasks that loop and perform each actor's work have a catch form as the topmost form in their body, and receiving the :halt
keyword in the blessed control channel triggers the throw which immediately ends that task without queuing its successor task.
Thanks. That looks straight forward. Indeed, :halt
, or maybe I call it :terminate
should immediately stop the message processing, but also discard any messages currently processing and any message still in the queue. Since the actor potentially doesn't operate its own thread but its mailbox is handled by one of the message-dispatcher threads it's not super trivial, but :terminate/:halt
could just call stop
function, which already implements what I want (or I think it does at least). Using :terminate
should also notify watchers and distribute a terminated
message.
its mailbox is handled by one of the message-dispatcher threads it's not super trivial
this is precisely the sort of complexity that ChanL strove to avoid; one thread per task, and in my hacky actors file, one task per actor. this invariant is not perfectly maintained in the remainder of ScalpL, although I am working towards restoring it.
Yeah, well. Actor systems still have a bit of a different use case. Actors are supposed to maintain state in a thread-safe manner. And potentially you have very many. I.e. I use Sento for Chipi (the house automation bus project) where every light, switch, window sensor and every rule definition and persistence handler are represented by an actor that maintains their state. This all doesn't require more than just a very few threads. Also Sento implements asynchronous ask pattern by spawning an anonymous actor that waits for a reply. Other runtimes have virtual or green threads that allow this kind of things naturally, like Erlang, but in CL this sort of thing is not possible without slightly more complexity.
I don't think the flow I wrote works well in that case, because you couldn't predict which actors could be the ones terminating one that was given the :terminate message; similar to how you could know that if there are two light switches that toggle one bulb, then its state is effected only by one of those two switches.
edit, in case amateur grammar police read along: one bulb can be affected by multiple switches, yet have its voltage effected by touching any single switch. this is a common gimmick indispensible for corridor lighting!
Yeah, ChanL is for running parallel tasks, not for maintaining state. But that's all fine.
Indeed,
:halt
, or maybe I call it:terminate
should immediately stop the message processing, but also discard [...]
Have you considered :break
? I realize the name collision against CL:BREAK
, however, despite this, it benefits from the intuition of tripping a circuit braker to turn off all lights in some section of a building.
I don't think the flow I wrote works well in that case, because you couldn't predict which actors could be the ones terminating one that was given the :terminate message; similar to how you could know that if there are two light switches that toggle one bulb, then its state is effected only by one of those two switches.
edit, in case amateur grammar police read along: one bulb can be affected by multiple switches, yet have its voltage effected by touching any single switch. this is a common gimmick indispensible for corridor lighting!
Right, but that's beyond the scope of the actor. In Chipi project this is solved by being able to setup rules.
Which acts similar to
act-cell:stop
method, but it more aligned with actor interface.