Behaviors
Every instance of
Actor
has a
behavior object associated with it.
Receiving and processing messages
Every
user-level message
sent to an Actor
must be a request carrying a
Message
instance. The message is sent to the actor’s behavior
object, and the reply is relayed to the calling actor.
Methods taking blocks or ActorProxy
values often demand special
treatment; see the section on the
weaknesses of the library’s design
for more information.
Ways of responding to messages
Simple replies
Methods on a behavior object can simply return their result, like any other method on any other object, and it will be relayed to the caller.
Replying with a promise
They may also choose to return a promise of an eventual answer. The caller will get their reply when the promise resolves or is rejected.
Suspending the caller
Finally, they may suspend the decision about how to reply to the caller.
Calling the method Actor class >> #caller
retrieves and detaches
the request object that the actor is working on right
now. The actor can then store the request in a variable,
making its reply
using #resolveWith:
or #rejectWith:
later. Calling Actor class >>
#caller
a second time will return nil
, since the request was
detached on the first call.
The actor only automatically replies to a request if Actor class >>
#caller
has not been called. Making a call to Actor class >>
#caller
signals that the request will be taken care of manually.
The Barrier tutorial shows an example of this technique.
Class ActorBehavior
Any Smalltalk object can serve as a behavior object, but inheriting
from ActorBehavior
offers a number of convenient features:
-
ActorBehavior class >> #spawn
is a convenient abbreviation forActor class >> #bootProxy:
. See ways of constructing an actor. -
ActorBehavior >> #log:
and#logAll:
produce log message events using the tracing mechanism. This allows log messages to be recorded in the correct order with respect to surrounding events when tracing is active. (By default, these messages go to theTranscript
; see the section on tracing for details.) -
ActorBehavior >> #changed
,#changed:
and#changed:with:
ensure that dependents of the behavior areupdate
d in the UI process, rather than directly in the actor’s own process. This is important not only because Morphic dependents often rely on executing in the UI process, but also for robustness. If any of theupdate
methods signals an exception, the offending dependent is simply removed, rather than killing the actor. An exception from oneupdate
method therefore will not prevent the other dependents of thechanged
object from running.