[Python-Dev] Active Objects in Python
Nick Coghlan
ncoghlan at gmail.com
Wed Sep 28 00:17:03 CEST 2005
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 | ncoghlan at gmail.com | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.blogspot.com
More information about the Python-Dev
mailing list