[Twisted-Python] Running callbacks in a non-main thread

Gabe Rudy rudy at goldenhelix.com
Fri Feb 3 15:29:21 MST 2006


Hey,
I realize that the point of deferreds is to have process/network intensive 
tasks work on in their own thread and send the results to callback function 
in the main thread, but is there away to have a deferred process it's 
callback in a non-main thread?

I'm sure someone will want to know why, and maybe solving my meta-problem 
would show me the errors in my ways in wanting to warp the purpose of the 
mighty deferred.

Async is great, but I'm slowly replacing some code that uses xmlrpc (blocking) 
with prospect broker objects (returns deferred, hence non-blocking). What I'm 
trying to hack is a method to make a non-blocking call in the main thread 
blocking until the deferred returns a result, hence emulating the blocking 
nature of xmlrpc. This dependency is something I would like to phase out, but 
certain things need it, so work with me eh?

My hack is to simply use a threading.Event to wait for the callback to be 
called in a non-waiting thread, save the value and do the let the main thread 
return the result. Of course this doesn't work when callbacks run in the main 
thread because the main thread is blocked.

#Bits of hack code:
class Block
    def waitFor(self, function, *args, **kwargs):
        if not hasattr(self,'async_done'):
            self.async_done = threading.Event()
        
        self.result = None
        #ceate a thread to wait for callback.
	threads.deferToThread(function, *args, 
**kwargs).addCallback(self._cbWait).addErrback(self._ebWait)

        #block on results of thread to be set
        self.async_done.wait()
        self.async_done.clear()
        return self.result
 
    #This is never called, because main thread is blocked
    def _cbWait(self, deferred):
        #expect original function to return a deferred
        deferred.addBoth(self._cbValue)
        
    def _ebWait(self, reason):
        print "ERROR in getting remote function: ",reason

    def _cbValue(self, v):
        self.result = v
        self.async_done.set()

Any ideas O masters of the twisted?

Gabe Rudy




More information about the Twisted-Python mailing list