ssize_t wait_and_fire_events()

in io/iouring-wrapper.cpp [376:435]


    ssize_t wait_and_fire_events(uint64_t timeout) override {
        // Prepare own timeout
        if (timeout > (uint64_t) std::numeric_limits<int64_t>::max()) {
            timeout = std::numeric_limits<int64_t>::max();
        }

        auto ts = usec_to_timespec(timeout);
        if (m_submit_wait_func(m_ring, &ts) != 0) {
            return -1;
        }

        uint32_t head = 0;
        unsigned i = 0;
        io_uring_cqe* cqe;
        io_uring_for_each_cqe(m_ring, head, cqe) {
            i++;
            auto ctx = (ioCtx*) io_uring_cqe_get_data(cqe);
            if (!ctx) {
                // Own timeout doesn't have user data
                continue;
            }

            if (ctx == (ioCtx*) this) {
                // Triggered by cancel_wait
                eventfd_t val;
                eventfd_read(m_eventfd, &val);
                continue;
            }

            if (cqe->flags & IORING_CQE_F_NOTIF) {
                // The cqe for notify, corresponding to IORING_CQE_F_MORE
                if (unlikely(cqe->res != 0))
                    LOG_WARN("iouring: send_zc fall back to copying");
                photon::thread_interrupt(ctx->th_id, EOK);
                continue;
            }

            ctx->res = cqe->res;
            if (!ctx->is_canceller && ctx->res == -ECANCELED) {
                // An I/O was canceled because of:
                // 1. IORING_OP_LINK_TIMEOUT. Leave the interrupt job to the linked timer later.
                // 2. IORING_OP_POLL_REMOVE. The I/O is actually a polling.
                // 3. IORING_OP_ASYNC_CANCEL. This OP is the superset of case 2.
                ctx->res = -ETIMEDOUT;
                continue;
            } else if (ctx->is_canceller && ctx->res == -ECANCELED) {
                // The linked timer itself is also a canceller. The reasons it got cancelled could be:
                // 1. I/O finished in time
                // 2. I/O was cancelled by IORING_OP_ASYNC_CANCEL
                continue;
            } else if (cqe->flags & IORING_CQE_F_MORE) {
                continue;
            }

            photon::thread_interrupt(ctx->th_id, EOK);
        }

        io_uring_cq_advance(m_ring, i);
        return 0;
    }