Repository: netty/netty
File: transport-classes-io_uring/src/main/java/io/netty/channel/uring/CompletionQueue.java (Java)

Code before:
    }

    /**
     * Process the completion events in the {@link CompletionQueue} and return the number of processed
     * events.
     */
    int process(CompletionCallback callback) {
        int tail = PlatformDependent.getIntVolatile(kTailAddress);
        int i = 0;
        boolean isTraceEnabled = logger.isTraceEnabled();
        while (ringHead != tail) {
            long cqeAddress = completionQueueArrayAddress + (ringHead & ringMask) * CQE_SIZE;

            long udata = PlatformDependent.getLong(cqeAddress + CQE_USER_DATA_FIELD);
            int res = PlatformDependent.getInt(cqeAddress + CQE_RES_FIELD);
            int flags = PlatformDependent.getInt(cqeAddress + CQE_FLAGS_FIELD);

            //Ensure that the kernel only sees the new value of the head index after the CQEs have been read.
            ringHead++;
            PlatformDependent.putIntOrdered(kHeadAddress, ringHead);

            i++;

            if (isTraceEnabled) {
                logger.trace("completed(ring {}: (res={}, flags={}, udata={})",
                        ringFd, res, flags, udata);
            }
            try {
                callback.handle(res, flags, udata);
            } catch (Error e) {
                throw e;
            } catch (Throwable throwable) {
                handleLoopException(throwable);
            }
        }
        return i;
    }

    private static void handleLoopException(Throwable throwable) {
        logger.warn("Unexpected exception in the IO event loop.", throwable);

        // Prevent possible consecutive immediate failures that lead to
        // excessive CPU consumption.
        try {
            Thread.sleep(100);
        } catch (InterruptedException ignore) {
        }
    }

    @Override
    public String toString() {

Review comment (suggestion):
This makes the tracing much less useful, because you can't immediately see what the operation is.
I think it's important that trace logging completions is as symmetric as possible with the corresponding trace logging of submissions, which isn't being changed in this PR.

We could instead create `traceLogSubmit` and `traceLogComplete` methods on `UserData` (or a separate class entirely) and move the logic there? Then the code for creating these messages would also be collected in one place.

Code after:
     */
    int process(CompletionCallback callback) {
        int tail = PlatformDependent.getIntVolatile(kTailAddress);
        int i = 0;
        while (ringHead != tail) {
            long cqeAddress = completionQueueArrayAddress + (ringHead & ringMask) * CQE_SIZE;

            long udata = PlatformDependent.getLong(cqeAddress + CQE_USER_DATA_FIELD);
            int res = PlatformDependent.getInt(cqeAddress + CQE_RES_FIELD);
            int flags = PlatformDependent.getInt(cqeAddress + CQE_FLAGS_FIELD);

            //Ensure that the kernel only sees the new value of the head index after the CQEs have been read.
            ringHead++;
            PlatformDependent.putIntOrdered(kHeadAddress, ringHead);

            i++;

            try {
                callback.handle(res, flags, udata);
            } catch (Error e) {
                throw e;
            } catch (Throwable throwable) {
                handleLoopException(throwable);
            }
        }
        return i;
    }

    private static void handleLoopException(Throwable throwable) {
        logger.warn("Unexpected exception in the IO event loop.", throwable);

        // Prevent possible consecutive immediate failures that lead to
        // excessive CPU consumption.
        try {
            Thread.sleep(100);
        } catch (InterruptedException ignore) {
        }
    }

    @Override
    public String toString() {
        StringJoiner sb = new StringJoiner(", ", "CompletionQueue [", "]");
        int tail = PlatformDependent.getIntVolatile(kTailAddress);
        int head = ringHead;
        while (head != tail) {
            long cqeAddress = completionQueueArrayAddress + (ringHead & ringMask) * CQE_SIZE;
            long udata = PlatformDependent.getLong(cqeAddress + CQE_USER_DATA_FIELD);
            int res = PlatformDependent.getInt(cqeAddress + CQE_RES_FIELD);
            int flags = PlatformDependent.getInt(cqeAddress + CQE_FLAGS_FIELD);

            sb.add("(res=" + res).add(", flags=" + flags).add(", udata=" + udata).add(")");