[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