r1 - 01 Jun 2004 - 13:49:00 - BrianKirschYou are here: OSAF >  Projects Web  >  DevelopmentHome > ServicesWorkingGroup > EmailService > TwistedHome > ChandlerTwistedInThreadedEnvironment

Overview


Integrating Twisted in to the current Chandler architecture will involve the following steps:
1. Add Twisted and its dependencies to the Chandler build process
2. Create a thread wrapper around the Twisted Reactor
3. Define a base class for Chandler code that wishes to be Twisted
4. Start the Twisted thread wrapper on Chandler startup and shut it down on Chandler exit


Chandler Build Integration


Markie and I have begun discussions on how best to accomplish this and a bug has been filed in Bugzilla. However, we are still in the beginning stages.


Running Twisted in a thread


By placing the Twisted Reactor in a thread, Chandler can continue to run the WXWindows event loop on the main thread. Classes wishing to execute methods in the Reactor use reactor.callFromThread(method, *args, **kw). The callFromThread method executes code in the Reactor thread (which is a requirement for proper asynch event handling).


Reactor Thread Source Code:



from twisted.internet import defer, reactor
import threading
from twisted.python import threadable

__author__ ="Brian Kirsch <bkirsch@osafoundation.org>"

#required for using threads with the Reactor
threadable.init()


class ReactorException(Exception):
      def __init__(self, *args):
            Exception.__init__(self, *args)
            

class ReactorThread(threading.Thread):    
  
      """Run the Reactor in a Thread to prevent blocking the 
         Main Thread once reactor.run is called"""
    
      def __init__(self):
              threading.Thread.__init__(self)
              self._reactorRunning = False
              
      def run(self):
              if self._reactorRunning:
                    raise ReactorException("Reactor Already Running")
              
              self._reactorRunning = True
              
              #call run passing a False flag indicating to the
              #reactor not to install sig handlers since sig handlers
              #only work on the main thread

              reactor.run(False)                  
        
      def callInReactor(self, callable, *args, **kw):
            if self._reactorRunning:
                  reactor.callFromThread(callable, *args, **kw)

            else:
                  callable(*args, **kw)                 
            
      def isReactorRunning(self):
              return self._reactorRunning
       
      def startReactor(self):
             if self._reactorRunning:
                    raise ReactorException("Reactor Already Running")
             
             threading.Thread.start(self)
             
             reactor.addSystemEventTrigger('after', 'shutdown', self.__reactorShutDown)
              
            
      def stopReactor(self):
            """may want a way to force thread to join if reactor does not shutdown
               properly. The reactor can get in to a recursive loop condition if reactor.stop 
               placed in the threads join method. This will require further investigation. 
              """
            
            if not self._reactorRunning:
                   raise ReactorException("Reactor Not Running")
           
            reactor.callFromThread(reactor.stop)
             
 
      def addReactorEventTrigger(self, phase, eventType, callable):
             if self._reactorRunning:
                reactor.callFromThread(reactor.addSystemEventTrigger, phase, eventType, callable)

             else:
                reactor.addSystemEventTrigger(phase, eventType, callable)
                    
                     
      def __reactorShuttingDown(self):
            pass

      def __reactorShutDown(self):
            """This method called when the reactor is stopped"""
            self._reactorRunning = False



Chandler objects extend TwistedBase? to leverage Twisted


Twisted itself is a complicated enough framework. Developers who understand Twisted will not want another layer of abstraction over Twisted. So the goal was to put the thinest wrapper possible around Twisted code. The one special condition that must be captured and handled in Twisted code is Chandler application shutdown. If code is in the middle of a series of callbacks it must stop the callback chain and perform any clean up required. The TwistedBase? class captures the reactor shutdown event and calls its child classes onShutdown method. The onShutdown method will be called when the Chandler

-- BrianKirsch - 01 Jun 2004

Edit | WYSIWYG | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r1 | More topic actions
 
Open Source Applications Foundation
Except where otherwise noted, this site and its content are licensed by OSAF under an Creative Commons License, Attribution Only 3.0.
See list of page contributors for attributions.