[Stackless] Giving names for tasklets

Juho Mäkinen juho.makinen at gmail.com
Tue Jun 27 21:12:32 CEST 2006

Err, made the same misstake what Richard did, so here
is the mail again to the mailing list:

> http://www.stackless.com/pipermail/stackless/2006-April/001658.html
> But put a try/except around old_f(...) and also handle the exiting
> of the new_f.

Finally I managed to get all parts together and here is the results.
The code is not 100% independent, it uses snake.Sync.beNice()
method which idea we should all know from EVE PowerPoint presentation.

There seems to be one broblem thought. If I add a __del__
method to NamedTasklet, Stackless seems to fail into
the following assert:
Assertion failed: Py_UnwindToken->tempval == NULL, file
..\Python\ceval.c, line 3016
In the following code I removed the __del__ and everything works. Is this
a bug?

Feel free to comment and use this code anywhere (stackless.com wiki?)

 - Juho Mäkinen

import stackless
import snake

#Tasklet counter which is used to giver uid's (unique id) for tasklets
global_counter = 0

#Dictionary which holds all tasklets
global_tasklets = {}

class NamedTasklet(stackless.tasklet):
    """Wrapper for stackless.tasklet.
       This allows us to store extra parameter for each taskler,
       for example, name of the tasklet.

       This is to be used with snake.pyos.spawn

    def __new__(cls, func, name=''):
        return super(NamedTasklet,cls).__new__(cls, func)

    def __init__(self, func, name=''):
        global global_counter, global_tasklets
        global_counter += 1

        if not name:
            name = 'T%s' % global_counter

        self.name = name
        self.uid = global_counter;
        self.state = "S";

        global_tasklets[self.uid] = self


    def __str__(self):
        return 'NamedTasklet("%s", uid: %d)' % (self.name, self.uid)

def newTasklet(self, *args, **kwargs):
    This is a special wrapper which works with NamedTasklet and
    maintains global_tasklets -dictionary and exception catching.
    global global_tasklets
    f = self.tempval
    def new_f(old_f, args, kwargs):
        self.state = "R"
            old_f(*args, **kwargs)
        except Exception, e:
            self.state = "Z";
            self.exception = e;
            raise e

        del global_tasklets[self.uid]

    self.tempval = new_f
    stackless.tasklet.setup(self, f, args, kwargs)

def spawn(func, name=None, *args, **kwargs):
    Creates new tasklet. Use this instead of stackless.tasklet!
    tasklet = NamedTasklet(func, name)
    newTasklet(tasklet, *args, **kwargs)

def listTasklets():
    Lists all tasklets.

    A tasklet can be in the following states:
     - S: Starting. The tasklet has been created but it's not yet running
     - R: Running.
     - Z: Zombie. Exception ran out from the tasklet stack all way
down to Watchdog.
    global global_tasklets
    starting = 0
    running = 0
    exceptions = 0
    total = 0

    for tasklet in global_tasklets.itervalues():
        if (tasklet.state == "R"):
            running += 1
        elif (tasklet.state == "S"):
            starting += 1
        elif (tasklet.state == "Z"):
            exceptions += 1
        total += 1

        if (tasklet.state == "Z"):
            print "%4d %s: %s [%s]" % (tasklet.uid, tasklet.state,
str(tasklet), tasklet.exception)
            print "%4d %s: %s" % (tasklet.uid, tasklet.state, str(tasklet))

    print "Total %d tasklets (%d running [R], %d starting [S], %d
zombie [Z])" % (total, running, starting, exceptions)

# Test functions

def f():
    for i in xrange(1,10):
        print i

    print "raising exception"
    raise ValueError("my exception")

def g():
    print 'g'

def t():
    print "Spawning f"
    except Exception, e:
        print "function f returned an exception"

    print "Spawning g"
    print "Spawning done"

Stackless mailing list
Stackless at stackless.com

More information about the Stackless mailing list