[Twisted-Python] callLater(0) is A BIG LIE

Jonathan Simms slyphon at twistedmatrix.com
Mon Nov 1 03:41:53 MST 2004


I'd like to offer some reflections on the reactor and facilitate some
conversation on a subject that's been causing me much frustration:

    the twisted idiom, "callLater(0)"

While it seems that this is a DelayedCall, it really is a lie. It has
nothing to do with time at all, it is a very *convenient* lie that we
all have accepted, but is a lie nonetheless.

We all know this means "call function f in the next reactor iteration", 
but the semantics of callLater have to do with time, not reactor
iterations. In fact, in the API documentation, there is no reference to
reactor iterations, at all.

I think the implicit nature of this idiom is bad.

For example in tcp.py:377

    reactor.callLater(0, self.failIfNotConnected, error)

what this really means is: "run this method at the beginning of the next 
reactor iteration, if my socket isn't connected, that method will fail"

Now, if the reactor were a "pure" event loop (in the way libevent is,
with no scheduling), callLater(0) would mean, "Call function f *ASAP*
after this function exits". There would be no guarantees as to what
would get run next.

The workaround (in terms of my implementation) is to emulate this
scheduling behavior the select reactor provides, but this kills some of
the performance gains one gets from using libevent.  When I asked the
libevent guys about this, they said it seemed like a brokenness of our
library.

I guess the question is, is there a better way for twisted to handle
this type of thing? Would it be more to our advantage to make scheduling
a different abstraction with explicit well-defined methods?

-Jonathan






More information about the Twisted-Python mailing list