io.netty.buffer.PooledByteBuf Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.buffer;
import io.netty.util.Recycler;
import io.netty.util.Recycler.Handle;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
abstract class PooledByteBuf extends AbstractReferenceCountedByteBuf {
private final Recycler.Handle> recyclerHandle;
protected PoolChunk chunk;
protected long handle;
protected T memory;
protected int offset;
protected int length;
int maxLength;
Thread initThread;
private ByteBuffer tmpNioBuf;
@SuppressWarnings("unchecked")
protected PooledByteBuf(Recycler.Handle extends PooledByteBuf> recyclerHandle, int maxCapacity) {
super(maxCapacity);
this.recyclerHandle = (Handle>) recyclerHandle;
}
void init(PoolChunk chunk, long handle, int offset, int length, int maxLength) {
assert handle >= 0;
assert chunk != null;
this.chunk = chunk;
this.handle = handle;
memory = chunk.memory;
this.offset = offset;
this.length = length;
this.maxLength = maxLength;
setIndex(0, 0);
tmpNioBuf = null;
initThread = Thread.currentThread();
}
void initUnpooled(PoolChunk chunk, int length) {
assert chunk != null;
this.chunk = chunk;
handle = 0;
memory = chunk.memory;
offset = 0;
this.length = maxLength = length;
setIndex(0, 0);
tmpNioBuf = null;
initThread = Thread.currentThread();
}
@Override
public final int capacity() {
return length;
}
@Override
public final ByteBuf capacity(int newCapacity) {
ensureAccessible();
// If the request capacity does not require reallocation, just update the length of the memory.
if (chunk.unpooled) {
if (newCapacity == length) {
return this;
}
} else {
if (newCapacity > length) {
if (newCapacity <= maxLength) {
length = newCapacity;
return this;
}
} else if (newCapacity < length) {
if (newCapacity > maxLength >>> 1) {
if (maxLength <= 512) {
if (newCapacity > maxLength - 16) {
length = newCapacity;
setIndex(Math.min(readerIndex(), newCapacity), Math.min(writerIndex(), newCapacity));
return this;
}
} else { // > 512 (i.e. >= 1024)
length = newCapacity;
setIndex(Math.min(readerIndex(), newCapacity), Math.min(writerIndex(), newCapacity));
return this;
}
}
} else {
return this;
}
}
// Reallocation required.
chunk.arena.reallocate(this, newCapacity, true);
return this;
}
@Override
public final ByteBufAllocator alloc() {
return chunk.arena.parent;
}
@Override
public final ByteOrder order() {
return ByteOrder.BIG_ENDIAN;
}
@Override
public final ByteBuf unwrap() {
return null;
}
protected final ByteBuffer internalNioBuffer() {
ByteBuffer tmpNioBuf = this.tmpNioBuf;
if (tmpNioBuf == null) {
this.tmpNioBuf = tmpNioBuf = newInternalNioBuffer(memory);
}
return tmpNioBuf;
}
protected abstract ByteBuffer newInternalNioBuffer(T memory);
@Override
protected final void deallocate() {
if (handle >= 0) {
final long handle = this.handle;
this.handle = -1;
memory = null;
boolean sameThread = initThread == Thread.currentThread();
initThread = null;
chunk.arena.free(chunk, handle, maxLength, sameThread);
recycle();
}
}
private void recycle() {
recyclerHandle.recycle(this);
}
protected final int idx(int index) {
return offset + index;
}
}