// File: shaovie[P]reactor/src/poller.cpp
// Function: poller::run()
void poller::run() {
    this->thread_id = pthread_self();
    this->set_cpu_affinity();

    int nfds = 0, msec = -1;
    poll_desc *pd  = nullptr;
    ev_handler *eh = nullptr;
    struct epoll_event *ev_itor = nullptr;

    while (true) {
        nfds = ::epoll_wait(this->efd, this->ready_events, this->ready_events_size, msec);
        if (nfds > 0) {
            for (int i = 0; i < nfds; ++i) {
                ev_itor = this->ready_events + i;
                pd = (poll_desc*)(ev_itor->data.ptr);

                // EPOLLHUP refer to man 2 epoll_ctl
                if (ev_itor->events & (EPOLLHUP|EPOLLERR)) {
                    if (pd->eh != nullptr) {
                        eh = pd->eh;
                        this->remove(pd->fd, ev_handler::ev_all); // MUST before on_close
                        eh->on_close();
                    }
                    continue;
                }

                // MUST before EPOLLIN (e.g. connect)
                if (ev_itor->events & (EPOLLOUT)) {
                    if (pd->eh == nullptr)
                        continue ;
                    if (pd->eh->on_write() == false) {
                        eh = pd->eh;
                        this->remove(pd->fd, ev_handler::ev_all); // MUST before on_close
                        eh->on_close();
                        continue;
                    }
                }

                if (ev_itor->events & (EPOLLIN|EPOLLRDHUP)) {
                    if (pd->eh == nullptr)
                        continue ;
                    if (pd->eh->on_read() == false) {
                        eh = pd->eh;
                        this->remove(pd->fd, ev_handler::ev_all); // MUST before on_close
                        eh->on_close();
                        continue;
                    }
                }
            } // end of `for i < nfds'
        } else if (nfds == -1 && errno != EINTR) {
            fprintf(stderr, "reactor: epoll_wait exception! %s\n", strerror(errno));
            break; // exit
        }
    }

    ::close(this->efd); // Just release this resource and let epoll_ctl direct failure.
    this->efd = -1; // Thread unsafe
}

// Assembly:
subq $0x48, %rsp
movq %rdi, 0x40(%rsp)
movq 0x40(%rsp), %rax
movq %rax, 0x10(%rsp)
callq 0x14f30
movq 0x10(%rsp), %rdi
movq %rax, 0x40(%rdi)
callq 0x14b60
movl $0x0, 0x3c(%rsp)
movl $0xffffffff, 0x38(%rsp) # imm = 0xFFFFFFFF
movq $0x0, 0x30(%rsp)
movq $0x0, 0x28(%rsp)
movq $0x0, 0x20(%rsp)
movq 0x10(%rsp), %rax
movl 0x4(%rax), %edi
movq 0x18(%rax), %rsi
movl 0x8(%rax), %edx
movl 0x38(%rsp), %ecx
callq 0x147d0
movl %eax, 0x3c(%rsp)
cmpl $0x0, 0x3c(%rsp)
jle 0x18b70
movl $0x0, 0x1c(%rsp)
movl 0x1c(%rsp), %eax
cmpl 0x3c(%rsp), %eax
jge 0x18b6e
movq 0x10(%rsp), %rax
movq 0x18(%rax), %rax
movslq 0x1c(%rsp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movq %rax, 0x20(%rsp)
movq 0x20(%rsp), %rax
movq 0x4(%rax), %rax
movq %rax, 0x30(%rsp)
movq 0x20(%rsp), %rax
movl (%rax), %eax
andl $0x18, %eax
cmpl $0x0, %eax
je 0x18a85
movq 0x30(%rsp), %rax
cmpq $0x0, 0x10(%rax)
je 0x18a80
movq 0x10(%rsp), %rdi
movq 0x30(%rsp), %rax
movq 0x10(%rax), %rax
movq %rax, 0x28(%rsp)
movq 0x30(%rsp), %rax
movl (%rax), %esi
movl $0x2005, %edx           # imm = 0x2005
callq 0x15d50
movq 0x28(%rsp), %rdi
movq (%rdi), %rax
callq *0x38(%rax)
jmp 0x18b5e
movq 0x20(%rsp), %rax
movl (%rax), %eax
andl $0x4, %eax
cmpl $0x0, %eax
je 0x18af1
movq 0x30(%rsp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x18aa5
jmp 0x18b5e
movq 0x30(%rsp), %rax
movq 0x10(%rax), %rdi
movq (%rdi), %rax
callq *0x20(%rax)
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
jne 0x18aef
movq 0x10(%rsp), %rdi
movq 0x30(%rsp), %rax
movq 0x10(%rax), %rax
movq %rax, 0x28(%rsp)
movq 0x30(%rsp), %rax
movl (%rax), %esi
movl $0x2005, %edx           # imm = 0x2005
callq 0x15d50
movq 0x28(%rsp), %rdi
movq (%rdi), %rax
callq *0x38(%rax)
jmp 0x18b5e
jmp 0x18af1
movq 0x20(%rsp), %rax
movl (%rax), %eax
andl $0x2001, %eax           # imm = 0x2001
cmpl $0x0, %eax
je 0x18b5c
movq 0x30(%rsp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x18b10
jmp 0x18b5e
movq 0x30(%rsp), %rax
movq 0x10(%rax), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
jne 0x18b5a
movq 0x10(%rsp), %rdi
movq 0x30(%rsp), %rax
movq 0x10(%rax), %rax
movq %rax, 0x28(%rsp)
movq 0x30(%rsp), %rax
movl (%rax), %esi
movl $0x2005, %edx           # imm = 0x2005
callq 0x15d50
movq 0x28(%rsp), %rdi
movq (%rdi), %rax
callq *0x38(%rax)
jmp 0x18b5e
jmp 0x18b5c
jmp 0x18b5e
movl 0x1c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c(%rsp)
jmp 0x18a00
jmp 0x18bb6
cmpl $-0x1, 0x3c(%rsp)
jne 0x18bb4
callq 0x140c0
cmpl $0x4, (%rax)
je 0x18bb4
movq 0x11448(%rip), %rax     # 0x29fd0
movq (%rax), %rax
movq %rax, 0x8(%rsp)
callq 0x140c0
movl (%rax), %edi
callq 0x144d0
movq 0x8(%rsp), %rdi
movq %rax, %rdx
leaq 0xa5cc(%rip), %rsi      # 0x23177
movb $0x0, %al
callq 0x15860
jmp 0x18bbb
jmp 0x18bb6
jmp 0x189d1
movq 0x10(%rsp), %rax
movl 0x4(%rax), %edi
callq 0x16000
movq 0x10(%rsp), %rax
movl $0xffffffff, 0x4(%rax)  # imm = 0xFFFFFFFF
addq $0x48, %rsp
retq
nopl (%rax)