netty abstract byte buf reference counter

netty byte buf definition: http://donald-draper.iteye.com/blog/2393813
netty resource leak detector: http://donald-draper.iteye.com/blog/2393940
netty abstract byte buf parsing: http ://donald-draper.iteye.com/blog/2394078
Introduction
In the last article, we looked at the abstract byte buf. Let’s review it first:
There are two indexes inside the byte buf, one for reading, one for writing, and two for writing. An index mark, that is, the mark corresponding to the read and write index, the maximum capacity of buf is maxCapacity; the construction of buf is mainly to initialize the maximum capacity.

Discard the read data method discardReadBytes, when discarding the buf data, only the read-write index and the corresponding mark are modified, and the data is not deleted.

The get* primitive type method will not modify the current buf read/write index, and the getBytes(...,ByteBuf,...) method will not modify the current buf read/write index, but will modify the write index of the destination buf. The getBytes(...,byte[],...) method does not modify the current buf read/write index.

The set* primitive type method will not modify the current buf read/write index, and the setBytes(...,ByteBuf,...) method will not modify the current buf read/write index, but will modify the read index of the source buf. The setBytes(...,byte[],...) method does not modify the current buf read/write index.

The read* primitive type method will modify the current buf read index, the readBytes(...,ByteBuf,...) method will modify the current buf read index, and will also modify the write index of the destination buf, readBytes(...,byte[] ,...) method will modify the current buf read index. The read* operation actually delegates a get* related operation, and at the same time updates the buf read index.

Skip length bytes, only update the read index, do not delete the actual buf data.

The byte buf returned by the retainedSlice and slice methods is actually the underlying unwrap buf of the byte buf, which can be understood as a snapshot or reference of the byte buf. Data changes affect each other. The retainedSlice method will increase the reference counter of the byte buf.

The write* primitive type method will modify the current buf write index, the writeBytes(...,ByteBuf,...) method will modify the current buf write index, and will also modify the read index of the destination buf, readBytes(...,byte[] ,...) method will modify the current buf write index. The write* operation actually delegates a set* related operation, and at the same time updates the buf write index.

The byte buf returned by the retainedDuplicate and duplicate methods is actually the underlying unwrap buf of the byte buf, which can be understood as a snapshot or reference of the byte buf. Data changes affect each other. The retainedDuplicate method will increase the reference counter of the byte buf.


Today we look at the abstract reference byte buf AbstractReferenceCountedByteBuf:
package io.netty.buffer;

import io.netty.util.IllegalReferenceCountException;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import static io.netty.util.internal.ObjectUtil.checkPositive;

/**
 * Abstract base class for {@link ByteBuf} implementations that count references.
 */
public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf {
    //Reference counter atomic Updater
    private static final AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> refCntUpdater =
            AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");

    private volatile int refCnt = 1;//reference counter
    protected AbstractReferenceCountedByteBuf(int maxCapacity) {
        super(maxCapacity);
    }
    @Override
    public int refCnt() {
        return refCnt;
    }
    /**
     * An unsafe operation intended for use by a subclass that sets the reference count of the buffer directly
     */
    protected final void setRefCnt(int refCnt) {
        this.refCnt = refCnt;
    }
    //increment the reference counter
    @Override
    public ByteBuf retain() {
        return retain0(1);
    }

    @Override
    public ByteBuf retain(int increment) {
        return retain0(checkPositive(increment, "increment"));
    }

    private ByteBuf retain0(int increment) {
        for (;;) {
            int refCnt = this.refCnt;
            final int nextCnt = refCnt + increment;

            // Ensure we not resurrect (which means the refCnt was 0) and also that we encountered an overflow.
            if (nextCnt <= increment) {
                throw new IllegalReferenceCountException(refCnt, increment);
            }
	    // atomically update the reference counter
            if (refCntUpdater.compareAndSet(this, refCnt, nextCnt)) {
                break;
            }
        }
        return this;
    }
   //Record the current object operation to provide information about memory leaks
    @Override
    public ByteBuf touch() {
        return this;
    }

    @Override
    public ByteBuf touch(Object hint) {
        return this;
    }
    // release the object reference
    @Override
    public boolean release() {
        return release0(1);
    }

    @Override
    public boolean release(int decrement) {
        return release0(checkPositive(decrement, "decrement"));
    }

    private boolean release0(int decrement) {
        for (;;) {
            int refCnt = this.refCnt;
            if (refCnt < decrement) {
                throw new IllegalReferenceCountException(refCnt, -decrement);
            }
            // atomically update the reference counter
            if (refCntUpdater.compareAndSet(this, refCnt, refCnt - decrement)) {
                if (refCnt == decrement) {
		    // release resources
                    deallocate();
                    return true;
                }
                return false;
            }
        }
    }
    /**
     * Called once {@link #refCnt()} is equals 0.
     */
    protected abstract void deallocate();
}

As can be seen from the above, the abstract byte reference counter AbstractReferenceCountedByteBuf has a reference counter inside, and refCntUpdater (AbstractReferenceCountedByteBuf) that atomically updates the reference counter, updates the reference counter, and actually releases the object reference through the refCntUpdater CAS operation, if the reference counter is 0, the object-related resources are released.


Summary:
The abstract byte reference counter AbstractReferenceCountedByteBuf has a reference counter inside, and refCntUpdater (AbstractReferenceCountedByteBuf) that atomically updates the reference counter, updates the reference counter, actually through the refCntUpdater CAS operation, when releasing the object reference, if the reference counter is 0, it will be released Object-related resources.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326260669&siteId=291194637