[Stackless] Advice on Writing a Stackless Reactor for Twisted

David Wyand TheHeadGnome at gnometech.com
Tue Jan 16 08:23:00 CET 2007


Greetings!

I'm quite new to Stackless and this is my first post here. ::waves::  I'm also fairly new to Twisted and am returning to Python after a long absence.  My goal is to is to use these three technologies along with the Torque Game Engine to build a multiplayer game.  I'm currently in the technology testing stage.

I've recently gone through the exercise myself of writing a custom Twisted reactor for use with Stackless (under Python 2.4).  After looking at what has been proposed on the Twisted mailing list, I took the direction of Stackless driving Twisted rather than the other way around.  After combining some techniques from Josh Ritter (over at GarageGames), Richard Tew (uthread is cool) and other sources, here's what I've come up with.

So far my own testing indicates everything is working as expected.  But it would be great to know if anyone finds any issues with my implementation.  And hopefully this'll help Andrew out.  I've included my stackless reactor as well as a snippet on how to use it.  You'll have to provide your own Twisted-based HTTP server if you want to run the example as is.

--- stacklessreactor.py ---

__all__ = ['install']
import sys
import stackless
import uthread
from twisted.internet import selectreactor

gReactor = None

def ReactorTick():
    global gReactor
    while(gReactor.running != 0):
        gReactor.simulate()
        uthread.BeNice()

class StacklessReactor(selectreactor.SelectReactor):
    def __init__(self):
        super(StacklessReactor, self).__init__()
        self.stopped = False
        
    def crash(self):
        print "StacklessReactor crash!"
        self.running = 0
        self.stopped = True
        
    def run(self):
        print "StacklessReactor starting to run"
        self.startRunning()
        stackless.tasklet(ReactorTick)()
        
    def simulate(self):
        self.iterate()
        
def StacklessReactorInstall():
    global gReactor

    print "StacklessReactorInstall() executed"
    
    reactor = StacklessReactor()
    gReactor = reactor
    
    from twisted.internet.main import installReactor
    installReactor(reactor)
    return reactor

install = StacklessReactorInstall

--- maintest.py ---

import stackless
import uthread

def ServerStartup():
    from twisted.internet import reactor
    from httpserver import MyHttpFactory
    
    print "Starting up the HTTP server"
    reactor.listenTCP(8001, MyHttpFactory())
    reactor.run()
    
def run():
    """Replacement for uthread.run()"""
    while(reactor.stopped == False):
        uthread.RunNiceTasklets()
        t = stackless.run(10000000)
        if t is not None:
            # Need better standard handling of this case.
            # Could StackTrace I guess?
            raise RuntimeError("Runaway tasklet", t)
        uthread.CheckSleepingTasklets()


if __name__ == "__main__":
    import stacklessreactor
    stacklessreactor.install()

    from twisted.internet import reactor
    
    print "Running reactor"
    stackless.tasklet(ServerStartup)()
    run()
    print "Finished running reactor"

------

The only other thing I was going to add is the handling of Twisted deferreds using the same method as suggested in http://twistedmatrix.com/trac/browser/sandbox/radix/threadless.py blockOn() function.

Hope that helps!

- Dave
http://www.gnometech.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.stackless.com/pipermail/stackless/attachments/20070116/4b6734bf/attachment.htm>
-------------- next part --------------
_______________________________________________
Stackless mailing list
Stackless at stackless.com
http://www.stackless.com/mailman/listinfo/stackless


More information about the Stackless mailing list