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

Code before:
        this.batchSize = batchSize;
        this.maxUnreleasedBuffers = maxUnreleasedBuffers;
        this.mask = (short) (entries - 1);
        this.bufferGroupId = bufferGroupId;
        this.ringFd = ringFd;
        this.buffers = new IoUringBufferRingByteBuf[entries];
        this.incremental = incremental;
        this.allocator = allocator;
        this.exhaustedEvent = new IoUringBufferRingExhaustedEvent(bufferGroupId);
    }

    boolean isUsable() {
        return !corrupted && usable;
    }

    void initialize() {
        fillBuffers();
        usable = true;
    }

    /**
     * Try to expand by adding more buffers to the ring if there is any space left.
     * This method might be called multiple times before we call {@link #fillBuffer()} again.
     */
    void expand() {
        // TODO: We could also shrink the number of elements again if we find out we not use all of it frequently.
        if (!expanded) {
            // Only expand once before we reset expanded in fillBuffer() which is called once a buffer was completely
            // used and moved out of the buffer ring.
            fillBuffers();
            expanded = true;
        }
    }

    private void fillBuffers() {
        int num = Math.min(batchSize, entries - numBuffers);
        for (short i = 0; i < num; i++) {
            fillBuffer();
        }
    }

    /**
     * @return the {@link IoUringBufferRingExhaustedEvent} that should be used to signal that there were no buffers
     * left for this buffer ring.
     */
    IoUringBufferRingExhaustedEvent getExhaustedEvent() {
        return exhaustedEvent;
    }

    void fillBuffer() {
        if (corrupted || closed) {

Review comment (performance):
This assert should be covered by the `assert batchSize % 2 == 0;` in the constructor.

Code after:
        assert batchSize % 2 == 0;
        this.ioUringBufRing = ioUringBufRing;
        this.tailFieldPosition = Native.IO_URING_BUFFER_RING_TAIL;
        this.entries = entries;
        this.batchSize = batchSize;
        this.maxUnreleasedBuffers = maxUnreleasedBuffers;
        this.mask = (short) (entries - 1);
        this.bufferGroupId = bufferGroupId;
        this.ringFd = ringFd;
        this.buffers = new IoUringBufferRingByteBuf[entries];
        this.incremental = incremental;
        this.allocator = allocator;
        this.exhaustedEvent = new IoUringBufferRingExhaustedEvent(bufferGroupId);
    }

    boolean isUsable() {
        return !corrupted && usable;
    }

    void initialize() {
        for (short i = 0; i < batchSize; i++) {
            addBuffer(i);
            numBuffers++;
            lastGeneratedBid = i;
        }
        assert numBuffers % 2 == 0;
        usable = true;
    }

    /**
     * Try to expand by adding more buffers to the ring if there is any space left.
     * This method might be called multiple times before we call {@link #useBuffer(short, int, boolean)} again.
     */
    void expand() {
        if (!expanded) {
            // Only expand once before we reset expanded in addBuffer() which is called once a buffer was completely
            // used and moved out of the buffer ring.
            tryExpand();
        }
    }

    private void tryExpand() {
        // We only expand if the last added BID is the last generated BID. The reason for this is as we want to
        // ensure we have a sequential ordering of BIDs as this is required for our nextBid(...) to work correctly when
        // RECVSEND_BUNDLE is used.
        if (lastAddedBid == lastGeneratedBid) {
            needsLazyExpansion = false;
            // TODO: We could also shrink the number of elements again if we find out we not use all of it frequently.
            int num = Math.min(batchSize, entries - numBuffers);
            assert num % 2 == 0;
            for (short i = 0; i < num; i++) {