Esempio n. 1
0
def run_until_complete(task):
    tasks = [(task, None)]

    selector = DefaultSelector()

    while tasks or selector.get_map():

        timeout = 0 if tasks else None
        if selector.get_map():
            for key, events in selector.select(timeout):
                tasks.append((key.data, None))
                selector.unregister(key.fileobj)

        queue, tasks = tasks, []
        for task, data in queue:
            try:
                data = task.send(data)
            except StopIteration:
                pass
            else:
                if data and data[0] == EVENT_READ:
                    selector.register(data[1], EVENT_READ, task)
                elif data and data[0] == EVENT_WRITE:
                    selector.register(data[1], EVENT_WRITE, task)
                elif data and data[0] == 'spawn':
                    tasks.append((data[1], None))
                    tasks.append((task, data[1]))
                else:
                    tasks.append((task, None))
Esempio n. 2
0
def run_until_complete(task):
    tasks = [(task, None)]

    # NEW: prepare for I/O multiplexing.
    selector = DefaultSelector()

    # NEW: watch out, all tasks might be suspended at the same time.
    while tasks or selector.get_map():

        # NEW: poll I/O operation status and resume tasks when ready.
        timeout = 0.0 if tasks else None
        for key, events in selector.select(timeout):
            tasks.append((key.data, None))
            selector.unregister(key.fileobj)

        queue, tasks = tasks, []
        for task, data in queue:
            try:
                data = task.send(data)
            except StopIteration:
                pass
            else:
                # NEW: register for I/O and suspend the task.
                if data and data[0] == EVENT_READ:
                    selector.register(data[1], EVENT_READ, task)
                elif data and data[0] == EVENT_WRITE:
                    selector.register(data[1], EVENT_WRITE, task)
                else:
                    tasks.append((task, None))
Esempio n. 3
0
def run_until_complete(task):
    tasks = [(task, None)]

    selector = DefaultSelector()

    while tasks or selector.get_map():
        print("___________________________________")

        # poll I/O and resume when ready
        timeout = 0.0 if tasks else None
        for key, events in selector.select(timeout):
            tasks.append((key.data, None))
            selector.unregister(key.fileobj)

        queue, tasks = tasks, []
        for task, data in queue:
            try:
                print(f"loop: send {data} into {task.__name__}")
                data = task.send(data)
                print(f"loop: received {data} from {task.__name__}")
            except StopIteration as res:
                pass
            except Exception as exp:
                print(repr(exp))
            else:
                if data:
                    req, _ = data
                    if req == EVENT_READ:
                        stream = data[1]
                        selector.register(stream, EVENT_READ, task)
                    elif req == EVENT_WRITE:
                        stream = data[1]
                        selector.register(data[1], EVENT_WRITE, task)
                else:
                    tasks.append((task, None))
Esempio n. 4
0
class TestBase(object):
    AF: int = AF_INET

    aa: Type[SocketReader] = SocketReader
    dd: Type[SocketReader] = SocketReader
    E: BaseSelector
    a: SocketReader
    b: EndPoint
    c: EndPoint
    d: SocketReader
    acceptor: socket
    listener: FlowAcceptor

    @classmethod
    def config(self, ahost: str, aport: int):
        return {'flow': {ahost + ':0': ahost + ':' + str(aport)}}

    def setup_method(self) -> None:
        self.acceptor = socket(self.AF, SOCK_STREAM)
        self.acceptor.bind(('localhost', 0))
        self.acceptor.listen(1)
        ahost, aport = self.acceptor.getsockname()[:2]
        self.E = DefaultSelector()
        load_config(self.E, self.config(ahost, aport))
        # There should be a single item in the map...
        (_, _, _, self.listener), = self.E.get_map().values()
        self.a = self.aa(self.AF, SOCK_STREAM)
        self.a.selector = self.E
        try:
            self.a.connect(self.listener.getsockname())
        except BlockingIOError:
            pass
        Dispatchable.dispatch(self.E, 1)
        for _, _, _, s in self.E.get_map().values():
            if s == self.listener:
                pass
            elif s.connected:
                self.b = s
            else:
                self.c = s
        assert hasattr(self, 'b')
        assert hasattr(self, 'c')
        serverfd, _ = self.acceptor._accept()  # type: ignore
        self.d = self.dd(fileno=serverfd)
        self.d.selector = self.E
        for X in self.a, self.b, self.c, self.d:
            X.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1)
        self.a.reregister()
        self.d.reregister()

    def teardown_method(self) -> None:
        for _, _, _, X in self.E.get_map().values():
            X.close()
        for X in self.a, self.d, self.E, self.acceptor, self.listener:
            X.close()

    def recv_wait(self, s: socket, n: int) -> bytes:
        for _ in range(100):
            assert Dispatchable.dispatch(self.E, 1)
            try:
                return s.recv(n)
            except BlockingIOError:
                pass
        assert False

    def raises(self, C):
        import pytest  # type: ignore
        return pytest.raises(C)
Esempio n. 5
0
class EventLoop:
    def __init__(self):
        self.tasks = deque()
        self.selector = DefaultSelector()

    def run_until_complete(self, task):
        self.tasks.append(task)
        self.run()

    def pause(self):
        return "pause", None

    def schedule(self, target):
        return "schedule", target

    def sock_accept(self, sock):
        yield ("read", sock)
        return sock.accept()

    def sock_recv(self, sock):
        yield ("read", sock)
        return sock.recv(1024)

    def sock_sendall(self, sock, data):
        yield ("write", sock)
        return sock.sendall(data)

    def start_server(self, handler, host, port, backlog=0):
        handler = partial(handler, self)
        with socket.socket() as sock:
            sock.bind((host, port))
            sock.listen(backlog)
            print("Listening on {}:{}".format(host, port))
            while True:
                conn, addr = yield from self.sock_accept(sock)
                print("Accepted client from", addr)
                yield self.schedule(handler(conn))

    def run(self):
        while self.tasks or self.selector.get_map():
            for _ in range(len(self.tasks)):
                try:
                    task = self.tasks.popleft()
                    tag, value = next(task)

                    if tag == "schedule":
                        self.tasks.append(value)
                        self.tasks.append(task)
                    elif tag == "read":
                        self.selector.register(value, EVENT_READ, data=task)
                    elif tag == "write":
                        self.selector.register(value, EVENT_WRITE, data=task)
                    elif tag == "pause":
                        self.tasks.append(task)
                    else:
                        raise ValueError("Incorrect tag")
                except StopIteration:
                    continue

            if self.selector.get_map():
                for key, event in self.selector.select():
                    if event & EVENT_READ or event & EVENT_WRITE:
                        self.tasks.append(key.data)
                    self.selector.unregister(key.fileobj)