1 # enigma2 reactor: based on pollreactor, which is
2 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
3 # See LICENSE for details.
7 Maintainer: U{Felix Domke<mailto:tmbinc@elitedvb.net>}
11 import select, errno, sys
14 from twisted.python import log, failure
15 from twisted.internet import main, posixbase, error
16 #from twisted.internet.pollreactor import PollReactor, poller
18 from enigma import getApplication
25 POLL_DISCONNECTED = (select.POLLHUP | select.POLLERR | select.POLLNVAL)
30 self.eApp = getApplication()
32 def register(self, fd, eventmask = select.POLLIN | select.POLLERR | select.POLLOUT):
33 self.dict[fd] = eventmask
35 def unregister(self, fd):
38 def poll(self, timeout = None):
39 r = self.eApp.poll(timeout, self.dict)
42 poller = E2SharedPoll()
44 class PollReactor(posixbase.PosixReactorBase):
45 """A reactor that uses poll(2)."""
47 def _updateRegistration(self, fd):
48 """Register/unregister an fd with the poller."""
55 if reads.has_key(fd): mask = mask | select.POLLIN
56 if writes.has_key(fd): mask = mask | select.POLLOUT
58 poller.register(fd, mask)
60 if selectables.has_key(fd): del selectables[fd]
63 poller.eApp.interruptPoll()
65 def _dictRemove(self, selectable, mdict):
68 fd = selectable.fileno()
69 # make sure the fd is actually real. In some situations we can get
73 # the hard way: necessary because fileno() may disappear at any
74 # moment, thanks to python's underlying sockets impl
75 for fd, fdes in selectables.items():
76 if selectable is fdes:
79 # Hmm, maybe not the right course of action? This method can't
80 # fail, because it happens inside error detection...
84 self._updateRegistration(fd)
86 def addReader(self, reader):
87 """Add a FileDescriptor for notification of data available to read.
90 if not reads.has_key(fd):
91 selectables[fd] = reader
93 self._updateRegistration(fd)
95 def addWriter(self, writer, writes=writes, selectables=selectables):
96 """Add a FileDescriptor for notification of data available to write.
99 if not writes.has_key(fd):
100 selectables[fd] = writer
102 self._updateRegistration(fd)
104 def removeReader(self, reader, reads=reads):
105 """Remove a Selectable for notification of data available to read.
107 return self._dictRemove(reader, reads)
109 def removeWriter(self, writer, writes=writes):
110 """Remove a Selectable for notification of data available to write.
112 return self._dictRemove(writer, writes)
114 def removeAll(self, reads=reads, writes=writes, selectables=selectables):
115 """Remove all selectables, and return a list of them."""
116 if self.waker is not None:
117 self.removeReader(self.waker)
118 result = selectables.values()
119 fds = selectables.keys()
124 poller.unregister(fd)
126 if self.waker is not None:
127 self.addReader(self.waker)
130 def doPoll(self, timeout,
133 selectables=selectables,
136 POLLIN=select.POLLIN,
137 POLLOUT=select.POLLOUT):
138 """Poll the poller for new events."""
140 if timeout is not None:
141 timeout = int(timeout * 1000) # convert seconds to milliseconds
144 l = poller.poll(timeout)
149 except select.error, e:
150 if e[0] == errno.EINTR:
154 _drdw = self._doReadOrWrite
157 selectable = selectables[fd]
159 # Handles the infrequent case where one selectable's
160 # handler disconnects another.
162 log.callWithLogger(selectable, _drdw, selectable, fd, event, POLLIN, POLLOUT, log)
166 def _doReadOrWrite(self, selectable, fd, event, POLLIN, POLLOUT, log,
168 error.ConnectionDone: failure.Failure(error.ConnectionDone()),
169 error.ConnectionLost: failure.Failure(error.ConnectionLost())
173 if event & POLL_DISCONNECTED and not (event & POLLIN):
174 why = main.CONNECTION_LOST
178 why = selectable.doRead()
180 if not why and event & POLLOUT:
181 why = selectable.doWrite()
183 if not selectable.fileno() == fd:
184 why = error.ConnectionFdescWentAway('Filedescriptor went away')
188 why = sys.exc_info()[1]
190 self._disconnectSelectable(selectable, why, inRead)
192 def callLater(self, *args, **kwargs):
193 poller.eApp.interruptPoll()
194 return posixbase.PosixReactorBase.callLater(self, *args, **kwargs)
197 """Install the poll() reactor."""
200 main.installReactor(p)
202 __all__ = ["PollReactor", "install"]