This tutorial introduces some more sophisticated control flow, achieved through postponing transmission of replies to requests.
ActorBehavior subclass: #BarrierActor instanceVariableNames: 'waiters' classVariableNames: '' poolDictionaries: '' category: 'Actors-Demos'
BarrierActor is a simple
that implements a barrier.
Clients may call
#barrierWait, in which case they will not receive a
reply until some other client calls
Any value supplied to
#releaseWaiters: is used as the resolved value
of waiting clients’ promises;
nil as this
The instance variable
waiters holds an
ActorRequests, the waiting continuations.
initialize super initialize. waiters := IdentitySet new.
Waiting for a value
barrierWait waiters add: Actor caller.
Releasing the current set of waiters
releaseWaiters: anObject waiters do: [ :c | c resolveWith: anObject ]. waiters := IdentitySet new.
Each of the waiting requests is released, with
anObject as the reply
value given to the suspended caller via the promise
associated with the request.
releaseWaiters self releaseWaiters: nil
Running an example
Exploring the behavior of
BarrierActors in a workspace must be done
with some care because of the way calls to
barrierWait block until a
releaseWaiters: arrives from another actor.
Instead of using blocking RPC, we will use Promises and Squeak’s explorer.
Creating a BarrierActor and some waiting promises
First, in a workspace, spawn a
b := BarrierActor spawn.
Then, type in
but instead of choosing “do it” or “print it”, right click on that
line and choose “explore it” (or press
Select the workspace window again, and choose “explore it” on the
barrierWait line a second time.
Your screen should now look something like this:
Exploring the state of the BarrierActor
At this moment, the two
Promises waiting for
barrierWait to return
are associated with two instances of
held in the
waiters instance variable of the
If we “explore it” on
b in our workspace, and drill down to see the
behavior object, we can see the two requests sitting where they
Releasing the waiters
Finally, “do it” with the following expression in the workspace:
b releaseWaiters: 1234.
Both the promises have now changed—though the explorers do not automatically update!
To update the view, click on the triangle next to “root” in each explorer, to collapse the view of the promise, and then click a second time, to reopen it.
After this, both explorer views on the promises should look like this:
Finally, we can terminate our
b actor terminate.