__author__ = 'mazheng'

import select
import socket
from threading import Thread


class IOLoop(Thread):

    def __init__(self):
        super(IOLoop, self).__init__()
        self.select = select.epoll()
        self.connections = {}
        self.websockets = {}

    @staticmethod
    def instance():
        if not hasattr(IOLoop, "_instance"):
            IOLoop._instance = IOLoop()
        return IOLoop._instance

    def register(self, fileno, connection, websocket):
        self.select.register(fileno, select.EPOLLIN)
        self.connections[fileno] = connection
        self.websockets[fileno] = websocket

    def run(self):
        while True:
            epoll_list = self.select.poll(1)
            for fd, events in epoll_list:
                print fd, events
                if select.EPOLLIN & events:
                    error = False
                    while True:
                        try:
                            data = self.connections[fd].recv(1024)
                        except socket.error:
                            error = True
                        if not data or error:
                            break
                        self.websockets[fd].write_message(data)
                elif select.EPOLLHUP & events:
                    self.close()
                else:
                    continue

    def close(self, fd):
        self.select.unregister(fd)
        self.connections[fd].close()
        self.websockets[fd].close()
        del self.connections[fd]
        del self.websockets[fd]

@@ -45,16 +45,29 @@
  socket%0A
+import errno%0A
 from thr
@@ -534,16 +534,33 @@
 .EPOLLIN
+ %7C select.EPOLLET
 )%0A      
@@ -725,17 +725,16 @@
 ct.poll(
-1
 )%0A      
@@ -773,41 +773,8 @@
 st:%0A
-                print fd, events%0A
     
@@ -817,42 +817,8 @@
 ts:%0A
-                    error = False%0A
     
@@ -980,24 +980,27 @@
 socket.error
+, e
 :%0A          
@@ -1021,100 +1021,289 @@
     
-error = True%0A                        if not data or error:%0A                            break
+if e.errno == errno.EAGAIN:%0A                                self.select.modify(fd, select.EPOLLET)%0A                            elif isinstance(e, socket.timeout):%0A                                break%0A                            else:%0A                                self.close(fd)
 %0A   
@@ -1402,32 +1402,32 @@
 LLHUP & events:%0A
-
                 
@@ -1437,24 +1437,26 @@
  self.close(
+fd
 )%0A          

use et mode