Re: [Python-Dev] Active Objects in Python
On Friday 30 September 2005 22:13, Michael Sparks (home address) wrote: > I wrote a white paper based on my Python UK talk, which is here: > * http://www.bbc.co.uk/rd/pubs/whp/whp11.shtml Oops that URL isn't right. It should be: * http://www.bbc.co.uk/rd/pubs/whp/whp113.shtml Sorry! (Thanks to LD 'Gus' Landis for pointing that out!) Regards, Michael. -- "Though we are not now that which in days of old moved heaven and earth, that which we are, we are: one equal temper of heroic hearts made weak by time and fate but strong in will to strive, to seek, to find and not to yield" -- "Ulysses", Tennyson ___ 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
Re: [Python-Dev] Active Objects in Python
[ I don't post often, but hopefully the following is of interest in this discussion ] Bruce Eckel wrote: > Yes, defining an class as "active" would: > 1) Install a worker thread and concurrent queue in each object of that > class. > 2) Automatically turn method calls into tasks and enqueue them > 3) Prevent any other interaction other than enqueued messages Here I think the point is an object that has some form of thread with enforced communications preventing (or limiting) shared data. This essentially describes the project we've been working on with Kamaelia. Kamaelia is divided into two halves: * A simple framework (Axon) for building components with the following characteristics: * Have a main() method which is a generator. * Have inbound and outbound named queues implemented using lists. (akin to stdin/out) * Access to an environmental system which is key/value lookup (similar purpose to the unix environment). (This could easily grow into a much more linda like system) * A collection of components which form a library. We also have a threaded component which uses a thread and queues rather than a generator & lists. With regard to the criteria you listed in a later post: 1) Has been tested against (so far) 2 novice programmers, who just picked up the framework and ran with in. (learnt python one week, axon the next, then implemented interesting things rapidly) 2) We don't deal with distribution (yet), but this is on the cards. Probably before EuroOSCON. (I want to have a program with two top level pygame windows) 3) We use python generators and have experimented initially with several tens of thousands of them, which works suprisingly well, even on an old 500Mhz machine. 4) Self guarding is difficult. However generators are pretty opaque, and getting at values inside their stack frame is beyond my python skills. 5) Deadlock can be forced in all scenarios, but you would actually have to work at it. In practice if we yield at all points or use the threaded components for everything then we'd simply livelock. 6) Regarding an actor. Our pygame sprite component actually is very, very actor like. This is to the extent we've considered implementing a script reading and director component for orchestrating them. (Time has prevented that though) 7) Since our target has been novices, this has come by default. 8) We don't do mobility of components/tasks as yet, however a colleague at work interested in mobility & agent software has proposed looking at that using Kamaelia for the coming year. We also ran the framework by people at the WoTUG (*) conference recently, and the general viewpoint came back that it's tractable from a formal analysis and mobility perspective(if we change x,y,z). (*) http://www.wotug.org/ I wrote a white paper based on my Python UK talk, which is here: * http://www.bbc.co.uk/rd/pubs/whp/whp11.shtml (BBC R&D white papers are aimed at imparting info in a such a way that it's useful and readable, unlike some white papers :) So far we have components for building things from network servers through to audio/video decoders and players, and presentation tools. (Using pygame and tkinter) Also we have a graphical editting tool for putting together systems and introspecting systems. An aim in terms of API was to enable novices to implement a microcosm version of the system. Specifically we tested this idea on a pre-university trainee who built a fairly highly parallel system which took video from an mpg file (simulating a PVR), and sent periodic snapshots to a mobile phone based client. He had minimal programming experience at the start, and implemented this over a 3 months period. We've since repeated that experience with a student who has had 2 years at university, but no prior concurrency, python or networks experience. In his 6 weeks with us he was able to do some interesting things. (Such as implement a system for joining multicast islands and sending content over a simple reliable multicast protocol). The tutorial we use to get people up to speed rapidly is here: * http://kamaelia.sourceforge.net/MiniAxon/ However that doesn't really cover the ideas of how to write components, use pipelines, graphlines and services. At the moment we're adding in the concept of a chassis into which you plug in existing components. The latest concept we're bouncing round is this: # (This was fleshed out in respect to a question by a novice on c.l.p - # periodically send the the same message to all connected clients) # start from Kamaelia.Chassis.ConnectedServer import SimpleServer from Kamaelia.Chassis.Splitter import splitter, publish, Subscriber class message_source(component): [ ... snippety ... ] def main(self): last = self.scheduler.time while 1: yield 1 if
Re: [Python-Dev] Active Objects in Python
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). My experience with active objects is with SDL (the Specification and Description Language). There, the primitive communication between objects is through one-way messages (called signals). Such a system can deadlock if an object doesn't produce "enough" new outgoing messages in response to incoming messages. If all communication is through RPCs, i.e. you owe your caller a response, then the only way to deadlock such a system is that all active objects terminate. The interesting question then is whether an object can terminate while processing a message, and whether this will cause a response to be sent back. > But what's not clear is whether this would > require knowledge of the innards of the Python interpreter (which I > don't have) or if it could be built using libraries. As others have pointed out, you have to find a way to deal with the standard library. In principle, each active object should have its own copy of the standard library. For some modules/objects, this is not reasonable (e.g. stdout). In OCCAM, host IO itself is (conceptually) an occam process, so sys.stdout would have to become an active object. In that approach, you would essentially have to rewrite parts of the standard library, wrapping the underlying modules appropriately. > 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. I don't believe this is true. In CSP, communication between processes is through rendezvous, which is quite different from active objects, as there is no queue for incoming calls - instead, the receiving process must expect a specific communication partner just like the sending process; there is also no inherent request/response mechanism in CSP. In CSP, there is plenty of chance for deadlocks. If a process becomes STOP (i.e. the process that will never again interact), then any communication attempt with that process also cause the partner to become STOP. Regards, Martin ___ 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
Re: [Python-Dev] Active Objects in Python
Greg Ewing wrote: > Nick Coghlan wrote: > > >>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 > > > I don't see how that helps, since makeSomeBlockingCall() > is evaluated (and therefore blocks) *before* the yield > happens. Chris got it right - I just named the function badly. The idea is that there would be an interaction with the Active Object's event loop to get the actual result back once it was available from the thread that actually made the blocking call. In the meantime, *this* object could continue to handle other messages. What the approach allows is to have a single physical thread with a number of coroutiney-type event handlers running inside it. Cheers, 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
Re: [Python-Dev] Active Objects in Python
Oops. I forgot to add that to the list. Yes, in the working example of Active Objects that I've written in Java J2SE5, when you send a message to an active object, you get back a Future, which I suspect would be the same as your Deferred. Tuesday, September 27, 2005, 7:41:27 PM, Christopher Armstrong wrote: > On 9/28/05, Greg Ewing <[EMAIL PROTECTED]> wrote: >> Nick Coghlan wrote: >> >> > 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 >> >> I don't see how that helps, since makeSomeBlockingCall() >> is evaluated (and therefore blocks) *before* the yield >> happens. > Sounds like makeSomeBlockingCall is just misnamed (probably depending > who you ask). > I wrote a small library recently that wraps Twisted's Deferreds and > asynchronous Failure objects such that you can do stuff like > try: > x = yield remoteObject.getSomething() > except Foo: > print "Oh no!" > This is just a 2.5-ification of defgen, which is at > twisted.internet.defer.{deferredGenerator,waitForDeferred}. So anyway, > if your actor messages always return Deferreds, then this works quite > nicely. > -- > Twisted | Christopher Armstrong: International Man of Twistery >Radix|-- http://radix.twistedmatrix.com > | Release Manager, Twisted Project > \\\V/// |-- http://twistedmatrix.com >|o O|| > wvw-+ > ___ > 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/bruceeckel-python3234%40mailblocks.com Bruce Eckelhttp://www.BruceEckel.com mailto:[EMAIL PROTECTED] Contains electronic books: "Thinking in Java 3e" & "Thinking in C++ 2e" Web log: http://www.artima.com/weblogs/index.jsp?blogger=beckel Subscribe to my newsletter: http://www.mindview.net/Newsletter My schedule can be found at: http://www.mindview.net/Calendar ___ 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
Re: [Python-Dev] Active Objects in Python
On 9/28/05, Greg Ewing <[EMAIL PROTECTED]> wrote: > Nick Coghlan wrote: > > > 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 > > I don't see how that helps, since makeSomeBlockingCall() > is evaluated (and therefore blocks) *before* the yield > happens. Sounds like makeSomeBlockingCall is just misnamed (probably depending who you ask). I wrote a small library recently that wraps Twisted's Deferreds and asynchronous Failure objects such that you can do stuff like try: x = yield remoteObject.getSomething() except Foo: print "Oh no!" This is just a 2.5-ification of defgen, which is at twisted.internet.defer.{deferredGenerator,waitForDeferred}. So anyway, if your actor messages always return Deferreds, then this works quite nicely. -- Twisted | Christopher Armstrong: International Man of Twistery Radix|-- http://radix.twistedmatrix.com | Release Manager, Twisted Project \\\V/// |-- http://twistedmatrix.com |o O|| wvw-+ ___ 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
Re: [Python-Dev] Active Objects in Python
Nick Coghlan wrote: > 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 I don't see how that helps, since makeSomeBlockingCall() is evaluated (and therefore blocks) *before* the yield happens. -- Greg Ewing, Computer Science Dept, +--+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | [EMAIL PROTECTED] +--+ ___ 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
Re: [Python-Dev] Active Objects in Python
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
Re: [Python-Dev] Active Objects in Python
Phillip J. Eby wrote: > Well, you could pickle and unpickle the objects you send from one function > to another, and for cross-process communication, you'll need to do > something like that anyway, or else use that shared-memory objects > thing. PySHM? I don't remember its name, but it's an extension that lets > you store Python objects in shared memory and use them from multiple > processes, modulo certain strict limitations. "POSH": http://poshmodule.sourceforge.net/posh/html/ -- Benji York ___ 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
Re: [Python-Dev] Active Objects in Python
At 11:18 AM 9/27/2005 -0600, Bruce Eckel wrote: >Yes, defining an class as "active" would: >1) Install a worker thread and concurrent queue in each object of that >class. >2) Automatically turn method calls into tasks and enqueue them >3) Prevent any other interaction other than enqueued messages #3 is the sticky bit. Enforcing such restrictions in Python is *hard*. Each active object would have to have its own sys.modules, for example, because modules and classes in Python are mutable and use dictionaries, and modifying them from two thread simultaneously would be fatal. For built-in types it's not so bad, so they could be shared... except for the fact that they have reference counts, which need lock protection as well to avoid fouling up GC. So really, this idea doesn't really help with GIL removal at all. What it *does* help with, is effective use of multiprocessor machines on platforms where fork() is available, if the API works across processes as well as threads. >So yes, the best way for this to work might be some kind of enforced >implementation -- but forcing you to do something is not particularly >Pythonic, But keeping the interpreter from dumping core due to program bugs *is* Pythonic, which is why the GIL would need to stay. :) >so I would think that it would be possible to build an >active object framework along with some checking tools to warn you if >you are breaking the rules. Well, you could pickle and unpickle the objects you send from one function to another, and for cross-process communication, you'll need to do something like that anyway, or else use that shared-memory objects thing. PySHM? I don't remember its name, but it's an extension that lets you store Python objects in shared memory and use them from multiple processes, modulo certain strict limitations. > But what's not clear is whether this would >require knowledge of the innards of the Python interpreter (which I >don't have) or if it could be built using libraries. If you're not trying to get rid of the GIL or truly "enforce" things, you can do everything you need for CSP in plain old Python. peak.events has a generator-based microthread facility that's CSP-ish, for example, although it doesn't have decorators for async methods. They're not hard to write, though; Chandler has some for methods that get called across thread barriers now. That is, methods that get called from Chandler's UI thread but are run in the Twisted reactor thread. I've occasionally also thought about implementing async C#'s "chord" features in Python for peak.events, but I haven't actually had a use case that needed that much generality yet. ___ 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
[Python-Dev] Active Objects in Python
According to this list's welcome message, I should introduce myself. I'm Bruce Eckel, I write, consult and give seminars about computer programming, I use Python whenever I can get away with it, and I've spoken at Pycon a number of times. There are further URLs in my signature at the bottom. I'm joining this list because I was having a conversation with Guido about concurrency support in Python (in particular, using an actor/active-object approach) and he suggested I bring it over here. Here are the highlights of my most recent reply to him (Guido's remarks are marked by the '>' signs): > Agreed. IMO the pthreads-style solution doesn't work well no matter > *what* the programming model. Exactly. I think the problem may be that low-level threads people are one step behind (much like embedded systems programmers, which is where I began). They may be just now catching up to objects, but as far as concurrency goes their brains still think in terms of threads, so it seems natural to apply thread concepts to objects. But from an OO standpoint, pthread-style thinking is two steps backwards. You effectively throw open the innards of the object that you just spent time decoupling from the rest of your system, and the coupling is now unpredictable. It's the worst of all possible worlds. > I worked on Mobile Agents at CNRI from 1995 till 2000, but they were > very heavy-weight. Yet, I think that any solution that moves objects > between CPUs on a regular basis is going to suffer the same problem > that process switching in general gets you -- the move is so expensive > that it's hard to decide when it's justified. The examples I've seen haven't relied on mobility, so that's a question: how important is mobility really to an agent system? And could it be done in a trivial fashion in Python, by sending source code. And if it was really necessary sometimes, could it be something where the cost of mobility only occurred when moving an object? It's possible that either an argument can be made against mobility and/or some kind of trivial mobility system could be developed that would work when necessary. Possibly a Linda-like put-take system with pickles (off the top of my head). I don't know that much about mobility, but it does seem like mobile agents could be a powerful solution to the problem solved by enterprise messaging systems. > I believe you pointed me to Active Objects before, right? (Years ago, > maybe when you visited us at Zope.) I may have mentioned them in the past. > If multiple active objects can co-exist in the same *process*, but > nevertheless the language implementation prevents them from sharing > data except via channels, and in addition allows dynamic reallocation > of active objects across multiple CPUs, they just might be the ticket. > But it would require a complete implementation to prove it. Yes, defining an class as "active" would: 1) Install a worker thread and concurrent queue in each object of that class. 2) Automatically turn method calls into tasks and enqueue them 3) Prevent any other interaction other than enqueued messages At that point, the only time the GIL might be needed is to lock the queue at the point of putting ant taking objects. But there has been work done on lock-free data structures, which has been incorporated into Java 5 libraries, so it might even be possible to use a lock-free queue to do this and thus eliminate the need for the GIL at all. 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). So yes, the best way for this to work might be some kind of enforced implementation -- but forcing you to do something is not particularly Pythonic, so I would think that it would be possible to build an active object framework along with some checking tools to warn you if you are breaking the rules. But what's not clear is whether this would require knowledge of the innards of the Python interpreter (which I don't have) or if it could be built using libraries. 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. Bruce Eckelhttp://www.BruceEckel.com Contains electronic books: "Thinking in Java 3e" & "Thinking in C++ 2e" Web log: http://www.artima.com/weblogs/index.jsp?blogger=beckel ___ 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