This subclass of Twisted’s selectreactor has methods to yield control of the reactor to its caller, and resume control later.
The guts of mainLoop have been moved to a generator method, and mainLoop instantiates the generator and calls .next() on it.
There are new methods for new functionality.
.release() causes the mainLoop to yield at the end of its current iteration.
.resume() transfers control back into the reactor. A .resume call is like .run, in that it does not yield control until the next .release or .stop.
.isRunning() tells you whether the reactor is running.
from twisted.python import log, failure, util
from twisted.internet.selectreactor import SelectReactor
class PausingReactor(SelectReactor):
"""Implement selectreactor that can be exited and resumed. """
def __init__(self, *args):
SelectReactor.__init__(self, *args)
self._releaseRequested = False
self._mainLoopGen = None
def _mainLoopGenerater(self):
"""Generater that acts as mainLoop, but yields when
requested.
"""
while self.running:
try:
while self.running:
# Advance simulation time in delayed event
# processors.
self.runUntilCurrent()
t2 = self.timeout()
t = self.running and t2
self.doIteration(t)
if self._releaseRequested:
self._releaseRequested = False
yield None
except:
log.msg("Unexpected error in main loop.")
log.deferr()
else:
log.msg('Main loop terminated.')
def mainLoop(self):
"""Setup mainLoop generater, and initiate looping. """
self._mainLoopGen = self._mainLoopGenerater()
self.resume()
def resume(self):
"""Resume mainLoop looping after interruption. """
try:
self._mainLoopGen.next()
except StopIteration:
pass
def release(self):
"""Request main loop pause and reacter yield to caller. """
self._releaseRequested = True
def isRunning(self):
"""Is reactor running? """
return self.running
def install():
"""Configure the twisted mainloop to be run using the pausingreactor.
"""
reactor = PausingReactor()
from twisted.internet.main import installReactor
installReactor(reactor)
__all__ = ['install']
To use the module,
import pausingreactor; pausingreactor.install()
The pausingreactor module, and a couple of files to test it, are linked. The stresstest.py sends increasing long strings to an echo type server ‘uppercaser_ns.py’, reads them back and checks them for intactness. It also pauses a couple times per second for a fraction of a second.
pausingreactor.py
stresstest.py
Enjoy.
11 December 2007 at 12:15 pm
[...] Add an option 6. Create a Twisted reactor subclass that can be exited and resumed. See later blogposts here for details. [...]