[Stackless] Updated version of the CCP games uthread library

Richard Tew richard.m.tew at gmail.com
Sat Oct 14 14:50:51 CEST 2006


I just checked in a fixed and updated version of the uthread library
which CCP recently let me release.  So I just thought I would write a
little about the functionality it offers.  You can find it here:

http://svn.python.org/view/stackless/sandbox/libraries/uthread-ccp/

In order to make best use of it, you have to use the functions it
provides instead of the equivalent ones in Stackless itself.  The
reason for this is that the functionality it provides is based on
the approach to tasklet scheduling we use internally at CCP.

Tasklets are only in the scheduler until they yield.  So the
scheduler can be run with a large timeout and we know that it will
exit pretty much immediately unless the code in the running
tasklets is written badly.

Instead of yielding through 'stackless.schedule()', the replacement
functions 'uthread.benice()' and 'uthread.sleep()' are provided.
'benice' is equivalent to 'schedule' and 'sleep' takes an argument
of a number of seconds which is ho long the current tasklet should
yield before reawakening.

e.g.   def NiceYieldingLoop():
           while 1:
               uthread.benice()

       def SleepingTasklet():
           while 1:
               print "Sleeping for 3 seconds."
               uthread.sleep(3.0)

And instead of calling 'stackless.run()', 'uthread.run()' must be
used instead.  It isn't actually necessary to use it for all the
functionality in the module, but there is a number of things which
rely on the custom scheduling it provides in order to work at all.
For instance sleeping and being nice.  Without custom handling of
scheduling there is nothing that will awaken tasklets which have
chosen to block in these ways.

Locking related functionality it provides..

e.g.   class SomeClass:
           def LockingFunction(self):
               # Use this instance of the class as the ID of the
               # lock to be acquired in order to prevent other
               # calls on the instance from doing related operations
               # at the same time.
               uthread.Lock(self)
               try:
                   # Custom logic which requires the locking.
                   pass
               finally:
                   uthread.UnLock(self)

       class SomeClass2:
           def ReentrantLockingFunction(self):
               # Same deal as the previous example, but allow
               # reentrant locking by the current tasklet.
               uthread.ReentrantLock(self)
                   # Recursively reenter the function to some degree.
                   if random.random() > 0.1:
                   	self.ReentrantLockingFunction()
               finally:
                   uthread.UnLock(self)

       class SomeClass3:
           # Use a provided decorator to do the locking boilerplate.
           @uthread.with_instance_locking
           def LockingFunction(self):
	       # Custom logic which requires the locking.
               pass

Keep in mind that there is logic which peiodically checks for
locking conflicts or deadlocks, but this requires 'uthread.run()'
be used so that Sleep will work.

There is more I haven't gone into further detail about.  For instance
'thread pooling' for tasklets, custom tasklet scheduling functions
one of which runs tasklets out of the tasklet pool, another runs them
as workers and yet another that runs a set of tasklets in parallel and
then returns all the collected results.

Cheers,
Richard.

_______________________________________________
Stackless mailing list
Stackless at stackless.com
http://www.stackless.com/mailman/listinfo/stackless



More information about the Stackless mailing list