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

Code before:
    private final ByteBufAllocator byteBufAllocator;
    private final IoUringBufferRingExhaustedEvent exhaustedEvent;
    private final boolean incremental;
    private boolean hasSpareBuffer;

    private short tail;
    private int numBuffers;

    IoUringBufferRing(int ringFd, long ioUringBufRingAddr,
                      short entries, short bufferGroupId,
                      int chunkSize, boolean incremental, IoUringIoHandler ioUringIoHandler,
                      ByteBufAllocator byteBufAllocator) {
        assert entries % 2 == 0;
        this.ioUringBufRingAddr = ioUringBufRingAddr;
        this.entries = entries;
        this.mask = (short) (entries - 1);
        this.bufferGroupId = bufferGroupId;
        this.ringFd = ringFd;
        this.buffers = new ByteBuf[entries];
        this.chunkSize = chunkSize;
        this.incremental = incremental;
        this.source = ioUringIoHandler;
        this.byteBufAllocator = byteBufAllocator;
        this.exhaustedEvent = new IoUringBufferRingExhaustedEvent(bufferGroupId);
    }

    void refillIfNecessary() {
        if (!hasSpareBuffer) {
            refill();
        }
    }

    /**
     * Mark this buffer ring as exhausted. This should be done if a read failed because there were no more buffers left
     * to use.
     */
    void markExhausted() {
        hasSpareBuffer = false;
        source.idHandler.notifyAllBuffersUsed(bufferGroupId);
    }

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

    private short idx(short idx) {
        return (short) (idx & mask);

Review comment (suggestion):
We can first add all buffer to the ring and then advance the tail. 
This way, the number of `putShortOrdered` operations can be reduced.

Code after:
    private boolean hasSpareBuffer;

    IoUringBufferRing(int ringFd, long ioUringBufRingAddr,
                      short entries, short bufferGroupId,
                      int chunkSize, boolean incremental, IoUringIoHandler ioUringIoHandler,
                      ByteBufAllocator byteBufAllocator) {
        assert entries % 2 == 0;
        this.ioUringBufRingAddr = ioUringBufRingAddr;
        this.entries = entries;
        this.mask = (short) (entries - 1);
        this.bufferGroupId = bufferGroupId;
        this.ringFd = ringFd;
        this.buffers = new ByteBuf[entries];
        this.chunkSize = chunkSize;
        this.incremental = incremental;
        this.source = ioUringIoHandler;
        this.byteBufAllocator = byteBufAllocator;
        this.exhaustedEvent = new IoUringBufferRingExhaustedEvent(bufferGroupId);
        fill();
    }

    private boolean fill() {
        boolean fillSomething = false;
        for (short i = 0; i < entries; i++) {
            if (buffers[i] == null) {
                addBuffer(i);
                fillSomething = true;
            }
        }
        return fillSomething;
    }

    boolean isExhausted() {
        return !hasSpareBuffer;
    }

    /**
     * Mark this buffer ring as exhausted. This should be done if a read failed because there were no more buffers left
     * to use.
     */
    void markExhausted() {
        hasSpareBuffer = false;
        source.idHandler.notifyAllBuffersUsed(bufferGroupId);
        if (fill()) {
            source.idHandler.notifyMoreBuffersReady(bufferGroupId);
        }
    }

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