User Tools

Site Tools


at:tutorial:actors

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Next revisionBoth sides next revision
at:tutorial:actors [2007/06/19 16:13] tvcutsemat:tutorial:actors [2007/07/18 10:09] elisag
Line 1: Line 1:
-<note>This tutorial is under heavy construction!</note> 
  
 ====== Concurrent Programming with Actors ====== ====== Concurrent Programming with Actors ======
Line 15: Line 14:
 Generally speaking, an active object is an object that encapsulates its own thread of control. An active object also has a message queue or mailbox from which it processes incoming messages. Each message is processed sequentially. An active object responds to an incoming message by invoking the method corresponding to the message. The method is executed by the active object's own thread. Because of this sequential processing of incoming messages, race conditions cannot occur on the internal state of an active object. Objects communicate with active objects by sending them messages //asynchronously//: the messages are enqueued in the receiver's message queue, rather than being invoked immediately. Generally speaking, an active object is an object that encapsulates its own thread of control. An active object also has a message queue or mailbox from which it processes incoming messages. Each message is processed sequentially. An active object responds to an incoming message by invoking the method corresponding to the message. The method is executed by the active object's own thread. Because of this sequential processing of incoming messages, race conditions cannot occur on the internal state of an active object. Objects communicate with active objects by sending them messages //asynchronously//: the messages are enqueued in the receiver's message queue, rather than being invoked immediately.
  
