tags:

views:

37

answers:

1

This question describes what actors are in actor programming. What are messages? How can you avoid shared state if you send an object in a message (assuming objects exist in actor programming)?

+1  A: 

If we think actors are People, then messages are like ... messages.

Say a Boss want to square root of a list of numbers a, and don't want to do all the calculating himeself. He can hire some Workers, and the Boss will know their Phone numbers.

So the Boss will SMS each of the Workers, and tell them to "Find the square root of a_i; reply me at 555-1234 after you've done.". This instruction is a message. The Boss will then wait for the Workers to finish.

 +------+  sqrt(i=0, a_i=9)         +------------+
 | Boss | ------------------------> | Worker 0   |
 +------+                           +------------+
       |   sqrt(i=1, a_i=16)        +------------+
       ‘--------------------------> | Worker 1   |
                                    +------------+
                                       ....

After the Workers completed the computation, they will send an SMS back the Boss and report the results. This is also done in message passing.

 +------+   set_result(i=0, val=3)  +------------+
 | Boss | <------------------------ | Worker 0   |
 +------+                           +------------+
       ^  set_result(i=1, val=4)    +------------+
       ‘--------------------------- | Worker 1   |
                                    +------------+
                                       ....

This sounds like Object-oriented programming, but there are no order to which when a message is sent or received — they are passed asynchronously. (However, within the actor themselves, messages are received and queued synchronously.)

When written in code, it may be like

actor Boss:
   receive('run'):
     worker_addrs = spawn_many(SqrtWorker, len(a))  # hire workers.
     for i, addr in enumerate(worker_addrs): 
        send(addr, 'sqrt', reply_addr=self, i=i, a_i=a[i])

   receive('set_value', i, val):
     a[i] = val

actor SqrtWorker:
   receive('sqrt', reply_addr, i, a_i):
     send(reply_addr, 'set_value', i, sqrt(a_i))
     quit()

There are no "shared states problem", because a state cannot be shared without copying. In my example above, the elements of list a are copied to each worker. In fact, only the Boss knows the existence of a — this is a local state.

Now what if we really want to make a shared? In actor model, we would convert them into a new actor, and the Phone number of this actor are sent to the Worker.

 +------+  sqrt(i=0, a_phoneNum=555-1111)  +----------+
 | Boss | -------------------------------> | Worker 0 |
 +------+                                  +----------+

             +---+
             | a |
             +---+

The Worker then ask the list actor for the required info (it is possible because the Boss has given the Phone number of a to the Worker.)

 +------+                                 +----------+
 | Boss |                                 | Worker 0 |
 +------+                                 +----------+
                                               |
             +---+                             |
             | a | <---------------------------’
             +---+             get(i=0)

Some time later the list replies...

 +------+                                 +----------+
 | Boss |                                 | Worker 0 |
 +------+                                 +----------+
                                               ^
             +---+       list_val(i=0, val=9)  |
             | a | ----------------------------’
             +---+

then the Worker can compute the square root after receiving the message list_val.

 +------+     set_result(i=0, val=3)      +----------+
 | Boss | <------------------------------ | Worker 0 |
 +------+                                 +----------+

             +---+
             | a |
             +---+

The Boss finally updates the shared state

 +------+                                 +----------+
 | Boss |                                 | Worker 0 |
 +------+                                 +----------+
    | set(i=0, val=3)                
    |        +---+ 
    ‘------> | a | 
             +---+ 

Will there be any problems accessing shared state like this? No — since messages received by a must be run synchronously, all read/write actions will be interfere with each other. Thus there are no need to mess with mutexes.

KennyTM