| OLD | NEW |
| (Empty) | |
| 1 == Introduction == |
| 2 |
| 3 The Actor model is a model of concurrent computation for distributed systems. |
| 4 An actor system consists of a number of concurrent and autonomous entities |
| 5 called actors. An actor has its own thread of control and state and is the |
| 6 unit of concurrency in the actor model. The state of actor is encapsulated |
| 7 and is not shared. Actors communicate using asynchronous message passing. |
| 8 Each actor updates its own local state by processing messages that it receives |
| 9 in its mailbox. |
| 10 |
| 11 Dart is the Google’s new language for web programming which features Isolates. |
| 12 Isolates provide a message passing model for programming in a non-shared memory |
| 13 setting. Here, we have an Actor framework developed on top of isolates as an |
| 14 alternative to using isolates directly. The goals of this framework are: |
| 15 |
| 16 1- Easier concurrent programming in Dart via a familiar syntax inspired by Scala |
| 17 and Erlang |
| 18 2- Cheap creation of lightweight concurrent entities (actors) for responsiveness |
| 19 3- Providing an API for accessing DOM from within a remote isolate |
| 20 |
| 21 |
| 22 == Getting Started == |
| 23 |
| 24 An actor is defined by a class. It is required that this class extends the |
| 25 "Actor" class. The Actor class handles all the mechanics for sending and serving |
| 26 messages and creating new actors. |
| 27 |
| 28 class HelloWorld extends Actor { |
| 29 HelloWorld() : super() { |
| 30 // ... |
| 31 } |
| 32 } |
| 33 |
| 34 Message handlers are defined inside the constructor's body. |
| 35 |
| 36 class HelloWorld extends Actor { |
| 37 HelloWorld() : super() { |
| 38 |
| 39 // a message handler for "say hello" message |
| 40 on["say hello"] = (String who) { |
| 41 ui.send("print", ["Hello $who!"]); |
| 42 }; |
| 43 |
| 44 // a message handler for "say goodbye" message |
| 45 on["say goodbye"] = (String who) { |
| 46 ui.send("print", ["Bye $who!"]); |
| 47 }; |
| 48 |
| 49 } |
| 50 } |
| 51 |
| 52 Every actor has access to the 'ui' actor for printing on the console. One can |
| 53 print something on the console by sending "print" message to the ui actor: |
| 54 |
| 55 ui.print("A string"); |
| 56 |
| 57 Note that the print function is only a syntactic sugar for: |
| 58 |
| 59 ui.send("print", ["A string"]); |
| 60 |
| 61 |
| 62 == Actor Discovery and Message Passing == |
| 63 |
| 64 No one can get a reference to an actor object. Actors are only accessible |
| 65 through their identity which can be used to send messages to the actor. |
| 66 How to send a message to an actor using its id? |
| 67 |
| 68 id.send("message name", [parameters]); |
| 69 |
| 70 Running on the dart VM, parameters can be everything but closures. |
| 71 |
| 72 In order to become known to other actors, one can send its own id to them. An |
| 73 actor can access its own id using 'me' and can send it as a parameter. |
| 74 |
| 75 anotherActorId.send("contact me", [me]); |
| 76 |
| 77 One can only send a message to self using 'me': |
| 78 |
| 79 me.send("message to self", [parameters]); |
| 80 |
| 81 |
| 82 == Creating Actors == |
| 83 |
| 84 ActorManager is responsible for creating actors. The first actor is created by |
| 85 actor manager from the main function of the application. For instance, for the |
| 86 HelloWorld example, the main functions looks like the following: |
| 87 |
| 88 main() { |
| 89 ActorManager manager = new ActorManager(1); |
| 90 manager.create(const HelloWorldFactory(), |
| 91 "say hello", ["World"]); |
| 92 } |
| 93 |
| 94 class HelloWorldFactory implements ActorFactory { |
| 95 const HelloWorldFactory(); |
| 96 Actor create() => new HelloWorld(); |
| 97 } |
| 98 |
| 99 Let's step through the main function. The following line will create an actor |
| 100 manager: |
| 101 |
| 102 ActorManager manager = new ActorManager(1); |
| 103 |
| 104 The parameter sent to the constructor is the number of background isolates used |
| 105 to schedule actors. In the above example it is one. |
| 106 |
| 107 The next line will ask actor manager to create an actor using the specified |
| 108 factory object: |
| 109 |
| 110 manager.create(const HelloWorldFactory(), |
| 111 |
| 112 The second and third parameters to the create function are the initial message |
| 113 and parameters that must be sent to the actor upon creation: |
| 114 |
| 115 manager.create(const HelloWorldFactory(), |
| 116 "say hello", ["World"]); |
| 117 |
| 118 |
| 119 Because of the lack of reflection (at the time of writing the framework) in |
| 120 Dart, there should be an actor factory for each actor. |
| 121 |
| 122 An actor creates other actor by calling a create function. This function is |
| 123 defined in the "Actor" class and it has the same parameters as mentioned above. |
| 124 |
| 125 |
| 126 == Request and Response == |
| 127 |
| 128 In order to get a response back for a message sent to another actor, you can use |
| 129 a Reply object. The Reply object encapsulates the way a response should be sent |
| 130 back to an actor. For instance, in the following example a client actor needs |
| 131 the fibonacci value of 100. It sends a message ("fibonacci") to a calculator |
| 132 actor and includes the number and a Reply object. Reply object takes two |
| 133 parameters. The first one indicates to whom the message must be sent and the |
| 134 second one indicates what message must be used to send the response back. |
| 135 |
| 136 ///// Client Actor |
| 137 |
| 138 on["some message"] = () { |
| 139 num n = 100; |
| 140 calculatorActor |
| 141 .send("fibonacci", |
| 142 [n, new Reply(me, "fib-result")]); |
| 143 }; |
| 144 |
| 145 on["fib-result"] = (num fibOfN) { |
| 146 ... |
| 147 }; |
| 148 |
| 149 ///// Calculator Actor |
| 150 |
| 151 on["fibonacci"] = (num n, Reply reply) { |
| 152 reply.response([fib(n)]); |
| 153 }; |
| 154 |
| 155 In the above example the, client must have a named message handler, |
| 156 "fib-result", in order to handle the result. One can use messageback to create |
| 157 an unnamed message handler. |
| 158 |
| 159 |
| 160 ///// Client Actor |
| 161 |
| 162 on["some message"] = () { |
| 163 num n = 100; |
| 164 calculatorActor |
| 165 .send("fibonacci", |
| 166 [n, |
| 167 messageback((num fibOfN) { |
| 168 ... |
| 169 }; |
| 170 )]); |
| 171 }; |
| 172 |
| 173 |
| 174 == Programming with Actors == |
| 175 |
| 176 When you are programming with actors, you can either program for web or |
| 177 terminal. If you are programming for web you will need to import |
| 178 'actors-web.dart' from core. You also will need to have a version of browser in |
| 179 which Dart VM is enabled. In case you only want to write a console application, |
| 180 you will need to import 'actors-term.dart' from core. |
| 181 |
| 182 |
| 183 == Known Issues == |
| 184 |
| 185 The current version of this framework does not work with frog and/or dartc. |
| 186 Applications written using this framework run with Dart VM (command line or a |
| 187 Dart enabled browser). |
| 188 |
| OLD | NEW |