-===== Actors and Far References =====+===== AmbientTalk Actors and Far References =====
  
 In AmbientTalk, concurrency is spawned by creating actors: each actor is an autonomous processor. AmbientTalk's actors are based on the [[Wp>E_programming_language|vat model]] of the [[http://www.erights.org|E programming language]]. In AmbientTalk, an actor consists of a message queue (to store incoming messages), a thread of control (to execute the incoming messages) and a number of regular objects that are said to be //hosted// by the actor. In AmbientTalk, concurrency is spawned by creating actors: each actor is an autonomous processor. AmbientTalk's actors are based on the [[Wp>E_programming_language|vat model]] of the [[http://www.erights.org|E programming language]]. In AmbientTalk, an actor consists of a message queue (to store incoming messages), a thread of control (to execute the incoming messages) and a number of regular objects that are said to be //hosted// by the actor.
Line 32: Line 31:
 As you can see, actors are created similar to objects. The ''actor:'' method, defined in the global lexical scope, takes a closure as its sole argument and uses that closure to initialize the behaviour of the new actor. The creator of the actor immediately receives a so-called //far reference// to this behaviour object, and from that moment on the creating actor and the created actor run in parallel, each capable of processing incoming messages autonomously. As you can see, actors are created similar to objects. The ''actor:'' method, defined in the global lexical scope, takes a closure as its sole argument and uses that closure to initialize the behaviour of the new actor. The creator of the actor immediately receives a so-called //far reference// to this behaviour object, and from that moment on the creating actor and the created actor run in parallel, each capable of processing incoming messages autonomously.
  
-So what exactly is a far reference to an object? The terminology stems from the E language: it is an object reference that refers to an object hosted by another actor. The main difference between regular object references and far references is that regular references allow direct, synchronous access to an object, while far references disallow such access. This is enforced by the kind of messages that these references can carry, as will be explained below.+So what exactly is a far reference to an object? The terminology stems from the E language: it is an object reference that refers to an object hosted by another actor. The main difference between regular object references and far references is that regular references allow direct, synchronous access to an object, while far references only allow asynchronous access to the referenced object. This is enforced by the kind of messages that these references can carry, as will be explained in the next section.
  
-Note that, if the object referred to by a far reference is tagged with one or more type tags, the far reference itself is tagged with the same type tags. Hence, an object located on a remote actor can be tested for its types //synchronously//, there is no need to communicate with the remote actor, as the far reference itself includes type tag information.+<note> 
 +If the object referred to by a far reference is tagged with one or more type tags, the far reference itself is tagged with the same type tags. Hence, an object located on a remote actor can be tested for its types //synchronously//, there is no need to communicate with the remote actor, as the far reference itself includes type tag information. 
 +</note> 
 + 
 +The figure below summarizes AmbientTalk's concurrency model where actors are represented as communicating event loops. The dotted lines represent the actor's event loop threads which perpetually take messages from their message queue and synchronously execute the corresponding methods on the actor's owned objects. Note that an event loop thread never //escapes// its actor boundary: when communication with an object in another actor is required, a message is sent asynchronously via a far reference to the object. For example, as shown below, when A sends a message to B, the message is enqueued in the message queue of B's actor which eventually processes it. 
 + 
 +{{ :at:tutorial:concurrencymodel.png?450 |AmbientTalk actors as communicating event loops }}
  
 ===== Asynchronous Message Sending ===== ===== Asynchronous Message Sending =====
Line 93: Line 98:
 The parameter passing semantics defined above rule out any possibility for an object to be passed by copy. The reason for this semantics is that objects encapsulate a lexical scope, and parameter passing an object by copy would require the entire lexical scope to be parameter-passed as well. The parameter passing semantics defined above rule out any possibility for an object to be passed by copy. The reason for this semantics is that objects encapsulate a lexical scope, and parameter passing an object by copy would require the entire lexical scope to be parameter-passed as well.
  
-To enable objects to be passed by copy between actors, a special type of objects is introduced. These objects are called **isolates** because they are //isolated// from their lexical scope. Continuing our previous example, imagine we want our calculator to work with complex numbers, which are typically objects that one would want to pass by copy. We can define complex numbers as isolate objects as follows:+To enable objects to be passed by copy between actors, a special type of objects is introduced. These objects are called **isolates** because they are //isolated// from their surrounding lexical scope. Continuing our previous example, imagine we want our calculator to work with complex numbers, which are typically objects that one would want to pass by copy. We can define complex numbers as isolate objects as follows:
  
 <code> <code>
Line 132: Line 137:
 </code> </code>
  
-<note important+<note warning
-A word of warning: isolates are objects that are copied freely between actors. As a result, they should be objects whose actual object identity is of little importance. Usually, the identity of by-copy objects is determined by the value of some of the object's fields. Therefore, it is good practice to override the ''=='' method on isolates to compare isolates based on their semantic identity, rather than on their object identity. For example, equality for complex numbers should be defined as:+A word of warning: isolates are objects that are (deep) copied freely between actors. As a result, they should be objects whose actual object identity is of little importance. Usually, the identity of by-copy objects is determined by the value of some of the object's fields. Therefore, it is good practice to override the ''=='' method on isolates to compare isolates based on their semantic identity, rather than on their object identity. For example, equality for complex numbers should be defined as:
 <code> <code>
 def ==(other) { def ==(other) {
Line 141: Line 146:
 </note> </note>
  
-It is important to note that an isolate has no access whatsoever to its encompassing scope. The following code results in an exception:+As already explained, an isolate has no access whatsoever to its encompassing scope. Hence, the following code results in an exception:
  
 <code> <code>
Line 154: Line 159:
 </code> </code>
  
-Sometimes it is useful to initialize an isolate with the values of lexically visible variables. In that case, AmbientTalk allows the programmer to specify which lexical variables should be //copied into// the isolate itself, such that the isolate has its own, local copy of the variable. Lexical variables that need to be copied like this are specified as formal parameters to the closure passed to the ''isolate:'' primitive, as follows:+However, sometimes it is useful to initialize an isolate with the values of lexically visible variables. To this end, AmbientTalk allows the programmer to specify which lexical variables should be //copied into// the isolate itself, such that the isolate has its own, local copy of the variable. Lexical variables that need to be copied like this are specified as formal parameters to the closure passed to the ''isolate:'' primitive, as follows:
  
 <code> <code>
Line 276: Line 281:
 When the future for ''<-add(1,2)'' becomes resolved with ''sum'', the ''fut'' future will be resolved with the future for the ''<-add(sum,3)'' message. When that message finally returns yet another sum, that sum will become the value of ''fut''. When the future for ''<-add(1,2)'' becomes resolved with ''sum'', the ''fut'' future will be resolved with the future for the ''<-add(sum,3)'' message. When that message finally returns yet another sum, that sum will become the value of ''fut''.
  
-==== Futures and Striped Messages ====+==== Futures and Annotated Messages ====
  
-As previously explained, there are two modes for enabling futures in AmbientTalk. Invoking ''enableFutures(true)'' makes asynchronous sends return a future by default. Invoking ''enableFutures(false)'' returns ''nil'' by default. No matter how you enabled futures, you can always override the default setting by explicitly //annotating// the message send itself by means of two stripes exported by the futures module, as explained below.+As previously explained, there are two modes for enabling futures in AmbientTalk. Invoking ''enableFutures(true)'' makes asynchronous sends return a future by default. Invoking ''enableFutures(false)'' returns ''nil'' by default. No matter how you enabled futures, you can always override the default setting by explicitly //annotating// the message send itself by means of two type tags exported by the futures module, as explained below.
  
-When a message send is striped with the ''OneWayMessage'' stripe, it will never attach a future to the message. This is primarily useful if you have enabled futures by default, but want to send a one-way message requiring no result. In this case, simply send the message as follows:+When a message send is annotated with the ''OneWayMessage'' type tag, it will never attach a future to the message. This is primarily useful if you have enabled futures by default, but want to send a one-way message requiring no result. In this case, simply send the message as follows:
  
 <code> <code>
Line 286: Line 291:
 </code> </code>
  
-When a message send is striped with the ''FutureMessage'' stripe, a future is attached to the message, but //only if futures have been enabled//! This is primarily useful if you have enabled futures, but not by default, because you don't want to incur the overhead of future-type message sends on each of the messages sent. In cases where futures become useful, simply send the message as follows:+When a message send is annotated with the ''FutureMessage'' type tag, a future is attached to the message, but //only if futures have been enabled//! This is primarily useful if you have enabled futures, but not by default, because you don't want to incur the overhead of future-type message sends on each of the messages sent. In cases where futures become useful, simply send the message as follows:
  
 <code> <code>
at/tutorial/actors.txt · Last modified: 2020/02/05 21:26 by elisag