class Bridge(IActor): def __init__(self): IActor.__init__(self) self.mailbox = Mailbox() def send(self, message, sender): self.mailbox.send(message, sender) def call(self, target, request, timeout, default=None): self.send_request(target, request) return self.receive_response(timeout, default) def multi_call(self, targeted_requests, timeout, default=None): count = 0 for target, request in targeted_requests: self.send_request(target, request) count += 1 for _ in xrange(count): yield self.receive_response(timeout, default) def stop(self, actors, timeout): stop = Stop() return list(self.multi_call(((actor, stop) for actor in actors), timeout, default=None)) def send_request(self, target, request): target.send(request, self) def receive_response(self, timeout, default): try: message, sender = self.mailbox.receive(timeout=timeout) return message except Empty: return default
class Actor(IActor): @classmethod def spawn(cls, *args, **kwargs): self = cls(*args, **kwargs) self.mailbox = Mailbox() self.start_thread(target=self.act, as_daemon=True) return self @classmethod def start_thread(cls, target, as_daemon, name=None): thread = Thread(target=target) if name: thread.setName(name) thread.setDaemon(as_daemon) thread.start() return thread def send(self, message, sender): if self.mailbox is None: raise ActorNotStartedError() else: self.mailbox.send(message, sender) def receive(self): if self.mailbox is None: raise ActorNotStartedError() else: return self.mailbox.receive() handles = HandlerRegistry() @classmethod def make_handles(*classes): return HandlerRegistry((typ, handler) for cls in classes for (typ, handler) in cls.handles.iteritems()) def act(self): try: while True: message, sender = self.receive() registry = self.__class__.handles handler = registry.get(message.__class__) or registry.get(OtherMessage) if handler is not None: handler(self, message, sender) except Stop: pass @handles(OtherMessage) def do_other(self, message, sender): pass @handles(Stop) def on_stop(self, message, sender): sender.send(Stopped(), self) raise message