New network subsystem updates

- auto-select select/poll/epoll/kqueue depending on what's available
This commit is contained in:
Peter Šurda 2017-03-10 23:56:38 +01:00
parent 998935be5f
commit a1d1114cb2
Signed by: PeterSurda
GPG Key ID: 0C5F50C0B5F37D87
2 changed files with 37 additions and 10 deletions

View File

@ -172,7 +172,10 @@ def poll_poller(timeout=0.0, map=None):
if timeout is not None:
# timeout is in milliseconds
timeout = int(timeout*1000)
pollster = select.poll()
try:
poll_poller.pollster
except AttributeError:
poll_poller.pollster = select.poll()
if map:
for fd, obj in list(map.items()):
flags = 0
@ -182,9 +185,12 @@ def poll_poller(timeout=0.0, map=None):
if obj.writable() and not obj.accepting:
flags |= select.POLLOUT
if flags:
pollster.register(fd, flags)
try:
r = pollster.poll(timeout)
poll_poller.pollster.modify(fd, flags)
except IOError:
poll_poller.pollster.register(fd, flags)
try:
r = poll_poller.pollster.poll(timeout)
except KeyboardInterrupt:
r = []
for fd, flags in r:
@ -201,7 +207,10 @@ def epoll_poller(timeout=0.0, map=None):
"""A poller which uses epoll(), supported on Linux 2.5.44 and newer."""
if map is None:
map = socket_map
pollster = select.epoll()
try:
epoll_poller.pollster
except AttributeError:
epoll_poller.pollster = select.epoll()
if map:
for fd, obj in map.items():
flags = 0
@ -213,9 +222,12 @@ def epoll_poller(timeout=0.0, map=None):
# Only check for exceptions if object was either readable
# or writable.
flags |= select.POLLERR | select.POLLHUP | select.POLLNVAL
pollster.register(fd, flags)
try:
r = pollster.poll(timeout)
epoll_poller.pollster.register(fd, flags)
except IOError:
epoll_poller.pollster.modify(fd, flags)
try:
r = epoll_poller.pollster.poll(timeout)
except select.error, err:
if err.args[0] != EINTR:
raise
@ -265,9 +277,14 @@ def loop(timeout=30.0, use_poll=False, map=None, count=None,
# code which grants backward compatibility with "use_poll"
# argument which should no longer be used in favor of
# "poller"
if use_poll and hasattr(select, 'poll'):
if hasattr(select, 'epoll'):
poller = epoll_poller
elif hasattr(select, 'kqueue'):
poller = kqueue_poller
elif hasattr(select, 'poll'):
poller = poll_poller
else:
elif hasattr(select, 'select'):
poller = select_poller
if count is None:
@ -349,6 +366,16 @@ class dispatcher:
#self.log_info('closing channel %d:%s' % (fd, self))
del map[fd]
self._fileno = None
try:
epoll_poller.pollster.unregister(fd)
except (AttributeError, KeyError):
# no epoll used, or not registered
pass
try:
poll_poller.pollster.unregister(fd)
except (AttributeError, KeyError):
# no poll used, or not registered
pass
def create_socket(self, family=socket.AF_INET, type=socket.SOCK_STREAM):
self.family_and_type = family, type

View File

@ -20,13 +20,13 @@ class HttpConnection(AdvancedDispatcher):
def state_init(self):
self.write_buf += "GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n" % (self.path, self.destination[0])
print "\"%s\"" % (self.write_buf)
print "Sending %ib" % (len(self.write_buf))
self.set_state("http_request_sent", 0)
return False
def state_http_request_sent(self):
if len(self.read_buf) > 0:
print self.read_buf
print "Received %ib" % (len(self.read_buf))
self.read_buf = b""
if not self.connected:
self.set_state("close", 0)