Created
July 25, 2011 16:12
-
-
Save Evgenus/1104483 to your computer and use it in GitHub Desktop.
Actors?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from collections import deque | |
from functools import partial | |
from weakref import proxy | |
class Scheduler(object): | |
def __init__(self): | |
self.queue = deque() | |
def add(self, callable, *args, **kwargs): | |
print 'scheduling', callable, args, kwargs | |
self.queue.append(partial(callable, *args, **kwargs)) | |
def tick(self): | |
if self.queue: | |
callable = self.queue.popleft() | |
callable() | |
return True | |
else: | |
return False | |
class Action(object): | |
scheduler = None | |
def __init__(self, preprocess=None): | |
self.preprocess = preprocess | |
self.callbacks = [] | |
self.source = None | |
self.name = None | |
def __lshift__(self, callback): | |
if callback not in self.callbacks: | |
self.callbacks.append(callback) | |
return self | |
def __rshift__(self, callback): | |
if callback in self.callbacks: | |
self.callbacks.append(callback) | |
return self | |
def clear(self): | |
self.callbacks = [] | |
def __repr__(self): | |
return "<Action {0} of {1}>".format(self.name, self.source) | |
def __call__(self, *args, **kwargs): | |
print 'invoking action', self | |
if self.preprocess is not None: | |
args, kwargs = self.preprocess(self.source, *args, **kwargs) | |
for callback in self.callbacks: | |
self.scheduler.add(callback, *args, **kwargs) | |
def clone(self): | |
new = self.__class__(self.preprocess) | |
new.name = self.name | |
return new | |
@classmethod | |
def wrap(cls, callable): | |
return cls(callable) | |
class Actor(object): | |
class __metaclass__(type): | |
def __new__(meta, name, bases, internals): | |
actions = internals['_actions'] = {} | |
for key, value in internals.iteritems(): | |
if isinstance(value, Action): | |
actions[key] = value | |
cls = type.__new__(meta, name, bases, internals) | |
for key, action in actions.iteritems(): | |
action.source = proxy(cls) | |
action.name = key | |
return cls | |
def __init__(self): | |
for name, cls_action in self._actions.iteritems(): | |
action = cls_action.clone() | |
cls_action << action | |
action.source = proxy(self) | |
setattr(self, name, action) | |
class Receiver(Actor): | |
@Action.wrap | |
def input(self, value): | |
print '>>', self, value | |
return (value,), {} | |
class Sender(Actor): | |
output = Action() | |
def __init__(self, name, value): | |
super(Sender, self).__init__() | |
self.value = value | |
self.name = name | |
def do(self): | |
self.output(self.value) | |
def __repr__(self): | |
return "<Sender {0}>".format(self.name) | |
if __name__ == "__main__": | |
Action.scheduler = Scheduler() | |
sender1 = Sender('sender#1', 0) | |
sender2 = Sender('sender#2', 1) | |
receiver1 = Receiver() | |
receiver2 = Receiver() | |
sender1.output << receiver1.input | |
receiver1.input << receiver2.input << sender2.output | |
#sender2.output << receiver1.input << receiver2.input << sender1.output | |
sender1.do() | |
receiver1.input(10) | |
turn = 0 | |
while True: | |
print '-' * 20, turn | |
if not Action.scheduler.tick(): | |
break | |
turn += 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment