[PEAK] Anybody using reactors?

Phillip J. Eby pje at telecommunity.com
Tue Jan 13 19:54:21 EST 2004

I've just done a partial merge of events.Scheduler and 
running.UntwistedReactor.  This merge allows the new event-driven "threads" 
to use timed events within a reactor-driven program.

In the long term, though, I would like to drop UntwistedReactor altogether, 
while refactoring MainLoop to use peak.events, and there are some 
transitional issues that would need to be addressed.

Most obvious of these is that if you're using a Twisted reactor, there will 
need to be a way to make it continue to run 'iterate()' operations.  A 
side-effect of this is that the reactor's 'run()' method will never be 
called, which means that Twisted startup/shutdown events will not run.  Is 
anybody relying on those events?  Even if you're *not* using a Twisted 
reactor, are you relying on the value of 'reactor.running' anywhere?  Do 
you ever call 'reactor.run()'?

So, the next issue is that the MainLoop will need to stop calling 
reactor.run(), and simply perform a scheduler-driven loop instead.  As a 
consequence, 'reactor.stop()' and 'reactor.crash()' calls will need to be 
redirected to the MainLoop.  Anybody using these directly?  (I can probably 
make this backward compatible, but it'd be helpful to know.)

The biggest issue I see at the moment is integrating I/O handling between a 
Twisted reactor and 'peak.events'.  I don't see an easy way to do this that 
wouldn't result in PEAK and Twisted fighting over how much time to run 
'select()' for.  So, I think there will need to be two 'events.ISelector' 
implementations.  One, a "native" selector using an events.Thread to run 
'select()' operations between timed events, and the other a 
"reactor-driven" selector that registers callbacks with a reactor, and 
calls 'reactor.iterate(scheduler.time_available())' between timed events.

The latter selector implementation would need to be used whenever one was 
depending upon ITwistedReactor.  However, this would introduce additional 
complexity when configuring such applications, since you'd need to add 
something like:

[Component Factories]
peak.events.interfaces.ISelector = events.TwistedSelector
peak.running.interfaces.IBasicReactor = 'peak.running.scheduler.getTwisted'

to your app's .ini file.  It would no longer be enough to depend on 

A further issue is that 'IBasicReactor' itself would need to be phased out 
in the a4 release cycle.  Once PEAK has moved over to the 'peak.events' 
model, I don't want to try to continue directly supporting the 
reactor-driven paradigm, unless this would cause undue hardship for people 
with reactor-driven apps.

However, that last point is only an issue for people who've written 
reactor-driven apps based on PEAK's UntwistedReactor, rather than using 
Twisted.  And in any event, the alpha 3 final release will still include an 
UntwistedReactor, it's just that it will be implemented using 
'peak.events'.  So, it's only in the alpha 4 release cycle that you would 
need to migrate from using UntwistedReactor to using 'peak.events' directly.

So...  if you're doing event-driven programming in PEAK currently, and have 
input or questions on the above issues, please speak up.  To reiterate:

Are you directly using reactor.running, reactor.run(), reactor.stop(), or 
reactor.crash() in your programs?  If yes, you will have issues in alpha 3 
if you use Twisted, or alpha 4 if you use only UntwistedReactor.  Also, if 
you use Twisted, you may have to change your application configuration 
somewhat during alpha 3, in order to maintain compatibility.  Finally, if 
you do not directly use a reactor with PEAK, you should not notice any 
changes in either release, since PEAK's internal usage of reactors will be 
transparently replaced during the a3 release cycle.

Any questions or problems?

More information about the PEAK mailing list