[Stackless] Figuring out stackless for use in Twisted

Christopher Armstrong radix at twistedmatrix.com
Tue Jul 29 00:00:01 CEST 2003


On Mon, Jul 28, 2003 at 01:51:08PM +0200, Christian Tismer wrote:
> Christopher Armstrong wrote:
> 
> >So, I'm trying to write a Stackless Reactor for Twisted.
> 
> That sounds phantastic.
> 
> >I'm pretty clueless about Stackless, now, though. Is there any
> >relevant documentation other than what's in the docstrings of the
> >stackless module and the classes it contains?
> 
> No. I'm building a Wiki, but due to recent financial
> problems, I didn't finish what I started 2 weeks ago.

Can't you just put up a blank wiki on a web server and let the
community build it? I would certainly contribute. :-)

> >Right now I'm trying to figure out what exactly `become' does. The
> >docs say that it captures the current frame in the tasklet. I can
> >somewhat understand this, but I'm not sure what happens to the code
> >calling the function (named, say, FOO) that calls t.become(). Does it
> >just block until `t' switches context back? And: Does blocking on a
> >channel.receive automatically switch back to the main tasklet? I
> >assume that just means that the call to FOO will return?
> 
> If you call t.become(), the current running frame is
> ripped off the frame stack and wrapped by a new
> tasklet object. become() then returns to the caller
> (so the active tasklet stays active) and returns the
> new tasklet as a value, unless you provide a different one.

Hmm. So that means I need to then call the run method on the new
tasklet? or maybe __call__?  hrmm, the code I've been reading as an
example (Sheared -- thanks Sune!) doesn't seem to do that. So I still
don't get it. It just passes a channel object to the `become' method,
and doesn't care about its return value. Maybe I should get Sune to
explain things more :-)

> In contrast, if you call t.capture(), the same happens,
> but the newly created tasklet continues to execute,
> leaving the old tasklet behind in the list of runnables.
> 
> When the original tasklet is resumed depends on how
> many other tasklets are in the runnables queue.
> This is no blocking, it is just scheduling order.

hmm, ok. I need to explain what I'm doing some more.

I want to control all context swithes myself. I think that's what
`setatomic' allows? But anyway, my reactor, every time it calls
"user-code", is going to start up a new tasklet for that code, and
call it (there may be future optimizations that won't start a new
tasklet for _every_ user-function, but I do not want to think about
that yet). 

The user code itself needs to say when it needs to block (I will
provide nice abstractions for this) and I _always_ want the reactor
(i.e., main tasklet) to be switched to when the user-tasklet
blocks. The reactor will later say when to continue the user-tasklet,
when the thing that the user-tasklet was waiting for has occured.

So this is what I'm thinking it should look like

def callUserFunction(self, f, *args, **kwargs):
    t = stackless.tasklet()
    c = stackless.channel()
    # whatever other setup code
    remember the tasklet and channel for later reference
    call the function `f' in tasklet `t', making sure it knows about
         channel `c'


If `f' decides it needs to block, it will say so (by registering that
it's waiting for something to happen with my own code, and then
receive()ing on the channel), and then the call will return. If I can
get my code to the point described by the pseudo-code above, I think I
can handle everything else.


> The real blocking is in the channels. If channel.receive
> does not have a waiting sender, the receiver gets blocked,
> that is, it is ripped off the runables queue and put
> into a chain of the channel.
> After such blocking, the next available tasklet from the
> runnables list is activated, reagrdless whether this
> is main or not.

Ok. I just need to force it to switch to main, somehow. :-)

> >Just an annoying little thing. I've just been reading the docstrings
> >by browsing the source (and help(stackless.tasklet) still works). :-)
> 
> Oops, yes this is right. Since a while, I'm storing
> special values in the dict of the frame type, under
> an integer key. Didn't realize this.
> So probably I have to change this? Is it "forbidden"
> to have non-string keys in type dicts?

Well, I would say "it is forbidden to do anything that will break
getattr(o, key)" :-)

Thanks for the help!

-- 
 Twisted | Christopher Armstrong: International Man of Twistery
  Radix  |          Release Manager,  Twisted Project
---------+     http://twistedmatrix.com/users/radix.twistd/




More information about the Stackless mailing list