[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
super(NamedTasklet,self).__init__(func)
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"
try:
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)
else:
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
snake.Sync.beNice()
print "raising exception"
raise ValueError("my exception")
def g():
print 'g'
snake.Sync.beNice()
listTasklets()
snake.Sync.beNice()
listTasklets()
def t():
print "Spawning f"
try:
spawn(f)
except Exception, e:
print "function f returned an exception"
print "Spawning g"
spawn(g)
print "Spawning done"
listTasklets()
_______________________________________________
Stackless mailing list
Stackless at stackless.com
http://www.stackless.com/mailman/listinfo/stackless
More information about the Stackless
mailing list