Quoth Dave Brueck <[EMAIL PROTECTED]>:
...
| Another related benefit is that a lot of application state is implicitly and | automatically managed by your local variables when the task is running in a | separate thread, whereas other approaches often end up forcing you to think in
| terms of a state machine when you don't really care* and as a by-product you | have to [semi-]manually track the state and state transitions - for some | problems this is fine, for others it's downright tedious.
I don't know if the current Stackless implementation has regained any of this ground, but at least of historical interest here, the old one's ability to interrupt, store and resume a computation could be used to
As you may know, it used to be, in Stackless Python, that you could have both. Your function would suspend itself, the select loop would resume it, for something like serialized threads. (The newer version of Stackless lost this continuation feature, but for all I know there may be new features that regain some of that ground.)
Yep, I follow Stackless development for this very reason. Last I heard, a more automatic scheduler was in the works, without which in can be a little confusing about when non-I/O tasks should get resumed (and by who), but it's not insurmountable. Ideally with Stackless you'd avoid OS threads altogether since the interpreter takes a performance hit with them, but this can be tough if you're e.g. also talking to a database via a blocking API.
I put that together with real OS threads once, where the I/O loop was a
message queue instead of select. A message queueing multi-threaded
architecture can end up just as much a state transition game.
Definitely, but for many cases it does not - having each thread represent a distinct "worker" that pops some item of work off one queue, processes it, and puts it on another queue can really simplify things. Often this maps to real-world objects quite well, additional steps can be inserted or removed easily (and dynamically), and each worker can be developed, tested, and debugged independently.
I like threads when they're used in this way, as application components that manage some device-like thing like a socket or a graphic user interface window, interacting through messages. Even then, though, there tend to be a lot of undefined behaviors in events like termination of the main thread, receipt of signals, etc.
That's how I tend to like using threads too. In practice I haven't found the undefined behaviors to be too much trouble though, e.g. deciding on common shutdown semantics for all child threads and making them daemon threads pretty much takes care of both expected and unexpected shutdown of the main thread.
Usings threads and signals can be confusing and troublesome, but often in cases where I would use them I end up wanting a richer interface anyway so something besides signals is a better fit.
-Dave -- http://mail.python.org/mailman/listinfo/python-list