[Twisted-Python] Win32 events main loop
Andrew Bennetts
andrew-twisted at puzzling.org
Sun Mar 3 23:11:22 MST 2002
Hi all,
Here is the first *rough* cut of the Twisted main loop using Win32 events,
based upon internet.poll.
It seems to be okay for simpleserv.py, but I haven't tested it for anything
else. I'll leave that to a day when I'm not feeling so ill... I pretty
much guarantee it is mostly broken -- think of it as a proof of concept.
I think if I experiment with MsgWaitForMultipleObjects instead of
WaitForMultipleObjects, I can make it respond to Win32 window messages
properly; e.g. Ctrl-C and stopping when running as a service might work
nicely -- COM stuff would probably benefit too.
Enjoy!
-Andrew.
--- win32.py ---
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""A win32event based implementation of the twisted main loop.
To install the event loop (and you should do this before any connections,
listeners or connectors are added):
from twisted.internet import win32
win32.install()
"""
# Win32 imports
from win32file import WSAEventSelect, FD_READ, FD_WRITE, FD_CLOSE, \
FD_ACCEPT, FD_CONNECT
from win32event import CreateEvent, WaitForMultipleObjects, \
WAIT_OBJECT_0, WAIT_TIMEOUT, INFINITE
# Twisted imports
from twisted.python import log, threadable
import main
# globals
reads = {}
writes = {}
events = {}
def _addEvent(fd, why, events=events):
print '_addEvent:', fd, why
event = CreateEvent(None, 0, 0, None)
WSAEventSelect(fd, event, why)
events[event] = (fd, why)
return event
def addReader(reader, reads=reads):
"""Add a FileDescriptor for notification of data available to read.
"""
print 'addReader:', reader
if not reads.has_key(reader):
reads[reader] = _addEvent(reader, FD_READ|FD_ACCEPT|FD_CONNECT)
def addWriter(writer, writes=writes):
"""Add a FileDescriptor for notification of data available to write.
"""
print 'addWriter:', writer
if not writes.has_key(writer):
writes[writer] =_addEvent(writer, FD_WRITE)
def removeReader(reader):
"""Remove a Selectable for notification of data available to read.
"""
if reads.has_key(reader):
del events[reads[reader]]
del reads[reader]
def removeWriter(writer, writes=writes):
"""Remove a Selectable for notification of data available to write.
"""
if writes.has_key(writer):
del events[writes[writer]]
del writes[writer]
def removeAll():
"""Remove all selectables, and return a list of them."""
result = reads.keys() + writes.keys()
reads.clear()
writes.clear()
events.clear()
return result
def doWaitForMultipleEvents(timeout,
reads=reads,
writes=writes):
if timeout is None:
#timeout = INFINITE
timeout = 5000
else:
timeout = timeout * 1000
print 'timeout is:', timeout
handles = events.keys()
val = WaitForMultipleObjects(handles, 0, timeout)
print 'WaitForMultipleObjects returned:', val
if val == WAIT_TIMEOUT:
return
elif val >= WAIT_OBJECT_0 and val < WAIT_OBJECT_0 + len(handles):
print 'Here'
fd, why = events[handles[val - WAIT_OBJECT_0]]
print fd, why
log.logOwner.own(fd)
try:
if why & FD_READ|FD_ACCEPT|FD_CONNECT:
fd.doRead()
elif why == FD_WRITE:
fd.doWrite()
except:
log.deferr()
why = FD_CLOSE
if why == FD_CLOSE:
removeReader(fd)
removeWriter(fd)
try:
fd.connectionLost()
except:
log.deferr()
log.logOwner.disown(fd)
def install():
"""Install the poll()-based event loop."""
main.addReader = addReader
main.addWriter = addWriter
main.removeReader = removeReader
main.removeWriter = removeWriter
#main.doSelect = doPoll
main.doSelect = doWaitForMultipleEvents
main.removeAll = removeAll
def initThreads():
"""Do initialization for threads."""
if main.wakerInstalled:
# make sure waker is registered with us
removeReader(main.waker)
addReader(main.waker)
threadable.whenThreaded(initThreads)
__all__ = ["install"]
More information about the Twisted-Python
mailing list