Bruce Eckel wrote: > Since the enqueuing process serializes all requests to active objects, > and since each message-task runs to completion before the next one > starts, the problem of threads interfering with each other is > eliminated. Also, the enqueuing process will always happen, so even if > the queue blocks it will be for a very short, deterministic time. So > the theory is that Active Object systems cannot deadlock (although I > believe they can livelock).
I've done this at work (in C++, not Python), and it works very well. I had my doubts when my boss first put the architecture for it in place, but a couple of years of working with this architecture (and that boss!) persuaded me otherwise. Livelock is a definite issue, particular if you design the individual active objects as finite state machines - it is fairly easy to get into a situation where Object A is waiting for a particular message from Object B, while Object B is waiting for a particular message from Object A. This chain is generally indirect, which makes it hard to spot. It is, however, still easier to figure this out than it is to figure out normal threading bugs, because you can find it just by analysing a sequence diagram showing message exchange and state transitions, rather than caring about the actual underlying code. Threading bugs, on the other hand, can turn up any time you access a shared data structure. > BTW: I think that Hoare's Communicating Sequential Processes (CSP) > basically describes the idea of active objects but without objects. > That is, I think active objects is CSP applied to OO. Or to put it another way, applying OO to CSP is a matter of hiding the addressing and sending of messages behind method calls. It becomes almost like doing in-process remote procedure calls. I think there's a definite synergy with PEP 342 here as well - one of the problems with handling Active Objects is how to allow other messages to be processed while making a blocking call, without losing your current state. One way is to hold any state that persists between messages in the object itself, but that's a seriously unnatural style of programming (it can be done, it's just a pain). PEP 342's yield expressions can probably be used to help address that problem, though: class SomeAO(ActiveObject): def processSomeMessage(self): msg = yield # Do something with the message next_msg = yield makeSomeBlockingCall(self) # Do something with the next message Regards, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.blogspot.com _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com