[Stackless] How does the PyStackless_RunWatchdog work and what's"main tasklet"?

Richard richard at ccpgames.com
Mon Mar 20 13:43:10 CET 2006

> On Behalf Of Juho Mäkinen
> Hello. I'm experimenting how to integrate Stackless inside 
> our game engine,
> but there's little or none good documentation how the Stackless works.
> The best resources so far have been the EVE Powerpoint from 
> PyCon, which
> only hows small keypoint areas from the code.
> Anyway, I'd like if somebody could describe what the Main Tasklet is,
> how it differs from other tasklets

>From http://www.stackless.com/wiki/Scheduling

The Main Tasklet

Before any tasklets are created, the context that exists initially is called the main tasklet. Here your application probably initialises itself and creates some tasklets in doing so, then does some sort of loop ensuring that it continues until all operation is complete. This is needed because if the main tasklet exits, so does the application, resulting in the implicit death of all existing tasklets.

Unless your use of tasklets is pretty straightforward, where you know that there will always be at least one other in existance, other than the main one. You cannot rely on just calling the run method or looping while calling it to preemptively schedule. Tasklets stalled on channels and others that are blocked do not count towards the running tasklet count and need to be waited for.

Anyone want to mention what it may leave out?  Or better yet
edit the page in the wiki as well :)

> and what does PyStackless_RunWatchdog do?

It runs the scheduler for the given number of instructions and
then interrupts the running tasklet, returning it.  It may
return prematurely because there are no remaining tasklets
scheduled.  Etc.  In theory, if you look at the doc string
of 'stackless.run', this should be exactly what it tells you.

In the Python snippets I included in my last post to the list,
I used this to regularly interrupt whichever tasklet was the
current running one in order to awaken sleeping tasklets and
to yield to the operating system.  But thinking about it,
while I was making that post, something I need to check is
that the tasklet that was interrupted is the one that is
scheduled next.  Otherwise, I wouldn't have the predictability
that comes from cooperative scheduling as my tasklets may
have been interrupted anywhere and forced to yield for any
number of arbitrary other tasklets before being able to
continue, unaware of their interruption.

What is different in EVE, as you can see from the snippets
in the slides, is that we run the watchdog with a very large
timeout period.  The reason we do this is that we know that
most of the time the list of scheduled tasklets is empty and
the scheduler will return in short order (certainly before
the watchdog hits its limit).  So, any tasklet returned is
guaranteed to be one that is running too long or out of
control.  And we can then stacktrace it, kill it, do stuff
we need to do in the meantime before reinserting it or
whatever.  But keeping the list of scheduled tasklets
empty relies on not having long living loops that just call
the equivalent of 'stackless.schedule'.  Our BeNice()
function is an alternative form of yielding that we use
which removes the tasklet from the list of scheduled
ones if it yields.

Anyway, please reply to the list saying so if this helps
with any notes about aspects that you consider important
or suggestions about additions.  Unless someone else steps
forward to do so, I'll add something about it to the wiki.

If anyone has any example code which uses it, which can
be added to the Stackless demo directory, it might be
a better resource than the allusions in the CCP slides.

Hope this helps,

Stackless mailing list
Stackless at stackless.com

More information about the Stackless mailing list