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, threadable, 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)
31 def register(self, fd, eventmask = select.POLLIN | select.POLLERR | select.POLLOUT):
32 self.dict[fd] = eventmask
34 def unregister(self, fd):
37 def poll(self, timeout = None):
38 r = getApplication().poll(timeout, self.dict)
41 poller = E2SharedPoll()
43 class PollReactor(posixbase.PosixReactorBase):
44 """A reactor that uses poll(2)."""
46 def _updateRegistration(self, fd):
47 """Register/unregister an fd with the poller."""
54 if reads.has_key(fd): mask = mask | select.POLLIN
55 if writes.has_key(fd): mask = mask | select.POLLOUT
57 poller.register(fd, mask)
59 if selectables.has_key(fd): del selectables[fd]
61 getApplication().interruptPoll()
63 def _dictRemove(self, selectable, mdict):
66 fd = selectable.fileno()
67 # make sure the fd is actually real. In some situations we can get
71 # the hard way: necessary because fileno() may disappear at any
72 # moment, thanks to python's underlying sockets impl
73 for fd, fdes in selectables.items():
74 if selectable is fdes:
77 # Hmm, maybe not the right course of action? This method can't
78 # fail, because it happens inside error detection...
82 self._updateRegistration(fd)
84 def addReader(self, reader):
85 """Add a FileDescriptor for notification of data available to read.
88 if not reads.has_key(fd):
89 selectables[fd] = reader
91 self._updateRegistration(fd)
93 def addWriter(self, writer, writes=writes, selectables=selectables):
94 """Add a FileDescriptor for notification of data available to write.
97 if not writes.has_key(fd):
98 selectables[fd] = writer
100 self._updateRegistration(fd)
102 def removeReader(self, reader, reads=reads):
103 """Remove a Selectable for notification of data available to read.
105 return self._dictRemove(reader, reads)
107 def removeWriter(self, writer, writes=writes):
108 """Remove a Selectable for notification of data available to write.
110 return self._dictRemove(writer, writes)
112 def removeAll(self, reads=reads, writes=writes, selectables=selectables):
113 """Remove all selectables, and return a list of them."""
114 if self.waker is not None:
115 self.removeReader(self.waker)
116 result = selectables.values()
117 fds = selectables.keys()
122 poller.unregister(fd)
124 if self.waker is not None:
125 self.addReader(self.waker)
128 def doPoll(self, timeout,
131 selectables=selectables,
134 POLLIN=select.POLLIN,
135 POLLOUT=select.POLLOUT):
136 """Poll the poller for new events."""
138 if timeout is not None:
139 timeout = int(timeout * 1000) # convert seconds to milliseconds
142 l = poller.poll(timeout)
147 except select.error, e:
148 if e[0] == errno.EINTR:
152 _drdw = self._doReadOrWrite
155 selectable = selectables[fd]
157 # Handles the infrequent case where one selectable's
158 # handler disconnects another.
160 log.callWithLogger(selectable, _drdw, selectable, fd, event, POLLIN, POLLOUT, log)
164 def _doReadOrWrite(self, selectable, fd, event, POLLIN, POLLOUT, log,
166 error.ConnectionDone: failure.Failure(error.ConnectionDone()),
167 error.ConnectionLost: failure.Failure(error.ConnectionLost())
171 if event & POLL_DISCONNECTED and not (event & POLLIN):
172 why = main.CONNECTION_LOST
176 why = selectable.doRead()
178 if not why and event & POLLOUT:
179 why = selectable.doWrite()
181 if not selectable.fileno() == fd:
182 why = error.ConnectionFdescWentAway('Filedescriptor went away')
186 why = sys.exc_info()[1]
188 self._disconnectSelectable(selectable, why, inRead)
190 def callLater(self, *args, **kwargs):
191 getApplication().interruptPoll()
192 return posixbase.PosixReactorBase.callLater(self, *args, **kwargs)
195 """Install the poll() reactor."""
198 main.installReactor(p)
200 __all__ = ["PollReactor", "install"]