Here we explain the multi-call system in PyActive. We have two variants (1) Multi Synchronous Call and (2) Multi Asynchronous Call.

  1. Multi Synchronous: Actor can call synchronous methods to more than one Actor at same time. This invocation returns a dictionary <key, value>, where key are "from id", and value are the result returned by the method execution of each actor. If not all the actors return a result, you'll receive all messages returned. On the other hand, if nobody returns the result, you will receive a timeout exception.
  2. Multi Asynchronous: Actor can call asynchronous methods to more than one Actor at same time. This invocation sends, to all Actors in the list, the same call.

 

In two cases, we need to initialize a Multi class. When we initialize this class, we can pass a list of Actors, who will receive the messages, or we can add the Actors after. Multi class has this interface:

Multi Asynchronous Interface:

  • def __init__(self, list_actors):
  • def attach(self, actor):
  • def detach(self, actor):
  • def attach_list(self, actors):

Multi Synchronous Interface:

  • def __init__(self, owner, list_actors):
  • def attach(self, actor):
  • def detach(self, actor):
  • def attach_list(self, actors):

Note: That the Synchronous Multi needs one extra parameter ("owner"), which is a reference of the actor that creates this Multi object. The owner parameter it's necessary to make possible the send of the results to the owner. 

Therefore, as we can see at the interface of the both Multis, we can add or remove actors from the Multi list when we believe that it's necessary. Moreover, we can add a single actor or a list of actors using the correct method. 

Tu use the multi objects, we can import it from pyactive.Multi with the names AMulti and SMulti. Next, you can see a example/test that shows how to use it:

from pyactive.controller import init_host, serve_forever, start_controller, sleep
import time
from pyactive.Multi import AMulti, SMulti

class Server(object):
    _sync = {}
    _async = ['add_actors', 'add', 'sync_add','print_references']
    _ref = ['add_actors']
    _parallel = []
    
    def add_actors(self, list_actors):
        print list_actors
        self.amulti = AMulti(list_actors)
        self.smulti = SMulti(self._atom, list_actors)
        self.list_actors = list_actors
    def add(self, x, y):
        self.amulti.add(x, y)
    
    def sync_add(self, x, y):
        result =  self.smulti.sync_add(x, y)
        print result.values()
    def print_references(self):
        for a in range(16):
            print 'hola'
            print self.smulti.get_reference().keys()
class Calc():
    _sync = {'sync_add':'1', 'get_reference':'1'}
    _async = ['add']
    _ref = ['get_reference']
    _parallel = []
        
    def add(self, x, y):
        print x+y
        
    def sync_add(self, x, y):
        sleep(2)
        return x+y
    def get_reference(self):
        print self.proxy
        return self.proxy
class Calc1():
    _sync = {'sync_add':'1', 'get_reference':'1'}
    _async = ['add']
    _ref = ['get_reference']
    _parallel = []
        
    def add(self, x, y):
        print x+y
    def sync_add(self, x, y):
        return x+y 
    def get_reference(self):
        return self.proxy       
def test():
    
    calcs = []
    
    tcpconf = ('tcp',('127.0.0.1',6664))
    host = init_host(tcpconf)
    
    for i in range(1):
        calcs.append(host.spawn_id(str(i),'test_multi','Calc',[]))
    
    for i in range(2):
        calcs.append(host.spawn_id(str(i),'test_multi','Calc1',[]))
    
    server = host.spawn_id('serv', 'test_multi', 'Server', [])
    server.add_actors(calcs)
    
    server.add(4,4)
    server.sync_add(3,3)
    server.print_references()
   
def main():
    start_controller('pyactive_thread')
    serve_forever(test)
    
   
if __name__ == "__main__":
    main()