add e2reactor
authorFelix Domke <tmbinc@elitedvb.net>
Sun, 19 Feb 2006 22:35:02 +0000 (22:35 +0000)
committerFelix Domke <tmbinc@elitedvb.net>
Sun, 19 Feb 2006 22:35:02 +0000 (22:35 +0000)
e2reactor.py [new file with mode: 0644]
mytest.py

diff --git a/e2reactor.py b/e2reactor.py
new file mode 100644 (file)
index 0000000..1ecd40e
--- /dev/null
@@ -0,0 +1,193 @@
+# enigma2 reactor: based on pollreactor, which is
+# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
+# See LICENSE for details.
+
+
+"""
+Maintainer: U{Felix Domke<mailto:tmbinc@elitedvb.net>}
+"""
+
+# System imports
+import select, errno, sys
+
+# Twisted imports
+from twisted.python import log, threadable, failure
+from twisted.internet import main, posixbase, error
+#from twisted.internet.pollreactor import PollReactor, poller
+
+from enigma import getApplication
+
+# globals
+reads = {}
+writes = {}
+selectables = {}
+
+POLL_DISCONNECTED = (select.POLLHUP | select.POLLERR | select.POLLNVAL)
+
+class E2SharedPoll:
+       def __init__(self):
+               self.dict = { }
+
+       def register(self, fd, eventmask = select.POLLIN | select.POLLERR | select.POLLOUT):
+               self.dict[fd] = eventmask
+       
+       def unregister(self, fd):
+               del self.dict[fd]
+       
+       def poll(self, timeout = None):
+               return getApplication().poll(timeout, self.dict)
+
+poller = E2SharedPoll()
+
+class PollReactor(posixbase.PosixReactorBase):
+       """A reactor that uses poll(2)."""
+
+       def _updateRegistration(self, fd):
+               """Register/unregister an fd with the poller."""
+               try:
+                       poller.unregister(fd)
+               except KeyError:
+                       pass
+
+               mask = 0
+               if reads.has_key(fd): mask = mask | select.POLLIN
+               if writes.has_key(fd): mask = mask | select.POLLOUT
+               if mask != 0:
+                       poller.register(fd, mask)
+               else:
+                       if selectables.has_key(fd): del selectables[fd]
+
+       def _dictRemove(self, selectable, mdict):
+               try:
+                       # the easy way
+                       fd = selectable.fileno()
+                       # make sure the fd is actually real.  In some situations we can get
+                       # -1 here.
+                       mdict[fd]
+               except:
+                       # the hard way: necessary because fileno() may disappear at any
+                       # moment, thanks to python's underlying sockets impl
+                       for fd, fdes in selectables.items():
+                               if selectable is fdes:
+                                       break
+                       else:
+                               # Hmm, maybe not the right course of action?  This method can't
+                               # fail, because it happens inside error detection...
+                               return
+               if mdict.has_key(fd):
+                       del mdict[fd]
+                       self._updateRegistration(fd)
+
+       def addReader(self, reader):
+               """Add a FileDescriptor for notification of data available to read.
+               """
+               fd = reader.fileno()
+               if not reads.has_key(fd):
+                       selectables[fd] = reader
+                       reads[fd] =  1
+                       self._updateRegistration(fd)
+
+       def addWriter(self, writer, writes=writes, selectables=selectables):
+               """Add a FileDescriptor for notification of data available to write.
+               """
+               fd = writer.fileno()
+               if not writes.has_key(fd):
+                       selectables[fd] = writer
+                       writes[fd] =  1
+                       self._updateRegistration(fd)
+
+       def removeReader(self, reader, reads=reads):
+               """Remove a Selectable for notification of data available to read.
+               """
+               return self._dictRemove(reader, reads)
+
+       def removeWriter(self, writer, writes=writes):
+               """Remove a Selectable for notification of data available to write.
+               """
+               return self._dictRemove(writer, writes)
+
+       def removeAll(self, reads=reads, writes=writes, selectables=selectables):
+               """Remove all selectables, and return a list of them."""
+               if self.waker is not None:
+                       self.removeReader(self.waker)
+               result = selectables.values()
+               fds = selectables.keys()
+               reads.clear()
+               writes.clear()
+               selectables.clear()
+               for fd in fds:
+                       poller.unregister(fd)
+                       
+               if self.waker is not None:
+                       self.addReader(self.waker)
+               return result
+
+       def doPoll(self, timeout,
+                          reads=reads,
+                          writes=writes,
+                          selectables=selectables,
+                          select=select,
+                          log=log,
+                          POLLIN=select.POLLIN,
+                          POLLOUT=select.POLLOUT):
+               """Poll the poller for new events."""
+               if timeout is not None:
+                       timeout = int(timeout * 1000) # convert seconds to milliseconds
+
+               try:
+                       l = poller.poll(timeout)
+                       if l is None:
+                               if self.running:
+                                       self.stop()
+                               l = [ ]
+               except select.error, e:
+                       if e[0] == errno.EINTR:
+                               return
+                       else:
+                               raise
+               _drdw = self._doReadOrWrite
+               for fd, event in l:
+                       try:
+                               selectable = selectables[fd]
+                       except KeyError:
+                               # Handles the infrequent case where one selectable's
+                               # handler disconnects another.
+                               continue
+                       log.callWithLogger(selectable, _drdw, selectable, fd, event, POLLIN, POLLOUT, log)
+
+       doIteration = doPoll
+
+       def _doReadOrWrite(self, selectable, fd, event, POLLIN, POLLOUT, log, 
+               faildict={
+                       error.ConnectionDone: failure.Failure(error.ConnectionDone()),
+                       error.ConnectionLost: failure.Failure(error.ConnectionLost())
+               }):
+               why = None
+               inRead = False
+               if event & POLL_DISCONNECTED and not (event & POLLIN):
+                       why = main.CONNECTION_LOST
+               else:
+                       try:
+                               if event & POLLIN:
+                                       why = selectable.doRead()
+                                       inRead = True
+                               if not why and event & POLLOUT:
+                                       why = selectable.doWrite()
+                                       inRead = False
+                               if not selectable.fileno() == fd:
+                                       why = error.ConnectionFdescWentAway('Filedescriptor went away')
+                                       inRead = False
+                       except:
+                               log.deferr()
+                               why = sys.exc_info()[1]
+               if why:
+                       self._disconnectSelectable(selectable, why, inRead)
+
+
+def install():
+       """Install the poll() reactor."""
+       
+       p = PollReactor()
+       main.installReactor(p)
+
+__all__ = ["PollReactor", "install"]
index 91cb9f9..8ae28ab 100644 (file)
--- a/mytest.py
+++ b/mytest.py
@@ -22,7 +22,7 @@ InitFallbackFiles()
 eDVBDB.getInstance().reloadBouquets()
 
 try:
-       from twisted.internet import e2reactor
+       import e2reactor
        e2reactor.install()
        
        from twisted.internet import reactor
@@ -30,6 +30,7 @@ try:
        def runReactor():
                reactor.run()
 except:
+       print "twisted not available"
        def runReactor():
                runMainloop()