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):
40 r = self.eApp.poll(timeout, self.dict)
41 except KeyboardInterrupt:
45 poller = E2SharedPoll()
47 class PollReactor(posixbase.PosixReactorBase):
48 """A reactor that uses poll(2)."""
50 def _updateRegistration(self, fd):
51 """Register/unregister an fd with the poller."""
58 if reads.has_key(fd): mask = mask | select.POLLIN
59 if writes.has_key(fd): mask = mask | select.POLLOUT
61 poller.register(fd, mask)
63 if selectables.has_key(fd): del selectables[fd]
66 poller.eApp.interruptPoll()
68 def _dictRemove(self, selectable, mdict):
71 fd = selectable.fileno()
72 # make sure the fd is actually real. In some situations we can get
76 # the hard way: necessary because fileno() may disappear at any
77 # moment, thanks to python's underlying sockets impl
78 for fd, fdes in selectables.items():
79 if selectable is fdes:
82 # Hmm, maybe not the right course of action? This method can't
83 # fail, because it happens inside error detection...
87 self._updateRegistration(fd)
89 def addReader(self, reader):
90 """Add a FileDescriptor for notification of data available to read.
93 if not reads.has_key(fd):
94 selectables[fd] = reader
96 self._updateRegistration(fd)
98 def addWriter(self, writer, writes=writes, selectables=selectables):
99 """Add a FileDescriptor for notification of data available to write.
102 if not writes.has_key(fd):
103 selectables[fd] = writer
105 self._updateRegistration(fd)
107 def removeReader(self, reader, reads=reads):
108 """Remove a Selectable for notification of data available to read.
110 return self._dictRemove(reader, reads)
112 def removeWriter(self, writer, writes=writes):
113 """Remove a Selectable for notification of data available to write.
115 return self._dictRemove(writer, writes)
117 def removeAll(self, reads=reads, writes=writes, selectables=selectables):
118 """Remove all selectables, and return a list of them."""
119 if self.waker is not None:
120 self.removeReader(self.waker)
121 result = selectables.values()
122 fds = selectables.keys()
127 poller.unregister(fd)
129 if self.waker is not None:
130 self.addReader(self.waker)
133 def doPoll(self, timeout,
136 selectables=selectables,
139 POLLIN=select.POLLIN,
140 POLLOUT=select.POLLOUT):
141 """Poll the poller for new events."""
143 if timeout is not None:
144 timeout = int(timeout * 1000) # convert seconds to milliseconds
147 l = poller.poll(timeout)
152 except select.error, e:
153 if e[0] == errno.EINTR:
157 _drdw = self._doReadOrWrite
160 selectable = selectables[fd]
162 # Handles the infrequent case where one selectable's
163 # handler disconnects another.
165 log.callWithLogger(selectable, _drdw, selectable, fd, event, POLLIN, POLLOUT, log)
169 def _doReadOrWrite(self, selectable, fd, event, POLLIN, POLLOUT, log,
171 error.ConnectionDone: failure.Failure(error.ConnectionDone()),
172 error.ConnectionLost: failure.Failure(error.ConnectionLost())
176 if event & POLL_DISCONNECTED and not (event & POLLIN):
177 why = main.CONNECTION_LOST
181 why = selectable.doRead()
183 if not why and event & POLLOUT:
184 why = selectable.doWrite()
186 if not selectable.fileno() == fd:
187 why = error.ConnectionFdescWentAway('Filedescriptor went away')
191 why = sys.exc_info()[1]
193 self._disconnectSelectable(selectable, why, inRead)
195 def callLater(self, *args, **kwargs):
196 poller.eApp.interruptPoll()
197 return posixbase.PosixReactorBase.callLater(self, *args, **kwargs)
200 """Install the poll() reactor."""
203 main.installReactor(p)
205 __all__ = ["PollReactor", "install"]