2
# This library is free software; you can redistribute it and/or
3
# modify it under the terms of version 2.1 of the GNU Lesser General Public
4
# License as published by the Free Software Foundation.
6
# This library is distributed in the hope that it will be useful,
7
# but WITHOUT ANY WARRANTY; without even the implied warranty of
8
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9
# Lesser General Public License for more details.
11
# You should have received a copy of the GNU Lesser General Public
12
# License along with this library; if not, write to the Free Software
13
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
"""A win32event based implementation of the twisted main loop.
17
To install the event loop (and you should do this before any connections,
18
listeners or connectors are added):
20
from twisted.internet import win32
26
from win32file import WSAEventSelect, FD_READ, FD_WRITE, FD_CLOSE, \
28
from win32event import CreateEvent, WaitForMultipleObjects, \
29
WAIT_OBJECT_0, WAIT_TIMEOUT, INFINITE
35
from twisted.python import log, threadable
43
def _makeSocketEvent(fd, action, why, events=events):
44
"""Make a win32 event object for a socket."""
45
event = CreateEvent(None, 0, 0, None)
46
WSAEventSelect(fd, event, why)
47
events[event] = (fd, action)
50
def addEvent(event, fd, action, events=events):
51
"""Add a new win32 event to the event loop."""
52
events[event] = (fd, action)
54
def removeEvent(event):
55
"""Remove an event."""
58
def addReader(reader, reads=reads):
59
"""Add a socket FileDescriptor for notification of data available to read.
61
if not reads.has_key(reader):
62
reads[reader] = _makeSocketEvent(reader, reader.doRead, FD_READ|FD_ACCEPT|FD_CONNECT|FD_CLOSE)
64
def addWriter(writer, writes=writes):
65
"""Add a socket FileDescriptor for notification of data available to write.
67
if not writes.has_key(writer):
68
writes[writer] =_makeSocketEvent(writer, writer.doWrite, FD_WRITE|FD_CLOSE)
70
def removeReader(reader):
71
"""Remove a Selectable for notification of data available to read.
73
if reads.has_key(reader):
74
del events[reads[reader]]
77
def removeWriter(writer, writes=writes):
78
"""Remove a Selectable for notification of data available to write.
80
if writes.has_key(writer):
81
del events[writes[writer]]
85
"""Remove all selectables, and return a list of them."""
86
result = reads.keys() + writes.keys()
92
def doWaitForMultipleEvents(timeout,
99
timeout = timeout * 1000
101
handles = events.keys()
103
# sleep so we don't suck up CPU time
104
time.sleep(timeout / 1000.0)
106
val = WaitForMultipleObjects(handles, 0, timeout)
107
if val == WAIT_TIMEOUT:
109
elif val >= WAIT_OBJECT_0 and val < WAIT_OBJECT_0 + len(handles):
110
fd, action = events[handles[val - WAIT_OBJECT_0]]
127
log.logOwner.disown(fd)
131
"""Install the win32 event loop."""
133
main.addReader = addReader
134
main.addWriter = addWriter
135
main.removeReader = removeReader
136
main.removeWriter = removeWriter
137
main.doSelect = doWaitForMultipleEvents
138
main.removeAll = removeAll
142
"""Do initialization for threads."""
144
if main.wakerInstalled:
145
# make sure waker is registered with us
146
removeReader(main.waker)
147
addReader(main.waker)
149
threadable.whenThreaded(initThreads)
152
__all__ = ["install"]