2.2 Actors and messages

The main mechanism for unifying control flow and data flow is a special abstraction, the actor, and the message-based communication that takes place between actors. An actor is any object that can exchange messages with other actors. In the actor programming model, actors communicate solely by passing messages to each other.

In a pure actor system, every object is an actor. For instance, in Erlang, another language that defines an actor programming model, even atomic objects, such as Ints and Strings, are actors. Scala's actors library, by contrast, allows you to easily turn any Scala object into an actor, but does not require that all objects be actors.

Actors have a uniform public interface: An actor can, in general, accept any kind of message. When an actor receives a message from another actor, the receiving actor examines, or evaluates, the incoming message. Based on the contents and type of that message, the receiving actor may find the message interesting; otherwise, it simply discards the message. When an actor is interested in an incoming message, it may perform some action in response to that message. The action depends on the actor's internal script or program, as well as the actor's current state. The ability to perform actions in response to incoming messages is what makes an object an actor.

An actor's response to an incoming message can take different forms. The simplest response is to merely evaluate the message's content. Performing addition of integers x and y in an actor-based system, for instance, would consist of a message containing x and y sent to an actor capable of adding the integers together. In that case, the arithmetic actor would simply evaluate the sum of x and y.

image images/addingXAndY90.jpg

Figure 2.3 - The simplest actor computation: adding x and y together.

Of course, merely adding two numbers together is of little use if the result is not visible outside the actor performing the evaluation. Thus, a more useful actor message would contain the address of another actor interested in receiving the result. This is illustrated in Figure 2.3.

A reference to another actor in a message is the receiving actor's continuation. Upon evaluating a message according to an internal script, an actor can send the results of that evaluation to its continuation. Including references to a continuation in an actor's message means that the actor programming model implicitly supports the continuation-passing style (CPS), but generalized to concurrent programming.[3] This is illustrated in Figure 2.4.

image images/continuation90.jpg

Figure 2.4 - Actor computation with continuation message passing.

The simplest kind of continuation is a reference to the sending actor. Having access to a message's sender is so convenient that the Scala actors library implicitly includes a reference to the sending actor in messages, as shown in Figure 2.5.

image images/sender90.jpg

Figure 2.5 - Every message carries a sender reference.

An actor's continuation is a key element of control flow in actor-based programming. Program control flows from one actor to another as continuations are passed between actors. At the same time, the actor message that sends possible continuations may also include the data required by the actor to determine control flow. The actor model unifies control flow and data flow in the sense that data as well as an actor's continuation can be passed inside the same message.

That unified view makes it easier to design actor-based programs. When designing a program with actors, it is helpful to first determine the kinds of control flow your code requires. Those control decisions would be made by actors. Thus, you would next define what data those control flow decisions require, and send that data inside messages to the appropriate actors.

The speed maintenance control structure in the previous example, for instance, requires a decision about whether to maintain or change the current speed. That decision needs just the current and desired speed values. The simplest implementation merely evaluates the values supplied by incoming messages and takes appropriate action based on those values, as illustrated in Figure 2.6. Note that the message sender does not have to be an actor.

image images/currentSpeed90.jpg

Figure 2.6 - CruiseControl actor receiving currentSpeed message.

A more modular approach would define an actor responsible for deciding the required speed adjustment, and would then send the result to a continuation, as shown in Figure 2.7.

image images/messageFlow90.jpg

Figure 2.7 - A more modular approach to cruise control with further decomposition of responsibilities into actors.

One advantage of the actor-based approach is that it allows the continuation of CruiseControlThrottleControl—to be defined sometime after CruiseControl is defined—and even after an instance of CruiseControl is already initialized and loaded into memory: ThrottleControl is simply an actor with the uniform actor interface to receive messages. Thus all CruiseControl needs is a reference to the continuation actor, such as that actor's address.

image images/throttleContinuation90.jpg

Figure 2.8 - A throttleControl continuation included in a message.

The ability to perform such extreme late binding of a continuation allows developers to incrementally add knowledge—such as control flow—to an actor-based system. Indeed, actors grew out of the desire to create large knowledge-based systems in an incremental fashion. A continuation actor included in a message, such as the throttleControl continuation shown in Figure 2.8, affects control flow and accommodates late binding in an actor system.

Late binding in actor control flow is also an important tool in lending robustness to an actor-based system. For instance, an actor may be redundantly defined, allowing a message sender to send replicated messages.

If actors interacting via messages sounds similar to how objects communicate in an object-oriented system, that likeness is no mere coincidence. Indeed, the actor model was developed at the same time the first object-oriented languages were designed, and was, in turn, influenced by object-oriented concepts. Alan Kay, an inventor of object-oriented programming, noted that message passing between objects is more central to object-oriented programming than objects themselves are. In an email on messaging to a Smalltalk discussion group, Kay wrote:[4]

The big idea is "messaging" -- that is what the kernel of Smalltalk/ Squeak is all about (and it's something that was never quite completed in our Xerox PARC phase). The Japanese have a small word -- ma -- for "that which is in between" -- perhaps the nearest English equivalent is "interstitial." The key in making great and growable systems is much more to design how its modules communicate rather than what their internal properties and behaviors should be...

You can view the actor model as a special case of object-oriented programming where all communication between objects takes place via message passing, and when an object's internal state changes only in response to messages.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset