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/07/18 11:11] elisagat:tutorial:actors [2008/03/13 16:23] – * tvcutsem
Line 201: Line 201:
 We have described a future as a placeholder for the return value of an asynchronous message send which is eventually //resolved// with the expected result. However, we have yet to describe what objects can do with futures that are //unresolved//, i.e. what can an object do with a future that does not know its value yet? In many multithreaded languages that introduce the future abstraction, the language dictates that accessing (performing an operation on) an unresolved futures causes the active thread to block; the thread has to wait for the value of the future to be available, before it can carry on. This makes futures a preferred means of //synchronising// two threads with more freedom than is possible using a simple remote procedure call. We have described a future as a placeholder for the return value of an asynchronous message send which is eventually //resolved// with the expected result. However, we have yet to describe what objects can do with futures that are //unresolved//, i.e. what can an object do with a future that does not know its value yet? In many multithreaded languages that introduce the future abstraction, the language dictates that accessing (performing an operation on) an unresolved futures causes the active thread to block; the thread has to wait for the value of the future to be available, before it can carry on. This makes futures a preferred means of //synchronising// two threads with more freedom than is possible using a simple remote procedure call.
  
-Blocking a thread on a future can be a major source of deadlocks, like any form of blocking, of course. In the actor paradigm where communication between actors should remain strictly asynchronous, this behaviour is obviously unwanted. Furthermore, in a distributed programming context, it is highly undesirable to make one actor block on a future that may have to be resolved by an actor on another machine. It would make the application much more vulnerable because of latency or partial failure, resulting in unresponsive applications at best, and deadlocked applications at worst.+Blocking a thread on a future can be a major source of deadlocks, like any form of blocking. In the actor paradigm where communication between actors should remain strictly asynchronous, this behaviour is obviously unwanted. Furthermore, in a distributed programming context, it is highly undesirable to make one actor block on a future that may have to be resolved by an actor on another machine. It would make the application much more vulnerable because of latency or partial failure, resulting in unresponsive applications at best, and deadlocked applications at worst.
  
-The solution proposed in the [[http://www.erights.org|E language]], and adopted in AmbientTalk, is to disallow direct access to a future by any object. Instead, objects may **only** send **asynchronous** messages to a future object. This enables the future to temporarily buffer such messages until its resolved value is known. The net effect of this solution is that futures actually can be "chained", forming asynchronous //pipelines// of messages, as will be further explained in the next section.+The solution proposed in the [[http://www.erights.org|E language]], and adopted in AmbientTalk, is to disallow direct access to a future by any object. Instead, objects may **only** send **asynchronous** messages to a future object. This enables the future to temporarily buffer such messages until its resolved value is known. The net effect of this solution is that futures actually can be "chained", forming asynchronous //pipelines// of messages, as will be illustrated in the next section. 
 + 
 +==== Working with Resolved Futures ====
  
 When a future eventually becomes resolved with a value, any messages that were accumulated by the future are forwarded asynchronously to the actual return value, such that it appears as if the original object had sent the messages to the actual return value in the first place. When a future eventually becomes resolved with a value, any messages that were accumulated by the future are forwarded asynchronously to the actual return value, such that it appears as if the original object had sent the messages to the actual return value in the first place.
Line 210: Line 212:
 AmbientTalk only allows one method to be synchronously invoked on a future, the ''=='' method. A word of warning though: equality on futures is defined as pointer equality, so a future will only be equal to itself. It does not compare the parameter object with its actual value, if it would be resolved. AmbientTalk only allows one method to be synchronously invoked on a future, the ''=='' method. A word of warning though: equality on futures is defined as pointer equality, so a future will only be equal to itself. It does not compare the parameter object with its actual value, if it would be resolved.
 </note> </note>
- 
-==== Working with Resolved Futures ==== 
  
 As explained above, it is always correct to use asynchronous message sends to communicate with a future. Sometimes, however, we may want to perform some operation on the return value other than message sending, for example, printing it to the screen. If you print the future directly, you get the following: As explained above, it is always correct to use asynchronous message sends to communicate with a future. Sometimes, however, we may want to perform some operation on the return value other than message sending, for example, printing it to the screen. If you print the future directly, you get the following:
Line 271: Line 271:
 </code> </code>
  
-Finally, it is useful to know that ''when:becomes:'' itself returns a future, who will be resolved with the value of applying the observer closure:+Finally, it is useful to know that ''when:becomes:'' itself returns a future, who will be resolved with the value of applying the observer closure: 
  
 <code> <code>
Line 279: Line 279:
 </code> </code>
  
-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''. This example also illustrates how futures can be chained by means of the ''when:becomes:'' function forming the so-called asynchrounous pipelines of messages
  
 ==== Futures and Annotated Messages ==== ==== Futures and Annotated Messages ====
Line 333: Line 333:
 Notice that, in this example, the new metaobject protocol is an extension of the old protocol. This enables it to invoke its parent's behaviour simply by means of a super-send. Note also that the ''install:'' primitive returns the previously installed mirror. This is useful for when an actor mirror should only temporarily be installed. The old mirror can later be re-installed. Notice that, in this example, the new metaobject protocol is an extension of the old protocol. This enables it to invoke its parent's behaviour simply by means of a super-send. Note also that the ''install:'' primitive returns the previously installed mirror. This is useful for when an actor mirror should only temporarily be installed. The old mirror can later be re-installed.
  
 +<note>
 For a good use case of actor mirrors, see the ''at/lang/futures.at'' file in the system library. This file implements future-type message passing. It uses a custom actor mirror that overrides ''createMessage'' -- which is invoked whenever an asynchronous message is created -- to attach a future to the message. For a good use case of actor mirrors, see the ''at/lang/futures.at'' file in the system library. This file implements future-type message passing. It uses a custom actor mirror that overrides ''createMessage'' -- which is invoked whenever an asynchronous message is created -- to attach a future to the message.
 +</note>
  
 Other methods that can be overridden are ''require'' and ''provide'', which reify the export and discovery of objects, and ''createMirror'', which is invoked by the ''reflect:'' primitive. By overriding this //factory method//, it becomes possible to easily customize the behaviour of mirrors defined on local objects. Other methods that can be overridden are ''require'' and ''provide'', which reify the export and discovery of objects, and ''createMirror'', which is invoked by the ''reflect:'' primitive. By overriding this //factory method//, it becomes possible to easily customize the behaviour of mirrors defined on local objects.
at/tutorial/actors.txt · Last modified: 2020/02/05 21:26 by elisag