ByteBufAllocator API w/ ByteBuf perf improvements
This commit introduces a new API for ByteBuf allocation which fixes issue #643 along with refactoring of ByteBuf for simplicity and better performance. (see #62) A user can configure the ByteBufAllocator of a Channel via ChannelOption.ALLOCATOR or ChannelConfig.get/setAllocator(). The default allocator is currently UnpooledByteBufAllocator.HEAP_BY_DEFAULT. To allocate a buffer, do not use Unpooled anymore. do the following: ctx.alloc().buffer(...); // allocator chooses the buffer type. ctx.alloc().heapBuffer(...); ctx.alloc().directBuffer(...); To deallocate a buffer, use the unsafe free() operation: ((UnsafeByteBuf) buf).free(); The following is the list of the relevant changes: - Add ChannelInboundHandler.freeInboundBuffer() and ChannelOutboundHandler.freeOutboundBuffer() to let a user free the buffer he or she allocated. ChannelHandler adapter classes implement is already, so most users won't need to call free() by themselves. freeIn/OutboundBuffer() methods are invoked when a Channel is closed and deregistered. - All ByteBuf by contract must implement UnsafeByteBuf. To access an unsafe operation: ((UnsafeByteBuf) buf).internalNioBuffer() - Replace WrappedByteBuf and ByteBuf.Unsafe with UnsafeByteBuf to simplify overall class hierarchy and to avoid unnecesary instantiation of Unsafe instances on an unsafe operation. - Remove buffer reference counting which is confusing - Instantiate SwappedByteBuf lazily to avoid instantiation cost - Rename ChannelFutureFactory to ChannelPropertyAccess and move common methods between Channel and ChannelHandlerContext there. Also made it package-private to hide it from a user. - Remove unused unsafe operations such as newBuffer() - Add DetectionUtil.canFreeDirectBuffer() so that an allocator decides which buffer type to use safely
This commit is contained in:
parent
2adebc4c54
commit
81e2db10fa
@ -28,36 +28,24 @@ import java.nio.charset.Charset;
|
||||
/**
|
||||
* A skeletal implementation of a buffer.
|
||||
*/
|
||||
public abstract class AbstractByteBuf implements ByteBuf {
|
||||
|
||||
private final SwappedByteBuf swappedBuf;
|
||||
private final ByteOrder order;
|
||||
private final int maxCapacity;
|
||||
public abstract class AbstractByteBuf implements UnsafeByteBuf {
|
||||
|
||||
private int readerIndex;
|
||||
private int writerIndex;
|
||||
private int markedReaderIndex;
|
||||
private int markedWriterIndex;
|
||||
|
||||
int refCnt = 1;
|
||||
private final int maxCapacity;
|
||||
|
||||
protected AbstractByteBuf(ByteOrder endianness, int maxCapacity) {
|
||||
if (endianness == null) {
|
||||
throw new NullPointerException("endianness");
|
||||
}
|
||||
private SwappedByteBuf swappedBuf;
|
||||
|
||||
protected AbstractByteBuf(int maxCapacity) {
|
||||
if (maxCapacity < 0) {
|
||||
throw new IllegalArgumentException("maxCapacity: " + maxCapacity + " (expected: >= 0)");
|
||||
}
|
||||
order = endianness;
|
||||
swappedBuf = new SwappedByteBuf(this);
|
||||
this.maxCapacity = maxCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPooled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelBufType type() {
|
||||
return ChannelBufType.BYTE;
|
||||
@ -266,19 +254,19 @@ public abstract class AbstractByteBuf implements ByteBuf {
|
||||
return Math.min(newCapacity, maxCapacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ByteOrder order() {
|
||||
return order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf order(ByteOrder endianness) {
|
||||
if (endianness == null) {
|
||||
throw new NullPointerException("endianness");
|
||||
}
|
||||
if (endianness == order()) {
|
||||
if (endianness == order() || capacity() == 0) {
|
||||
return this;
|
||||
}
|
||||
|
||||
SwappedByteBuf swappedBuf = this.swappedBuf;
|
||||
if (swappedBuf == null) {
|
||||
this.swappedBuf = swappedBuf = new SwappedByteBuf(this);
|
||||
}
|
||||
return swappedBuf;
|
||||
}
|
||||
|
||||
@ -521,7 +509,9 @@ public abstract class AbstractByteBuf implements ByteBuf {
|
||||
if (length == 0) {
|
||||
return Unpooled.EMPTY_BUFFER;
|
||||
}
|
||||
ByteBuf buf = unsafe().newBuffer(length);
|
||||
|
||||
// Use an unpooled heap buffer because there's no way to mandate a user to free the returned buffer.
|
||||
ByteBuf buf = Unpooled.buffer(length, maxCapacity);
|
||||
buf.writeBytes(this, readerIndex, length);
|
||||
readerIndex += length;
|
||||
return buf;
|
||||
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public abstract class AbstractByteBufAllocator implements ByteBufAllocator {
|
||||
|
||||
private final boolean directByDefault;
|
||||
private final ByteBuf emptyBuf;
|
||||
|
||||
protected AbstractByteBufAllocator() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
protected AbstractByteBufAllocator(boolean directByDefault) {
|
||||
this.directByDefault = directByDefault;
|
||||
emptyBuf = new UnpooledHeapByteBuf(this, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf buffer() {
|
||||
if (directByDefault) {
|
||||
return directBuffer();
|
||||
}
|
||||
return heapBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf buffer(int initialCapacity) {
|
||||
if (directByDefault) {
|
||||
return directBuffer(initialCapacity);
|
||||
}
|
||||
return heapBuffer(initialCapacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf buffer(int initialCapacity, int maxCapacity) {
|
||||
if (directByDefault) {
|
||||
return directBuffer(initialCapacity, maxCapacity);
|
||||
}
|
||||
return heapBuffer(initialCapacity, maxCapacity);
|
||||
}
|
||||
|
||||
public ByteBuf heapBuffer() {
|
||||
return heapBuffer(256, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public ByteBuf heapBuffer(int initialCapacity) {
|
||||
return buffer(initialCapacity, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public ByteBuf heapBuffer(int initialCapacity, int maxCapacity) {
|
||||
if (initialCapacity == 0 && maxCapacity == 0) {
|
||||
return emptyBuf;
|
||||
}
|
||||
return newHeapBuffer(initialCapacity, maxCapacity);
|
||||
}
|
||||
|
||||
public ByteBuf directBuffer() {
|
||||
return directBuffer(256, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public ByteBuf directBuffer(int initialCapacity) {
|
||||
return directBuffer(initialCapacity, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public ByteBuf directBuffer(int initialCapacity, int maxCapacity) {
|
||||
if (initialCapacity == 0 && maxCapacity == 0) {
|
||||
return emptyBuf;
|
||||
}
|
||||
return newDirectBuffer(initialCapacity, maxCapacity);
|
||||
}
|
||||
|
||||
protected abstract ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity);
|
||||
protected abstract ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity);
|
||||
}
|
@ -1,263 +0,0 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
/**
|
||||
* Abstract base class for WrappedByteBuf implementations.
|
||||
*/
|
||||
public abstract class AbstractWrappedByteBuf extends AbstractByteBuf implements WrappedByteBuf {
|
||||
|
||||
protected AbstractWrappedByteBuf(ByteOrder endianness, int maxCapacity) {
|
||||
super(endianness, maxCapacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf capacity(int newCapacity) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf discardReadBytes() {
|
||||
return (WrappedByteBuf) super.discardReadBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf readerIndex(int readerIndex) {
|
||||
return (WrappedByteBuf) super.readerIndex(readerIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writerIndex(int writerIndex) {
|
||||
return (WrappedByteBuf) super.writerIndex(writerIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setIndex(int readerIndex, int writerIndex) {
|
||||
return (WrappedByteBuf) super.setIndex(readerIndex, writerIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf clear() {
|
||||
return (WrappedByteBuf) super.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf markReaderIndex() {
|
||||
return (WrappedByteBuf) super.markReaderIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf resetReaderIndex() {
|
||||
return (WrappedByteBuf) super.resetReaderIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf markWriterIndex() {
|
||||
return (WrappedByteBuf) super.markWriterIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf resetWriterIndex() {
|
||||
return (WrappedByteBuf) super.resetWriterIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf ensureWritableBytes(int minWritableBytes) {
|
||||
return (WrappedByteBuf) super.ensureWritableBytes(minWritableBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, ByteBuf dst) {
|
||||
return (WrappedByteBuf) super.getBytes(index, dst);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, ByteBuf dst, int length) {
|
||||
return (WrappedByteBuf) super.getBytes(index, dst, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, byte[] dst) {
|
||||
return (WrappedByteBuf) super.getBytes(index, dst);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBoolean(int index, boolean value) {
|
||||
return (WrappedByteBuf) super.setBoolean(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setChar(int index, int value) {
|
||||
return (WrappedByteBuf) super.setChar(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setFloat(int index, float value) {
|
||||
return (WrappedByteBuf) super.setFloat(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setDouble(int index, double value) {
|
||||
return (WrappedByteBuf) super.setDouble(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, ByteBuf src) {
|
||||
return (WrappedByteBuf) super.setBytes(index, src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, ByteBuf src, int length) {
|
||||
return (WrappedByteBuf) super.setBytes(index, src, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, byte[] src) {
|
||||
return (WrappedByteBuf) super.setBytes(index, src);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setZero(int index, int length) {
|
||||
return (WrappedByteBuf) super.setZero(index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf readBytes(ByteBuf dst) {
|
||||
return (WrappedByteBuf) super.readBytes(dst);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf readBytes(ByteBuf dst, int length) {
|
||||
return (WrappedByteBuf) super.readBytes(dst, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf readBytes(ByteBuf dst, int dstIndex, int length) {
|
||||
return (WrappedByteBuf) super.readBytes(dst, dstIndex, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf readBytes(byte[] dst) {
|
||||
return (WrappedByteBuf) super.readBytes(dst);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf readBytes(byte[] dst, int dstIndex, int length) {
|
||||
return (WrappedByteBuf) super.readBytes(dst, dstIndex, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf readBytes(ByteBuffer dst) {
|
||||
return (WrappedByteBuf) super.readBytes(dst);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf readBytes(OutputStream out, int length) throws IOException {
|
||||
return (WrappedByteBuf) super.readBytes(out, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf skipBytes(int length) {
|
||||
return (WrappedByteBuf) super.skipBytes(length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeBoolean(boolean value) {
|
||||
return (WrappedByteBuf) super.writeBoolean(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeByte(int value) {
|
||||
return (WrappedByteBuf) super.writeByte(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeShort(int value) {
|
||||
return (WrappedByteBuf) super.writeShort(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeMedium(int value) {
|
||||
return (WrappedByteBuf) super.writeMedium(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeInt(int value) {
|
||||
return (WrappedByteBuf) super.writeInt(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeLong(long value) {
|
||||
return (WrappedByteBuf) super.writeLong(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeChar(int value) {
|
||||
return (WrappedByteBuf) super.writeChar(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeFloat(float value) {
|
||||
return (WrappedByteBuf) super.writeFloat(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeDouble(double value) {
|
||||
return (WrappedByteBuf) super.writeDouble(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeBytes(ByteBuf src) {
|
||||
return (WrappedByteBuf) super.writeBytes(src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeBytes(ByteBuf src, int length) {
|
||||
return (WrappedByteBuf) super.writeBytes(src, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeBytes(ByteBuf src, int srcIndex, int length) {
|
||||
return (WrappedByteBuf) super.writeBytes(src, srcIndex, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeBytes(byte[] src) {
|
||||
return (WrappedByteBuf) super.writeBytes(src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeBytes(byte[] src, int srcIndex, int length) {
|
||||
return (WrappedByteBuf) super.writeBytes(src, srcIndex, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeBytes(ByteBuffer src) {
|
||||
return (WrappedByteBuf) super.writeBytes(src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeZero(int length) {
|
||||
return (WrappedByteBuf) super.writeZero(length);
|
||||
}
|
||||
|
||||
}
|
@ -251,6 +251,11 @@ public interface ByteBuf extends ChannelBuf, Comparable<ByteBuf> {
|
||||
*/
|
||||
int maxCapacity();
|
||||
|
||||
/**
|
||||
* Returns the {@link ByteBufAllocator} which created this buffer.
|
||||
*/
|
||||
ByteBufAllocator alloc();
|
||||
|
||||
/**
|
||||
* Returns the <a href="http://en.wikipedia.org/wiki/Endianness">endianness</a>
|
||||
* of this buffer.
|
||||
@ -1831,53 +1836,4 @@ public interface ByteBuf extends ChannelBuf, Comparable<ByteBuf> {
|
||||
*/
|
||||
@Override
|
||||
String toString();
|
||||
|
||||
/**
|
||||
* Returns an object that exposes unsafe expert-only operations which can lead to unspecified
|
||||
* behavior.
|
||||
*/
|
||||
Unsafe unsafe();
|
||||
|
||||
interface Unsafe {
|
||||
/**
|
||||
* Returns the internal NIO buffer that is reused for I/O.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the buffer has no internal NIO buffer
|
||||
*/
|
||||
ByteBuffer nioBuffer();
|
||||
|
||||
/**
|
||||
* Returns the internal NIO buffer array that is reused for I/O.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the buffer has no internal NIO buffer array
|
||||
*/
|
||||
ByteBuffer[] nioBuffers();
|
||||
|
||||
/**
|
||||
* Returns a new buffer whose type is identical to the callee.
|
||||
*
|
||||
* @param initialCapacity the initial capacity of the new buffer
|
||||
*/
|
||||
ByteBuf newBuffer(int initialCapacity);
|
||||
|
||||
/**
|
||||
* Similar to {@link ByteBuf#discardReadBytes()} except that this method might discard
|
||||
* some, all, or none of read bytes depending on its internal implementation to reduce
|
||||
* overall memory bandwidth consumption at the cost of potentially additional memory
|
||||
* consumption.
|
||||
*/
|
||||
void discardSomeReadBytes();
|
||||
|
||||
/**
|
||||
* Increases the reference count of the buffer.
|
||||
*/
|
||||
void acquire();
|
||||
|
||||
/**
|
||||
* Decreases the reference count of the buffer. If decreased to 0, the internal memory
|
||||
* block of the buffer will be deallocated. The result of accessing a freed buffer is
|
||||
* unspecified and can even cause JVM crash.
|
||||
*/
|
||||
void release();
|
||||
}
|
||||
}
|
||||
|
37
buffer/src/main/java/io/netty/buffer/ByteBufAllocator.java
Normal file
37
buffer/src/main/java/io/netty/buffer/ByteBufAllocator.java
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 java.util.concurrent.TimeUnit;
|
||||
|
||||
public interface ByteBufAllocator {
|
||||
|
||||
ByteBuf buffer();
|
||||
ByteBuf buffer(int initialCapacity);
|
||||
ByteBuf buffer(int initialCapacity, int maxCapacity);
|
||||
ByteBuf heapBuffer();
|
||||
ByteBuf heapBuffer(int initialCapacity);
|
||||
ByteBuf heapBuffer(int initialCapacity, int maxCapacity);
|
||||
ByteBuf directBuffer();
|
||||
ByteBuf directBuffer(int initialCapacity);
|
||||
ByteBuf directBuffer(int initialCapacity, int maxCapacity);
|
||||
ByteBuf ioBuffer();
|
||||
|
||||
void shutdown();
|
||||
boolean isShutdown();
|
||||
boolean isTerminated();
|
||||
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
|
||||
}
|
@ -20,10 +20,4 @@ public interface ChannelBuf {
|
||||
* The ChannelBufType which will be handled by the ChannelBuf implementation
|
||||
*/
|
||||
ChannelBufType type();
|
||||
|
||||
/**
|
||||
* Return {@code true} if the ChannelBuf is pooled.
|
||||
*
|
||||
*/
|
||||
boolean isPooled();
|
||||
}
|
||||
|
@ -39,26 +39,36 @@ import java.util.ListIterator;
|
||||
*/
|
||||
public class DefaultCompositeByteBuf extends AbstractByteBuf implements CompositeByteBuf {
|
||||
|
||||
private static final ByteBuffer[] EMPTY_NIOBUFFERS = new ByteBuffer[0];
|
||||
|
||||
private final ByteBufAllocator alloc;
|
||||
private final List<Component> components = new ArrayList<Component>();
|
||||
private final int maxNumComponents;
|
||||
private final Unsafe unsafe = new CompositeUnsafe();
|
||||
|
||||
private Component lastAccessed;
|
||||
private int lastAccessedId;
|
||||
private boolean freed;
|
||||
|
||||
public DefaultCompositeByteBuf(int maxNumComponents) {
|
||||
super(ByteOrder.BIG_ENDIAN, Integer.MAX_VALUE);
|
||||
public DefaultCompositeByteBuf(ByteBufAllocator alloc, int maxNumComponents) {
|
||||
super(Integer.MAX_VALUE);
|
||||
if (alloc == null) {
|
||||
throw new NullPointerException("alloc");
|
||||
}
|
||||
this.alloc = alloc;
|
||||
this.maxNumComponents = maxNumComponents;
|
||||
}
|
||||
|
||||
public DefaultCompositeByteBuf(int maxNumComponents, ByteBuf... buffers) {
|
||||
super(ByteOrder.BIG_ENDIAN, Integer.MAX_VALUE);
|
||||
|
||||
public DefaultCompositeByteBuf(ByteBufAllocator alloc, int maxNumComponents, ByteBuf... buffers) {
|
||||
super(Integer.MAX_VALUE);
|
||||
if (alloc == null) {
|
||||
throw new NullPointerException("alloc");
|
||||
}
|
||||
if (maxNumComponents < 2) {
|
||||
throw new IllegalArgumentException(
|
||||
"maxNumComponents: " + maxNumComponents + " (expected: >= 2)");
|
||||
}
|
||||
|
||||
this.alloc = alloc;
|
||||
this.maxNumComponents = maxNumComponents;
|
||||
|
||||
addComponents0(0, buffers);
|
||||
@ -66,14 +76,17 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
setIndex(0, capacity());
|
||||
}
|
||||
|
||||
public DefaultCompositeByteBuf(int maxNumComponents, Iterable<ByteBuf> buffers) {
|
||||
super(ByteOrder.BIG_ENDIAN, Integer.MAX_VALUE);
|
||||
|
||||
public DefaultCompositeByteBuf(ByteBufAllocator alloc, int maxNumComponents, Iterable<ByteBuf> buffers) {
|
||||
super(Integer.MAX_VALUE);
|
||||
if (alloc == null) {
|
||||
throw new NullPointerException("alloc");
|
||||
}
|
||||
if (maxNumComponents < 2) {
|
||||
throw new IllegalArgumentException(
|
||||
"maxNumComponents: " + maxNumComponents + " (expected: >= 2)");
|
||||
}
|
||||
|
||||
this.alloc = alloc;
|
||||
this.maxNumComponents = maxNumComponents;
|
||||
addComponents0(0, buffers);
|
||||
consolidateIfNeeded();
|
||||
@ -83,7 +96,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
|
||||
@Override
|
||||
public CompositeByteBuf addComponent(ByteBuf buffer) {
|
||||
addComponent0(components.size(), buffer);
|
||||
addComponent0(components.size(), buffer, false);
|
||||
consolidateIfNeeded();
|
||||
return this;
|
||||
}
|
||||
@ -104,12 +117,12 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
|
||||
@Override
|
||||
public CompositeByteBuf addComponent(int cIndex, ByteBuf buffer) {
|
||||
addComponent0(cIndex, buffer);
|
||||
addComponent0(cIndex, buffer, false);
|
||||
consolidateIfNeeded();
|
||||
return this;
|
||||
}
|
||||
|
||||
private int addComponent0(int cIndex, ByteBuf buffer) {
|
||||
private int addComponent0(int cIndex, ByteBuf buffer, boolean addedBySelf) {
|
||||
checkComponentIndex(cIndex);
|
||||
|
||||
if (buffer == null) {
|
||||
@ -128,7 +141,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
}
|
||||
|
||||
// No need to consolidate - just add a component to the list.
|
||||
Component c = new Component(buffer.order(ByteOrder.BIG_ENDIAN).slice());
|
||||
Component c = new Component(buffer.order(ByteOrder.BIG_ENDIAN).slice(), addedBySelf);
|
||||
if (cIndex == components.size()) {
|
||||
components.add(c);
|
||||
if (cIndex == 0) {
|
||||
@ -177,7 +190,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
break;
|
||||
}
|
||||
if (b.readable()) {
|
||||
cIndex = addComponent0(cIndex, b) + 1;
|
||||
cIndex = addComponent0(cIndex, b, false) + 1;
|
||||
int size = components.size();
|
||||
if (cIndex > size) {
|
||||
cIndex = size;
|
||||
@ -246,16 +259,17 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
if (numComponents > maxNumComponents) {
|
||||
final int capacity = components.get(numComponents - 1).endOffset;
|
||||
|
||||
ByteBuf consolidated = components.get(numComponents - 1).buf.unsafe().newBuffer(capacity);
|
||||
ByteBuf consolidated = alloc().buffer(capacity);
|
||||
|
||||
// We're not using foreach to avoid creating an iterator.
|
||||
// noinspection ForLoopReplaceableByForEach
|
||||
for (int i = 0; i < numComponents; i ++) {
|
||||
ByteBuf b = components.get(i).buf;
|
||||
Component c = components.get(i);
|
||||
UnsafeByteBuf b = c.buf;
|
||||
consolidated.writeBytes(b);
|
||||
b.unsafe().release();
|
||||
c.freeIfNecessary();
|
||||
}
|
||||
Component c = new Component(consolidated);
|
||||
Component c = new Component(consolidated, true);
|
||||
c.endOffset = c.length;
|
||||
components.clear();
|
||||
components.add(c);
|
||||
@ -263,6 +277,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
}
|
||||
|
||||
private void checkComponentIndex(int cIndex) {
|
||||
assert !freed;
|
||||
if (cIndex < 0 || cIndex > components.size()) {
|
||||
throw new IndexOutOfBoundsException(String.format(
|
||||
"cIndex: %d (expected: >= 0 && <= numComponents(%d))",
|
||||
@ -271,6 +286,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
}
|
||||
|
||||
private void checkComponentIndex(int cIndex, int numComponents) {
|
||||
assert !freed;
|
||||
if (cIndex < 0 || cIndex + numComponents > components.size()) {
|
||||
throw new IndexOutOfBoundsException(String.format(
|
||||
"cIndex: %d, numComponents: %d " +
|
||||
@ -317,6 +333,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
|
||||
@Override
|
||||
public Iterator<ByteBuf> iterator() {
|
||||
assert !freed;
|
||||
List<ByteBuf> list = new ArrayList<ByteBuf>(components.size());
|
||||
for (Component c: components) {
|
||||
list.add(c.buf);
|
||||
@ -413,6 +430,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
|
||||
@Override
|
||||
public CompositeByteBuf capacity(int newCapacity) {
|
||||
assert !freed;
|
||||
if (newCapacity < 0 || newCapacity > maxCapacity()) {
|
||||
throw new IllegalArgumentException("newCapacity: " + newCapacity);
|
||||
}
|
||||
@ -422,13 +440,15 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
final int paddingLength = newCapacity - oldCapacity;
|
||||
ByteBuf padding;
|
||||
if (components.isEmpty()) {
|
||||
padding = new HeapByteBuf(paddingLength, paddingLength);
|
||||
padding = alloc().buffer(paddingLength, paddingLength);
|
||||
padding.setIndex(0, paddingLength);
|
||||
addComponent0(0, padding, true);
|
||||
} else {
|
||||
Component last = components.get(components.size() - 1);
|
||||
padding = last.buf.unsafe().newBuffer(paddingLength);
|
||||
padding = alloc().buffer(paddingLength);
|
||||
padding.setIndex(0, paddingLength);
|
||||
addComponent0(components.size(), padding, true);
|
||||
consolidateIfNeeded();
|
||||
}
|
||||
padding.setIndex(0, paddingLength);
|
||||
addComponent(padding);
|
||||
} else if (newCapacity < oldCapacity) {
|
||||
int bytesToTrim = oldCapacity - newCapacity;
|
||||
for (ListIterator<Component> i = components.listIterator(components.size()); i.hasPrevious();) {
|
||||
@ -440,10 +460,9 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
}
|
||||
|
||||
// Replace the last component with the trimmed slice.
|
||||
Component newC = new Component(c.buf.slice(0, c.length - bytesToTrim));
|
||||
Component newC = new Component(c.buf.slice(0, c.length - bytesToTrim), c.allocatedBySelf);
|
||||
newC.offset = c.offset;
|
||||
newC.endOffset = newC.offset + newC.length;
|
||||
c.buf.unsafe().release();
|
||||
i.set(newC);
|
||||
break;
|
||||
}
|
||||
@ -457,6 +476,16 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufAllocator alloc() {
|
||||
return alloc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteOrder order() {
|
||||
return ByteOrder.BIG_ENDIAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int numComponents() {
|
||||
return components.size();
|
||||
@ -469,6 +498,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
|
||||
@Override
|
||||
public int toComponentIndex(int offset) {
|
||||
assert !freed;
|
||||
if (offset < 0 || offset >= capacity()) {
|
||||
throw new IndexOutOfBoundsException(String.format(
|
||||
"offset: %d (expected: >= 0 && < capacity(%d))", offset, capacity()));
|
||||
@ -941,7 +971,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
+ (index + length) + ", maximum is " + capacity());
|
||||
}
|
||||
|
||||
ByteBuf dst = unsafe().newBuffer(length);
|
||||
ByteBuf dst = Unpooled.buffer(length);
|
||||
copyTo(index, length, componentId, dst);
|
||||
return dst;
|
||||
}
|
||||
@ -977,6 +1007,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
}
|
||||
|
||||
private Component findComponent(int offset) {
|
||||
assert !freed;
|
||||
if (offset < 0 || offset >= capacity()) {
|
||||
throw new IndexOutOfBoundsException(String.format(
|
||||
"offset: %d (expected: >= 0 && < capacity(%d))", offset, capacity()));
|
||||
@ -1033,6 +1064,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
}
|
||||
|
||||
private ByteBuffer copiedNioBuffer(int index, int length) {
|
||||
assert !freed;
|
||||
if (components.size() == 1) {
|
||||
return toNioBuffer(components.get(0).buf, index, length);
|
||||
}
|
||||
@ -1061,7 +1093,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
throw new IndexOutOfBoundsException("index must be >= 0");
|
||||
}
|
||||
if (length == 0) {
|
||||
return new ByteBuffer[0];
|
||||
return EMPTY_NIOBUFFERS;
|
||||
}
|
||||
int componentId = toComponentIndex(index);
|
||||
|
||||
@ -1092,6 +1124,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
|
||||
@Override
|
||||
public CompositeByteBuf consolidate() {
|
||||
assert !freed;
|
||||
final int numComponents = numComponents();
|
||||
if (numComponents <= 1) {
|
||||
return this;
|
||||
@ -1099,16 +1132,17 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
|
||||
final Component last = components.get(numComponents - 1);
|
||||
final int capacity = last.endOffset;
|
||||
final ByteBuf consolidated = last.buf.unsafe().newBuffer(capacity);
|
||||
final ByteBuf consolidated = alloc().buffer(capacity);
|
||||
|
||||
for (int i = 0; i < numComponents; i ++) {
|
||||
ByteBuf b = components.get(i).buf;
|
||||
Component c = components.get(i);
|
||||
UnsafeByteBuf b = c.buf;
|
||||
consolidated.writeBytes(b);
|
||||
b.unsafe().release();
|
||||
}
|
||||
c.freeIfNecessary();
|
||||
}
|
||||
|
||||
components.clear();
|
||||
components.add(new Component(consolidated));
|
||||
components.add(new Component(consolidated, true));
|
||||
updateComponentOffsets(0);
|
||||
return this;
|
||||
}
|
||||
@ -1123,22 +1157,24 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
final int endCIndex = cIndex + numComponents;
|
||||
final Component last = components.get(endCIndex - 1);
|
||||
final int capacity = last.endOffset - components.get(cIndex).offset;
|
||||
final ByteBuf consolidated = last.buf.unsafe().newBuffer(capacity);
|
||||
final ByteBuf consolidated = alloc().buffer(capacity);
|
||||
|
||||
for (int i = cIndex; i < endCIndex; i ++) {
|
||||
ByteBuf b = components.get(i).buf;
|
||||
Component c = components.get(i);
|
||||
ByteBuf b = c.buf;
|
||||
consolidated.writeBytes(b);
|
||||
b.unsafe().release();
|
||||
c.freeIfNecessary();
|
||||
}
|
||||
|
||||
components.subList(cIndex + 1, endCIndex).clear();
|
||||
components.set(cIndex, new Component(consolidated));
|
||||
components.set(cIndex, new Component(consolidated, true));
|
||||
updateComponentOffsets(cIndex);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeByteBuf discardReadComponents() {
|
||||
assert !freed;
|
||||
final int readerIndex = readerIndex();
|
||||
if (readerIndex == 0) {
|
||||
return this;
|
||||
@ -1148,7 +1184,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
int writerIndex = writerIndex();
|
||||
if (readerIndex == writerIndex && writerIndex == capacity()) {
|
||||
for (Component c: components) {
|
||||
c.buf.unsafe().release();
|
||||
c.freeIfNecessary();
|
||||
}
|
||||
components.clear();
|
||||
setIndex(0, 0);
|
||||
@ -1159,7 +1195,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
// Remove read components.
|
||||
int firstComponentId = toComponentIndex(readerIndex);
|
||||
for (int i = 0; i < firstComponentId; i ++) {
|
||||
components.get(i).buf.unsafe().release();
|
||||
components.get(i).freeIfNecessary();
|
||||
}
|
||||
components.subList(0, firstComponentId).clear();
|
||||
|
||||
@ -1173,6 +1209,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
|
||||
@Override
|
||||
public CompositeByteBuf discardReadBytes() {
|
||||
assert !freed;
|
||||
final int readerIndex = readerIndex();
|
||||
if (readerIndex == 0) {
|
||||
return this;
|
||||
@ -1182,7 +1219,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
int writerIndex = writerIndex();
|
||||
if (readerIndex == writerIndex && writerIndex == capacity()) {
|
||||
for (Component c: components) {
|
||||
c.buf.unsafe().release();
|
||||
c.freeIfNecessary();
|
||||
}
|
||||
components.clear();
|
||||
setIndex(0, 0);
|
||||
@ -1193,7 +1230,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
// Remove read components.
|
||||
int firstComponentId = toComponentIndex(readerIndex);
|
||||
for (int i = 0; i < firstComponentId; i ++) {
|
||||
components.get(i).buf.unsafe().release();
|
||||
components.get(i).freeIfNecessary();
|
||||
}
|
||||
components.subList(0, firstComponentId).clear();
|
||||
|
||||
@ -1204,8 +1241,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
// new slice would be empty, so remove instead
|
||||
components.remove(0);
|
||||
} else {
|
||||
Component newC = new Component(c.buf.slice(adjustment, c.length - adjustment));
|
||||
c.buf.unsafe().release();
|
||||
Component newC = new Component(c.buf.slice(adjustment, c.length - adjustment), c.allocatedBySelf);
|
||||
components.set(0, newC);
|
||||
}
|
||||
|
||||
@ -1224,14 +1260,29 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
}
|
||||
|
||||
private static final class Component {
|
||||
final ByteBuf buf;
|
||||
final UnsafeByteBuf buf;
|
||||
final int length;
|
||||
final boolean allocatedBySelf;
|
||||
int offset;
|
||||
int endOffset;
|
||||
|
||||
Component(ByteBuf buf) {
|
||||
this.buf = buf;
|
||||
Component(ByteBuf buf, boolean allocatedBySelf) {
|
||||
this.buf = (UnsafeByteBuf) buf;
|
||||
length = buf.readableBytes();
|
||||
this.allocatedBySelf = allocatedBySelf;
|
||||
}
|
||||
|
||||
void freeIfNecessary() {
|
||||
if (!allocatedBySelf) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Unwrap so that we can free slices, too.
|
||||
UnsafeByteBuf buf;
|
||||
for (buf = this.buf; buf.unwrap() != null; buf = (UnsafeByteBuf) buf.unwrap()) {
|
||||
continue;
|
||||
}
|
||||
buf.free(); // We should not get a NPE here. If so, it must be a bug.
|
||||
}
|
||||
}
|
||||
|
||||
@ -1458,68 +1509,47 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unsafe unsafe() {
|
||||
return unsafe;
|
||||
public ByteBuffer[] nioBuffers() {
|
||||
return nioBuffers(readerIndex(), readableBytes());
|
||||
}
|
||||
|
||||
private final class CompositeUnsafe implements Unsafe {
|
||||
@Override
|
||||
public ByteBuffer nioBuffer() {
|
||||
if (components.size() == 1) {
|
||||
return components.get(0).buf.unsafe().nioBuffer();
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
@Override
|
||||
public ByteBuffer internalNioBuffer() {
|
||||
if (components.size() == 1) {
|
||||
return components.get(0).buf.internalNioBuffer();
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] internalNioBuffers() {
|
||||
ByteBuffer[] nioBuffers = new ByteBuffer[components.size()];
|
||||
int index = 0;
|
||||
for (Component component : components) {
|
||||
nioBuffers[index++] = component.buf.internalNioBuffer();
|
||||
}
|
||||
return nioBuffers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void discardSomeReadBytes() {
|
||||
discardReadComponents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free() {
|
||||
if (freed) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] nioBuffers() {
|
||||
ByteBuffer[] nioBuffers = new ByteBuffer[components.size()];
|
||||
int index = 0;
|
||||
for (Component component : components) {
|
||||
nioBuffers[index++] = component.buf.unsafe().nioBuffer();
|
||||
}
|
||||
return nioBuffers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf newBuffer(int initialCapacity) {
|
||||
CompositeByteBuf buf = new DefaultCompositeByteBuf(maxNumComponents);
|
||||
buf.addComponent(new HeapByteBuf(new byte[initialCapacity], initialCapacity));
|
||||
return buf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void discardSomeReadBytes() {
|
||||
discardReadComponents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acquire() {
|
||||
if (refCnt <= 0) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
refCnt ++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
if (refCnt <= 0) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
refCnt --;
|
||||
if (refCnt == 0) {
|
||||
for (Component c: components) {
|
||||
c.buf.unsafe().release();
|
||||
}
|
||||
|
||||
components.clear();
|
||||
lastAccessed = null;
|
||||
}
|
||||
freed = true;
|
||||
for (Component c: components) {
|
||||
c.freeIfNecessary();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] nioBuffers() {
|
||||
return nioBuffers(readerIndex(), readableBytes());
|
||||
public ByteBuf unwrap() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -32,11 +32,6 @@ public class DefaultMessageBuf<T> extends ArrayDeque<T> implements MessageBuf<T>
|
||||
super(initialCapacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPooled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelBufType type() {
|
||||
return ChannelBufType.MESSAGE;
|
||||
|
@ -19,6 +19,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
|
||||
@ -28,13 +29,12 @@ import java.nio.channels.ScatteringByteChannel;
|
||||
* parent. It is recommended to use {@link ByteBuf#duplicate()} instead
|
||||
* of calling the constructor explicitly.
|
||||
*/
|
||||
public class DuplicatedByteBuf extends AbstractWrappedByteBuf {
|
||||
public class DuplicatedByteBuf extends AbstractByteBuf {
|
||||
|
||||
private final Unsafe unsafe = new DuplicatedUnsafe();
|
||||
final ByteBuf buffer;
|
||||
private final UnsafeByteBuf buffer;
|
||||
|
||||
public DuplicatedByteBuf(ByteBuf buffer) {
|
||||
super(buffer.order(), buffer.maxCapacity());
|
||||
public DuplicatedByteBuf(UnsafeByteBuf buffer) {
|
||||
super(buffer.maxCapacity());
|
||||
|
||||
if (buffer instanceof DuplicatedByteBuf) {
|
||||
this.buffer = ((DuplicatedByteBuf) buffer).buffer;
|
||||
@ -43,8 +43,6 @@ public class DuplicatedByteBuf extends AbstractWrappedByteBuf {
|
||||
}
|
||||
|
||||
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
||||
|
||||
buffer.unsafe().acquire();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -52,6 +50,16 @@ public class DuplicatedByteBuf extends AbstractWrappedByteBuf {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufAllocator alloc() {
|
||||
return buffer.alloc();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteOrder order() {
|
||||
return buffer.order();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirect() {
|
||||
return buffer.isDirect();
|
||||
@ -63,7 +71,7 @@ public class DuplicatedByteBuf extends AbstractWrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf capacity(int newCapacity) {
|
||||
public ByteBuf capacity(int newCapacity) {
|
||||
buffer.capacity(newCapacity);
|
||||
return this;
|
||||
}
|
||||
@ -119,73 +127,73 @@ public class DuplicatedByteBuf extends AbstractWrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||
buffer.getBytes(index, dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
buffer.getBytes(index, dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, ByteBuffer dst) {
|
||||
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||
buffer.getBytes(index, dst);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setByte(int index, int value) {
|
||||
public ByteBuf setByte(int index, int value) {
|
||||
buffer.setByte(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setShort(int index, int value) {
|
||||
public ByteBuf setShort(int index, int value) {
|
||||
buffer.setShort(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setMedium(int index, int value) {
|
||||
public ByteBuf setMedium(int index, int value) {
|
||||
buffer.setMedium(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setInt(int index, int value) {
|
||||
public ByteBuf setInt(int index, int value) {
|
||||
buffer.setInt(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setLong(int index, long value) {
|
||||
public ByteBuf setLong(int index, long value) {
|
||||
buffer.setLong(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
buffer.setBytes(index, src, srcIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||
buffer.setBytes(index, src, srcIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, ByteBuffer src) {
|
||||
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||
buffer.setBytes(index, src);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, OutputStream out, int length)
|
||||
public ByteBuf getBytes(int index, OutputStream out, int length)
|
||||
throws IOException {
|
||||
buffer.getBytes(index, out, length);
|
||||
return this;
|
||||
@ -230,40 +238,22 @@ public class DuplicatedByteBuf extends AbstractWrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unsafe unsafe() {
|
||||
return unsafe;
|
||||
public ByteBuffer internalNioBuffer() {
|
||||
return buffer.internalNioBuffer();
|
||||
}
|
||||
|
||||
private final class DuplicatedUnsafe implements Unsafe {
|
||||
@Override
|
||||
public ByteBuffer[] internalNioBuffers() {
|
||||
return buffer.internalNioBuffers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer nioBuffer() {
|
||||
return buffer.unsafe().nioBuffer();
|
||||
}
|
||||
@Override
|
||||
public void discardSomeReadBytes() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] nioBuffers() {
|
||||
return buffer.unsafe().nioBuffers();
|
||||
}
|
||||
@Override
|
||||
public void free() {
|
||||
|
||||
@Override
|
||||
public ByteBuf newBuffer(int initialCapacity) {
|
||||
return buffer.unsafe().newBuffer(initialCapacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void discardSomeReadBytes() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acquire() {
|
||||
buffer.unsafe().acquire();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
buffer.unsafe().release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,11 +30,6 @@ public class QueueBackedMessageBuf<T> implements MessageBuf<T> {
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPooled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelBufType type() {
|
||||
return ChannelBufType.MESSAGE;
|
||||
|
@ -19,6 +19,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.ReadOnlyBufferException;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
@ -28,27 +29,36 @@ import java.nio.channels.ScatteringByteChannel;
|
||||
* recommended to use {@link Unpooled#unmodifiableBuffer(ByteBuf)}
|
||||
* instead of calling the constructor explicitly.
|
||||
*/
|
||||
public class ReadOnlyByteBuf extends AbstractWrappedByteBuf {
|
||||
public class ReadOnlyByteBuf extends AbstractByteBuf {
|
||||
|
||||
private final ByteBuf buffer;
|
||||
private final UnsafeByteBuf buffer;
|
||||
|
||||
public ReadOnlyByteBuf(UnsafeByteBuf buffer) {
|
||||
super(buffer.maxCapacity());
|
||||
|
||||
if (buffer instanceof ReadOnlyByteBuf) {
|
||||
buffer = ((ReadOnlyByteBuf) buffer).buffer;
|
||||
}
|
||||
|
||||
public ReadOnlyByteBuf(ByteBuf buffer) {
|
||||
super(buffer.order(), buffer.maxCapacity());
|
||||
this.buffer = buffer;
|
||||
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
||||
}
|
||||
|
||||
private ReadOnlyByteBuf(ReadOnlyByteBuf buffer) {
|
||||
super(buffer.buffer.order(), buffer.maxCapacity());
|
||||
this.buffer = buffer.buffer;
|
||||
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf unwrap() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufAllocator alloc() {
|
||||
return buffer.alloc();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteOrder order() {
|
||||
return buffer.order();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirect() {
|
||||
return buffer.isDirect();
|
||||
@ -70,47 +80,47 @@ public class ReadOnlyByteBuf extends AbstractWrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf discardReadBytes() {
|
||||
public ByteBuf discardReadBytes() {
|
||||
throw new ReadOnlyBufferException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setByte(int index, int value) {
|
||||
public ByteBuf setByte(int index, int value) {
|
||||
throw new ReadOnlyBufferException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||
throw new ReadOnlyBufferException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
throw new ReadOnlyBufferException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, ByteBuffer src) {
|
||||
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||
throw new ReadOnlyBufferException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setShort(int index, int value) {
|
||||
public ByteBuf setShort(int index, int value) {
|
||||
throw new ReadOnlyBufferException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setMedium(int index, int value) {
|
||||
public ByteBuf setMedium(int index, int value) {
|
||||
throw new ReadOnlyBufferException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setInt(int index, int value) {
|
||||
public ByteBuf setInt(int index, int value) {
|
||||
throw new ReadOnlyBufferException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setLong(int index, long value) {
|
||||
public ByteBuf setLong(int index, long value) {
|
||||
throw new ReadOnlyBufferException();
|
||||
}
|
||||
|
||||
@ -133,26 +143,26 @@ public class ReadOnlyByteBuf extends AbstractWrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, OutputStream out, int length)
|
||||
public ByteBuf getBytes(int index, OutputStream out, int length)
|
||||
throws IOException {
|
||||
buffer.getBytes(index, out, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
buffer.getBytes(index, dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||
buffer.getBytes(index, dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, ByteBuffer dst) {
|
||||
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||
buffer.getBytes(index, dst);
|
||||
return this;
|
||||
}
|
||||
@ -169,7 +179,7 @@ public class ReadOnlyByteBuf extends AbstractWrappedByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf slice(int index, int length) {
|
||||
return new ReadOnlyByteBuf(buffer.slice(index, length));
|
||||
return new ReadOnlyByteBuf((UnsafeByteBuf) buffer.slice(index, length));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -223,12 +233,25 @@ public class ReadOnlyByteBuf extends AbstractWrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf capacity(int newCapacity) {
|
||||
public ByteBuf capacity(int newCapacity) {
|
||||
throw new ReadOnlyBufferException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unsafe unsafe() {
|
||||
return buffer.unsafe();
|
||||
public ByteBuffer internalNioBuffer() {
|
||||
return buffer.internalNioBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] internalNioBuffers() {
|
||||
return buffer.internalNioBuffers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void discardSomeReadBytes() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free() { }
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
|
||||
@ -29,15 +30,14 @@ import java.nio.channels.ScatteringByteChannel;
|
||||
* {@link ByteBuf#slice(int, int)} instead of calling the constructor
|
||||
* explicitly.
|
||||
*/
|
||||
public class SlicedByteBuf extends AbstractWrappedByteBuf {
|
||||
public class SlicedByteBuf extends AbstractByteBuf {
|
||||
|
||||
private final Unsafe unsafe = new SlicedUnsafe();
|
||||
private final ByteBuf buffer;
|
||||
private final UnsafeByteBuf buffer;
|
||||
private final int adjustment;
|
||||
private final int length;
|
||||
|
||||
public SlicedByteBuf(ByteBuf buffer, int index, int length) {
|
||||
super(buffer.order(), length);
|
||||
public SlicedByteBuf(UnsafeByteBuf buffer, int index, int length) {
|
||||
super(length);
|
||||
if (index < 0 || index > buffer.capacity()) {
|
||||
throw new IndexOutOfBoundsException("Invalid index of " + index
|
||||
+ ", maximum is " + buffer.capacity());
|
||||
@ -52,7 +52,7 @@ public class SlicedByteBuf extends AbstractWrappedByteBuf {
|
||||
this.buffer = ((SlicedByteBuf) buffer).buffer;
|
||||
adjustment = ((SlicedByteBuf) buffer).adjustment + index;
|
||||
} else if (buffer instanceof DuplicatedByteBuf) {
|
||||
this.buffer = ((DuplicatedByteBuf) buffer).buffer;
|
||||
this.buffer = (UnsafeByteBuf) buffer.unwrap();
|
||||
adjustment = index;
|
||||
} else {
|
||||
this.buffer = buffer;
|
||||
@ -61,8 +61,6 @@ public class SlicedByteBuf extends AbstractWrappedByteBuf {
|
||||
this.length = length;
|
||||
|
||||
writerIndex(length);
|
||||
|
||||
buffer.unsafe().acquire();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -70,6 +68,16 @@ public class SlicedByteBuf extends AbstractWrappedByteBuf {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufAllocator alloc() {
|
||||
return buffer.alloc();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteOrder order() {
|
||||
return buffer.order();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirect() {
|
||||
return buffer.isDirect();
|
||||
@ -81,7 +89,7 @@ public class SlicedByteBuf extends AbstractWrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf capacity(int newCapacity) {
|
||||
public ByteBuf capacity(int newCapacity) {
|
||||
throw new UnsupportedOperationException("sliced buffer");
|
||||
}
|
||||
|
||||
@ -153,84 +161,84 @@ public class SlicedByteBuf extends AbstractWrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||
checkIndex(index, length);
|
||||
buffer.getBytes(index + adjustment, dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
checkIndex(index, length);
|
||||
buffer.getBytes(index + adjustment, dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, ByteBuffer dst) {
|
||||
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||
checkIndex(index, dst.remaining());
|
||||
buffer.getBytes(index + adjustment, dst);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setByte(int index, int value) {
|
||||
public ByteBuf setByte(int index, int value) {
|
||||
checkIndex(index);
|
||||
buffer.setByte(index + adjustment, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setShort(int index, int value) {
|
||||
public ByteBuf setShort(int index, int value) {
|
||||
checkIndex(index, 2);
|
||||
buffer.setShort(index + adjustment, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setMedium(int index, int value) {
|
||||
public ByteBuf setMedium(int index, int value) {
|
||||
checkIndex(index, 3);
|
||||
buffer.setMedium(index + adjustment, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setInt(int index, int value) {
|
||||
public ByteBuf setInt(int index, int value) {
|
||||
checkIndex(index, 4);
|
||||
buffer.setInt(index + adjustment, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setLong(int index, long value) {
|
||||
public ByteBuf setLong(int index, long value) {
|
||||
checkIndex(index, 8);
|
||||
buffer.setLong(index + adjustment, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
checkIndex(index, length);
|
||||
buffer.setBytes(index + adjustment, src, srcIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||
checkIndex(index, length);
|
||||
buffer.setBytes(index + adjustment, src, srcIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, ByteBuffer src) {
|
||||
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||
checkIndex(index, src.remaining());
|
||||
buffer.setBytes(index + adjustment, src);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, OutputStream out, int length)
|
||||
public ByteBuf getBytes(int index, OutputStream out, int length)
|
||||
throws IOException {
|
||||
checkIndex(index, length);
|
||||
buffer.getBytes(index + adjustment, out, length);
|
||||
@ -302,40 +310,20 @@ public class SlicedByteBuf extends AbstractWrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unsafe unsafe() {
|
||||
return unsafe;
|
||||
public ByteBuffer internalNioBuffer() {
|
||||
return buffer.nioBuffer(adjustment, length);
|
||||
}
|
||||
|
||||
private final class SlicedUnsafe implements Unsafe {
|
||||
|
||||
@Override
|
||||
public ByteBuffer nioBuffer() {
|
||||
return buffer.nioBuffer(adjustment, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] nioBuffers() {
|
||||
return buffer.nioBuffers(adjustment, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf newBuffer(int initialCapacity) {
|
||||
return buffer.unsafe().newBuffer(initialCapacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void discardSomeReadBytes() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acquire() {
|
||||
buffer.unsafe().acquire();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
buffer.unsafe().release();
|
||||
}
|
||||
@Override
|
||||
public ByteBuffer[] internalNioBuffers() {
|
||||
return buffer.nioBuffers(adjustment, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void discardSomeReadBytes() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free() { }
|
||||
}
|
||||
|
@ -24,12 +24,12 @@ import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public class SwappedByteBuf implements WrappedByteBuf {
|
||||
public class SwappedByteBuf implements UnsafeByteBuf {
|
||||
|
||||
private final ByteBuf buf;
|
||||
private final UnsafeByteBuf buf;
|
||||
private final ByteOrder order;
|
||||
|
||||
public SwappedByteBuf(ByteBuf buf) {
|
||||
public SwappedByteBuf(UnsafeByteBuf buf) {
|
||||
if (buf == null) {
|
||||
throw new NullPointerException("buf");
|
||||
}
|
||||
@ -63,8 +63,8 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPooled() {
|
||||
return buf.isPooled();
|
||||
public ByteBufAllocator alloc() {
|
||||
return buf.alloc();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -78,7 +78,7 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf capacity(int newCapacity) {
|
||||
public ByteBuf capacity(int newCapacity) {
|
||||
buf.capacity(newCapacity);
|
||||
return this;
|
||||
}
|
||||
@ -99,7 +99,7 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf readerIndex(int readerIndex) {
|
||||
public ByteBuf readerIndex(int readerIndex) {
|
||||
buf.readerIndex(readerIndex);
|
||||
return this;
|
||||
}
|
||||
@ -110,13 +110,13 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writerIndex(int writerIndex) {
|
||||
public ByteBuf writerIndex(int writerIndex) {
|
||||
buf.writerIndex(writerIndex);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setIndex(int readerIndex, int writerIndex) {
|
||||
public ByteBuf setIndex(int readerIndex, int writerIndex) {
|
||||
buf.setIndex(readerIndex, writerIndex);
|
||||
return this;
|
||||
}
|
||||
@ -142,43 +142,43 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf clear() {
|
||||
public ByteBuf clear() {
|
||||
buf.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf markReaderIndex() {
|
||||
public ByteBuf markReaderIndex() {
|
||||
buf.markReaderIndex();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf resetReaderIndex() {
|
||||
public ByteBuf resetReaderIndex() {
|
||||
buf.resetReaderIndex();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf markWriterIndex() {
|
||||
public ByteBuf markWriterIndex() {
|
||||
buf.markWriterIndex();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf resetWriterIndex() {
|
||||
public ByteBuf resetWriterIndex() {
|
||||
buf.resetWriterIndex();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf discardReadBytes() {
|
||||
public ByteBuf discardReadBytes() {
|
||||
buf.discardReadBytes();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf ensureWritableBytes(int writableBytes) {
|
||||
public ByteBuf ensureWritableBytes(int writableBytes) {
|
||||
buf.ensureWritableBytes(writableBytes);
|
||||
return this;
|
||||
}
|
||||
@ -254,43 +254,43 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, ByteBuf dst) {
|
||||
public ByteBuf getBytes(int index, ByteBuf dst) {
|
||||
buf.getBytes(index, dst);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, ByteBuf dst, int length) {
|
||||
public ByteBuf getBytes(int index, ByteBuf dst, int length) {
|
||||
buf.getBytes(index, dst, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||
buf.getBytes(index, dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, byte[] dst) {
|
||||
public ByteBuf getBytes(int index, byte[] dst) {
|
||||
buf.getBytes(index, dst);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
buf.getBytes(index, dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, ByteBuffer dst) {
|
||||
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||
buf.getBytes(index, dst);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
|
||||
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
|
||||
buf.getBytes(index, out, length);
|
||||
return this;
|
||||
}
|
||||
@ -301,91 +301,91 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBoolean(int index, boolean value) {
|
||||
public ByteBuf setBoolean(int index, boolean value) {
|
||||
buf.setBoolean(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setByte(int index, int value) {
|
||||
public ByteBuf setByte(int index, int value) {
|
||||
buf.setByte(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setShort(int index, int value) {
|
||||
public ByteBuf setShort(int index, int value) {
|
||||
buf.setShort(index, ByteBufUtil.swapShort((short) value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setMedium(int index, int value) {
|
||||
public ByteBuf setMedium(int index, int value) {
|
||||
buf.setMedium(index, ByteBufUtil.swapMedium(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setInt(int index, int value) {
|
||||
public ByteBuf setInt(int index, int value) {
|
||||
buf.setInt(index, ByteBufUtil.swapInt(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setLong(int index, long value) {
|
||||
public ByteBuf setLong(int index, long value) {
|
||||
buf.setLong(index, ByteBufUtil.swapLong(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setChar(int index, int value) {
|
||||
public ByteBuf setChar(int index, int value) {
|
||||
setShort(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setFloat(int index, float value) {
|
||||
public ByteBuf setFloat(int index, float value) {
|
||||
setInt(index, Float.floatToRawIntBits(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setDouble(int index, double value) {
|
||||
public ByteBuf setDouble(int index, double value) {
|
||||
setLong(index, Double.doubleToRawLongBits(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, ByteBuf src) {
|
||||
public ByteBuf setBytes(int index, ByteBuf src) {
|
||||
buf.setBytes(index, src);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, ByteBuf src, int length) {
|
||||
public ByteBuf setBytes(int index, ByteBuf src, int length) {
|
||||
buf.setBytes(index, src, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||
buf.setBytes(index, src, srcIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, byte[] src) {
|
||||
public ByteBuf setBytes(int index, byte[] src) {
|
||||
buf.setBytes(index, src);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
buf.setBytes(index, src, srcIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setBytes(int index, ByteBuffer src) {
|
||||
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||
buf.setBytes(index, src);
|
||||
return this;
|
||||
}
|
||||
@ -401,7 +401,7 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf setZero(int index, int length) {
|
||||
public ByteBuf setZero(int index, int length) {
|
||||
buf.setZero(index, length);
|
||||
return this;
|
||||
}
|
||||
@ -473,7 +473,7 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf readBytes(int length) {
|
||||
return buf.readBytes(length);
|
||||
return buf.readBytes(length).order(order());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -482,43 +482,43 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf readBytes(ByteBuf dst) {
|
||||
public ByteBuf readBytes(ByteBuf dst) {
|
||||
buf.readBytes(dst);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf readBytes(ByteBuf dst, int length) {
|
||||
public ByteBuf readBytes(ByteBuf dst, int length) {
|
||||
buf.readBytes(dst, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf readBytes(ByteBuf dst, int dstIndex, int length) {
|
||||
public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) {
|
||||
buf.readBytes(dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf readBytes(byte[] dst) {
|
||||
public ByteBuf readBytes(byte[] dst) {
|
||||
buf.readBytes(dst);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf readBytes(byte[] dst, int dstIndex, int length) {
|
||||
public ByteBuf readBytes(byte[] dst, int dstIndex, int length) {
|
||||
buf.readBytes(dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf readBytes(ByteBuffer dst) {
|
||||
public ByteBuf readBytes(ByteBuffer dst) {
|
||||
buf.readBytes(dst);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf readBytes(OutputStream out, int length) throws IOException {
|
||||
public ByteBuf readBytes(OutputStream out, int length) throws IOException {
|
||||
buf.readBytes(out, length);
|
||||
return this;
|
||||
}
|
||||
@ -529,97 +529,97 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf skipBytes(int length) {
|
||||
public ByteBuf skipBytes(int length) {
|
||||
buf.skipBytes(length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeBoolean(boolean value) {
|
||||
public ByteBuf writeBoolean(boolean value) {
|
||||
buf.writeBoolean(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeByte(int value) {
|
||||
public ByteBuf writeByte(int value) {
|
||||
buf.writeByte(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeShort(int value) {
|
||||
public ByteBuf writeShort(int value) {
|
||||
buf.writeShort(ByteBufUtil.swapShort((short) value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeMedium(int value) {
|
||||
public ByteBuf writeMedium(int value) {
|
||||
buf.writeMedium(ByteBufUtil.swapMedium(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeInt(int value) {
|
||||
public ByteBuf writeInt(int value) {
|
||||
buf.writeInt(ByteBufUtil.swapInt(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeLong(long value) {
|
||||
public ByteBuf writeLong(long value) {
|
||||
buf.writeLong(ByteBufUtil.swapLong(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeChar(int value) {
|
||||
public ByteBuf writeChar(int value) {
|
||||
writeShort(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeFloat(float value) {
|
||||
public ByteBuf writeFloat(float value) {
|
||||
writeInt(Float.floatToRawIntBits(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeDouble(double value) {
|
||||
public ByteBuf writeDouble(double value) {
|
||||
writeLong(Double.doubleToRawLongBits(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeBytes(ByteBuf src) {
|
||||
public ByteBuf writeBytes(ByteBuf src) {
|
||||
buf.writeBytes(src);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeBytes(ByteBuf src, int length) {
|
||||
public ByteBuf writeBytes(ByteBuf src, int length) {
|
||||
buf.writeBytes(src, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeBytes(ByteBuf src, int srcIndex, int length) {
|
||||
public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) {
|
||||
buf.writeBytes(src, srcIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeBytes(byte[] src) {
|
||||
public ByteBuf writeBytes(byte[] src) {
|
||||
buf.writeBytes(src);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeBytes(byte[] src, int srcIndex, int length) {
|
||||
public ByteBuf writeBytes(byte[] src, int srcIndex, int length) {
|
||||
buf.writeBytes(src, srcIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeBytes(ByteBuffer src) {
|
||||
public ByteBuf writeBytes(ByteBuffer src) {
|
||||
buf.writeBytes(src);
|
||||
return this;
|
||||
}
|
||||
@ -635,7 +635,7 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf writeZero(int length) {
|
||||
public ByteBuf writeZero(int length) {
|
||||
buf.writeZero(length);
|
||||
return this;
|
||||
}
|
||||
@ -768,11 +768,6 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
||||
return buf.toString(index, length, charset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unsafe unsafe() {
|
||||
return buf.unsafe();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return buf.hashCode();
|
||||
@ -798,4 +793,22 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
||||
public String toString() {
|
||||
return "Swapped(" + buf.toString() + ')';
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer internalNioBuffer() {
|
||||
return buf.internalNioBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] internalNioBuffers() {
|
||||
return buf.internalNioBuffers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void discardSomeReadBytes() {
|
||||
buf.discardSomeReadBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free() { }
|
||||
}
|
||||
|
@ -77,6 +77,8 @@ import java.util.Queue;
|
||||
*/
|
||||
public final class Unpooled {
|
||||
|
||||
private static final ByteBufAllocator ALLOC = UnpooledByteBufAllocator.HEAP_BY_DEFAULT;
|
||||
|
||||
/**
|
||||
* Big endian byte order.
|
||||
*/
|
||||
@ -90,15 +92,7 @@ public final class Unpooled {
|
||||
/**
|
||||
* A buffer whose capacity is {@code 0}.
|
||||
*/
|
||||
public static final ByteBuf EMPTY_BUFFER = new HeapByteBuf(0, 0) {
|
||||
@Override
|
||||
public ByteBuf order(ByteOrder endianness) {
|
||||
if (endianness == null) {
|
||||
throw new NullPointerException("endianness");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
};
|
||||
public static final ByteBuf EMPTY_BUFFER = ALLOC.heapBuffer(0, 0);
|
||||
|
||||
public static <T> MessageBuf<T> messageBuffer() {
|
||||
return new DefaultMessageBuf<T>();
|
||||
@ -120,7 +114,7 @@ public final class Unpooled {
|
||||
* expands its capacity boundlessly on demand.
|
||||
*/
|
||||
public static ByteBuf buffer() {
|
||||
return buffer(256, Integer.MAX_VALUE);
|
||||
return ALLOC.heapBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,7 +122,7 @@ public final class Unpooled {
|
||||
* expands its capacity boundlessly on demand.
|
||||
*/
|
||||
public static ByteBuf directBuffer() {
|
||||
return directBuffer(256, Integer.MAX_VALUE);
|
||||
return ALLOC.directBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,7 +131,7 @@ public final class Unpooled {
|
||||
* {@code writerIndex} are {@code 0}.
|
||||
*/
|
||||
public static ByteBuf buffer(int initialCapacity) {
|
||||
return buffer(initialCapacity, Integer.MAX_VALUE);
|
||||
return ALLOC.heapBuffer(initialCapacity);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -146,7 +140,7 @@ public final class Unpooled {
|
||||
* {@code writerIndex} are {@code 0}.
|
||||
*/
|
||||
public static ByteBuf directBuffer(int initialCapacity) {
|
||||
return directBuffer(initialCapacity, Integer.MAX_VALUE);
|
||||
return ALLOC.directBuffer(initialCapacity);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,10 +149,7 @@ public final class Unpooled {
|
||||
* {@code writerIndex} are {@code 0}.
|
||||
*/
|
||||
public static ByteBuf buffer(int initialCapacity, int maxCapacity) {
|
||||
if (initialCapacity == 0 && maxCapacity == 0) {
|
||||
return EMPTY_BUFFER;
|
||||
}
|
||||
return new HeapByteBuf(initialCapacity, maxCapacity);
|
||||
return ALLOC.heapBuffer(initialCapacity, maxCapacity);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,10 +158,7 @@ public final class Unpooled {
|
||||
* {@code writerIndex} are {@code 0}.
|
||||
*/
|
||||
public static ByteBuf directBuffer(int initialCapacity, int maxCapacity) {
|
||||
if (initialCapacity == 0 && maxCapacity == 0) {
|
||||
return EMPTY_BUFFER;
|
||||
}
|
||||
return new DirectByteBuf(initialCapacity, maxCapacity);
|
||||
return ALLOC.directBuffer(initialCapacity, maxCapacity);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -182,7 +170,7 @@ public final class Unpooled {
|
||||
if (array.length == 0) {
|
||||
return EMPTY_BUFFER;
|
||||
}
|
||||
return new HeapByteBuf(array, array.length);
|
||||
return new UnpooledHeapByteBuf(ALLOC, array, array.length);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -199,7 +187,7 @@ public final class Unpooled {
|
||||
return wrappedBuffer(array);
|
||||
}
|
||||
|
||||
return new SlicedByteBuf(wrappedBuffer(array), offset, length);
|
||||
return wrappedBuffer(array).slice(offset, length);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -217,7 +205,7 @@ public final class Unpooled {
|
||||
buffer.arrayOffset() + buffer.position(),
|
||||
buffer.remaining()).order(buffer.order());
|
||||
} else {
|
||||
return new DirectByteBuf(buffer, buffer.remaining());
|
||||
return new UnpooledDirectByteBuf(ALLOC, buffer, buffer.remaining());
|
||||
}
|
||||
}
|
||||
|
||||
@ -288,7 +276,7 @@ public final class Unpooled {
|
||||
}
|
||||
|
||||
if (!components.isEmpty()) {
|
||||
return new DefaultCompositeByteBuf(maxNumComponents, components);
|
||||
return new DefaultCompositeByteBuf(ALLOC, maxNumComponents, components);
|
||||
}
|
||||
}
|
||||
|
||||
@ -312,7 +300,7 @@ public final class Unpooled {
|
||||
default:
|
||||
for (ByteBuf b: buffers) {
|
||||
if (b.readable()) {
|
||||
return new DefaultCompositeByteBuf(maxNumComponents, buffers);
|
||||
return new DefaultCompositeByteBuf(ALLOC, maxNumComponents, buffers);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -346,7 +334,7 @@ public final class Unpooled {
|
||||
}
|
||||
|
||||
if (!components.isEmpty()) {
|
||||
return new DefaultCompositeByteBuf(maxNumComponents, components);
|
||||
return new DefaultCompositeByteBuf(ALLOC, maxNumComponents, components);
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,7 +352,7 @@ public final class Unpooled {
|
||||
* Returns a new big-endian composite buffer with no components.
|
||||
*/
|
||||
public static CompositeByteBuf compositeBuffer(int maxNumComponents) {
|
||||
return new DefaultCompositeByteBuf(maxNumComponents);
|
||||
return new DefaultCompositeByteBuf(ALLOC, maxNumComponents);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -674,10 +662,7 @@ public final class Unpooled {
|
||||
* {@code buffer}.
|
||||
*/
|
||||
public static ByteBuf unmodifiableBuffer(ByteBuf buffer) {
|
||||
if (buffer instanceof ReadOnlyByteBuf) {
|
||||
buffer = ((ReadOnlyByteBuf) buffer).unwrap();
|
||||
}
|
||||
return new ReadOnlyByteBuf(buffer);
|
||||
return new ReadOnlyByteBuf((UnsafeByteBuf) buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.internal.DetectionUtil;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Simplistic {@link ByteBufAllocator} implementation that does not pool anything.
|
||||
*/
|
||||
public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator {
|
||||
|
||||
public static final UnpooledByteBufAllocator HEAP_BY_DEFAULT = new UnpooledByteBufAllocator(false);
|
||||
public static final UnpooledByteBufAllocator DIRECT_BY_DEFAULT = new UnpooledByteBufAllocator(true);
|
||||
|
||||
private UnpooledByteBufAllocator(boolean directByDefault) {
|
||||
super(directByDefault);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) {
|
||||
return new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
|
||||
return new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf ioBuffer() {
|
||||
if (DetectionUtil.canFreeDirectBuffer()) {
|
||||
return directBuffer();
|
||||
}
|
||||
|
||||
return heapBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
throw new IllegalStateException(getClass().getName() + " cannot be shut down.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShutdown() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTerminated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
Thread.sleep(unit.toMillis(timeout));
|
||||
return false;
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ import java.nio.channels.ScatteringByteChannel;
|
||||
* constructor explicitly.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class DirectByteBuf extends AbstractByteBuf {
|
||||
public class UnpooledDirectByteBuf extends AbstractByteBuf {
|
||||
|
||||
private static final Field CLEANER_FIELD;
|
||||
|
||||
@ -52,6 +52,11 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
}
|
||||
|
||||
private static void freeDirect(ByteBuffer buffer) {
|
||||
if (CLEANER_FIELD == null) {
|
||||
// Doomed to wait for GC.
|
||||
return;
|
||||
}
|
||||
|
||||
Cleaner cleaner;
|
||||
try {
|
||||
cleaner = (Cleaner) CLEANER_FIELD.get(buffer);
|
||||
@ -61,12 +66,12 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
}
|
||||
}
|
||||
|
||||
private final Unsafe unsafe = new DirectUnsafe();
|
||||
|
||||
private boolean doNotFree;
|
||||
private final ByteBufAllocator alloc;
|
||||
private ByteBuffer buffer;
|
||||
private ByteBuffer tmpBuf;
|
||||
private ByteBuffer tmpNioBuf;
|
||||
private int capacity;
|
||||
private boolean freed;
|
||||
private boolean doNotFree;
|
||||
|
||||
/**
|
||||
* Creates a new direct buffer.
|
||||
@ -74,8 +79,11 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
* @param initialCapacity the initial capacity of the underlying direct buffer
|
||||
* @param maxCapacity the maximum capacity of the underlying direct buffer
|
||||
*/
|
||||
public DirectByteBuf(int initialCapacity, int maxCapacity) {
|
||||
super(ByteOrder.BIG_ENDIAN, maxCapacity);
|
||||
public UnpooledDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
|
||||
super(maxCapacity);
|
||||
if (alloc == null) {
|
||||
throw new NullPointerException("alloc");
|
||||
}
|
||||
if (initialCapacity < 0) {
|
||||
throw new IllegalArgumentException("initialCapacity: " + initialCapacity);
|
||||
}
|
||||
@ -87,6 +95,7 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
"initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity));
|
||||
}
|
||||
|
||||
this.alloc = alloc;
|
||||
setByteBuffer(ByteBuffer.allocateDirect(initialCapacity));
|
||||
}
|
||||
|
||||
@ -95,9 +104,11 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
*
|
||||
* @param maxCapacity the maximum capacity of the underlying direct buffer
|
||||
*/
|
||||
public DirectByteBuf(ByteBuffer initialBuffer, int maxCapacity) {
|
||||
super(ByteOrder.BIG_ENDIAN, maxCapacity);
|
||||
|
||||
public UnpooledDirectByteBuf(ByteBufAllocator alloc, ByteBuffer initialBuffer, int maxCapacity) {
|
||||
super(maxCapacity);
|
||||
if (alloc == null) {
|
||||
throw new NullPointerException("alloc");
|
||||
}
|
||||
if (initialBuffer == null) {
|
||||
throw new NullPointerException("initialBuffer");
|
||||
}
|
||||
@ -114,6 +125,7 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
"initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity));
|
||||
}
|
||||
|
||||
this.alloc = alloc;
|
||||
doNotFree = true;
|
||||
setByteBuffer(initialBuffer.slice().order(ByteOrder.BIG_ENDIAN));
|
||||
writerIndex(initialCapacity);
|
||||
@ -130,7 +142,7 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
}
|
||||
|
||||
this.buffer = buffer;
|
||||
tmpBuf = buffer.duplicate();
|
||||
tmpNioBuf = null;
|
||||
capacity = buffer.remaining();
|
||||
}
|
||||
|
||||
@ -146,6 +158,7 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf capacity(int newCapacity) {
|
||||
assert !freed;
|
||||
if (newCapacity < 0 || newCapacity > maxCapacity()) {
|
||||
throw new IllegalArgumentException("newCapacity: " + newCapacity);
|
||||
}
|
||||
@ -181,6 +194,16 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufAllocator alloc() {
|
||||
return alloc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteOrder order() {
|
||||
return ByteOrder.BIG_ENDIAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasArray() {
|
||||
return false;
|
||||
@ -198,34 +221,40 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public byte getByte(int index) {
|
||||
assert !freed;
|
||||
return buffer.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort(int index) {
|
||||
assert !freed;
|
||||
return buffer.getShort(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnsignedMedium(int index) {
|
||||
assert !freed;
|
||||
return (getByte(index) & 0xff) << 16 | (getByte(index + 1) & 0xff) << 8 | getByte(index + 2) & 0xff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(int index) {
|
||||
assert !freed;
|
||||
return buffer.getInt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(int index) {
|
||||
assert !freed;
|
||||
return buffer.getLong(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||
if (dst instanceof DirectByteBuf) {
|
||||
DirectByteBuf bbdst = (DirectByteBuf) dst;
|
||||
ByteBuffer data = bbdst.tmpBuf;
|
||||
assert !freed;
|
||||
if (dst instanceof UnpooledDirectByteBuf) {
|
||||
UnpooledDirectByteBuf bbdst = (UnpooledDirectByteBuf) dst;
|
||||
ByteBuffer data = bbdst.internalNioBuffer();
|
||||
data.clear().position(dstIndex).limit(dstIndex + length);
|
||||
getBytes(index, data);
|
||||
} else if (buffer.hasArray()) {
|
||||
@ -238,6 +267,8 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
assert !freed;
|
||||
ByteBuffer tmpBuf = internalNioBuffer();
|
||||
try {
|
||||
tmpBuf.clear().position(index).limit(index + length);
|
||||
} catch (IllegalArgumentException e) {
|
||||
@ -250,7 +281,9 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||
assert !freed;
|
||||
int bytesToCopy = Math.min(capacity() - index, dst.remaining());
|
||||
ByteBuffer tmpBuf = internalNioBuffer();
|
||||
try {
|
||||
tmpBuf.clear().position(index).limit(index + bytesToCopy);
|
||||
} catch (IllegalArgumentException e) {
|
||||
@ -263,18 +296,21 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf setByte(int index, int value) {
|
||||
assert !freed;
|
||||
buffer.put(index, (byte) value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setShort(int index, int value) {
|
||||
assert !freed;
|
||||
buffer.putShort(index, (short) value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setMedium(int index, int value) {
|
||||
assert !freed;
|
||||
setByte(index, (byte) (value >>> 16));
|
||||
setByte(index + 1, (byte) (value >>> 8));
|
||||
setByte(index + 2, (byte) value);
|
||||
@ -283,21 +319,24 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf setInt(int index, int value) {
|
||||
assert !freed;
|
||||
buffer.putInt(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setLong(int index, long value) {
|
||||
assert !freed;
|
||||
buffer.putLong(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||
if (src instanceof DirectByteBuf) {
|
||||
DirectByteBuf bbsrc = (DirectByteBuf) src;
|
||||
ByteBuffer data = bbsrc.tmpBuf;
|
||||
assert !freed;
|
||||
if (src instanceof UnpooledDirectByteBuf) {
|
||||
UnpooledDirectByteBuf bbsrc = (UnpooledDirectByteBuf) src;
|
||||
ByteBuffer data = bbsrc.internalNioBuffer();
|
||||
|
||||
data.clear().position(srcIndex).limit(srcIndex + length);
|
||||
setBytes(index, data);
|
||||
@ -311,6 +350,8 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
assert !freed;
|
||||
ByteBuffer tmpBuf = internalNioBuffer();
|
||||
tmpBuf.clear().position(index).limit(index + length);
|
||||
tmpBuf.put(src, srcIndex, length);
|
||||
return this;
|
||||
@ -318,6 +359,8 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||
assert !freed;
|
||||
ByteBuffer tmpBuf = internalNioBuffer();
|
||||
if (src == tmpBuf) {
|
||||
src = src.duplicate();
|
||||
}
|
||||
@ -329,6 +372,7 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
|
||||
assert !freed;
|
||||
if (length == 0) {
|
||||
return this;
|
||||
}
|
||||
@ -337,6 +381,7 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
out.write(buffer.array(), index + buffer.arrayOffset(), length);
|
||||
} else {
|
||||
byte[] tmp = new byte[length];
|
||||
ByteBuffer tmpBuf = internalNioBuffer();
|
||||
tmpBuf.clear().position(index);
|
||||
tmpBuf.get(tmp);
|
||||
out.write(tmp);
|
||||
@ -346,33 +391,38 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
|
||||
assert !freed;
|
||||
if (length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ByteBuffer tmpBuf = internalNioBuffer();
|
||||
tmpBuf.clear().position(index).limit(index + length);
|
||||
return out.write(tmpBuf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBytes(int index, InputStream in, int length) throws IOException {
|
||||
|
||||
assert !freed;
|
||||
if (buffer.hasArray()) {
|
||||
return in.read(buffer.array(), buffer.arrayOffset() + index, length);
|
||||
} else {
|
||||
byte[] tmp = new byte[length];
|
||||
int readBytes = in.read(tmp);
|
||||
tmpBuf.clear().position(index);
|
||||
tmpBuf.put(tmp);
|
||||
ByteBuffer tmpNioBuf = internalNioBuffer();
|
||||
tmpNioBuf.clear().position(index);
|
||||
tmpNioBuf.put(tmp);
|
||||
return readBytes;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
|
||||
tmpBuf.clear().position(index).limit(index + length);
|
||||
assert !freed;
|
||||
ByteBuffer tmpNioBuf = internalNioBuffer();
|
||||
tmpNioBuf.clear().position(index).limit(index + length);
|
||||
try {
|
||||
return in.read(tmpBuf);
|
||||
return in.read(tmpNioBuf);
|
||||
} catch (ClosedChannelException e) {
|
||||
return -1;
|
||||
}
|
||||
@ -385,10 +435,11 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuffer nioBuffer(int index, int length) {
|
||||
assert !freed;
|
||||
if (index == 0 && length == capacity()) {
|
||||
return buffer.duplicate();
|
||||
} else {
|
||||
return ((ByteBuffer) tmpBuf.clear().position(index).limit(index + length)).slice();
|
||||
return ((ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length)).slice();
|
||||
}
|
||||
}
|
||||
|
||||
@ -404,9 +455,10 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf copy(int index, int length) {
|
||||
assert !freed;
|
||||
ByteBuffer src;
|
||||
try {
|
||||
src = (ByteBuffer) tmpBuf.clear().position(index).limit(index + length);
|
||||
src = (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IndexOutOfBoundsException("Too many bytes to read - Need " + (index + length));
|
||||
}
|
||||
@ -416,67 +468,52 @@ public class DirectByteBuf extends AbstractByteBuf {
|
||||
dst.put(src);
|
||||
dst.order(order());
|
||||
dst.clear();
|
||||
return new DirectByteBuf(dst, maxCapacity());
|
||||
return new UnpooledDirectByteBuf(alloc(), dst, maxCapacity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unsafe unsafe() {
|
||||
return unsafe;
|
||||
public ByteBuffer internalNioBuffer() {
|
||||
ByteBuffer tmpNioBuf = this.tmpNioBuf;
|
||||
if (tmpNioBuf == null) {
|
||||
this.tmpNioBuf = tmpNioBuf = buffer.duplicate();
|
||||
}
|
||||
return tmpNioBuf;
|
||||
}
|
||||
|
||||
private class DirectUnsafe implements Unsafe {
|
||||
@Override
|
||||
public ByteBuffer nioBuffer() {
|
||||
return tmpBuf;
|
||||
@Override
|
||||
public ByteBuffer[] internalNioBuffers() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void discardSomeReadBytes() {
|
||||
final int readerIndex = readerIndex();
|
||||
if (readerIndex == writerIndex()) {
|
||||
discardReadBytes();
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] nioBuffers() {
|
||||
throw new UnsupportedOperationException();
|
||||
if (readerIndex > 0 && readerIndex >= capacity >>> 1) {
|
||||
discardReadBytes();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free() {
|
||||
if (freed) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf newBuffer(int initialCapacity) {
|
||||
return new DirectByteBuf(initialCapacity, Math.max(initialCapacity, maxCapacity()));
|
||||
freed = true;
|
||||
if (doNotFree) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void discardSomeReadBytes() {
|
||||
final int readerIndex = readerIndex();
|
||||
if (readerIndex == writerIndex()) {
|
||||
discardReadBytes();
|
||||
return;
|
||||
}
|
||||
freeDirect(buffer);
|
||||
}
|
||||
|
||||
if (readerIndex > 0 && readerIndex >= capacity >>> 1) {
|
||||
discardReadBytes();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acquire() {
|
||||
if (refCnt <= 0) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
refCnt ++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
if (refCnt <= 0) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
refCnt --;
|
||||
if (refCnt == 0) {
|
||||
if (doNotFree) {
|
||||
doNotFree = false;
|
||||
} else {
|
||||
freeDirect(buffer);
|
||||
}
|
||||
|
||||
buffer = null;
|
||||
tmpBuf = null;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public ByteBuf unwrap() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -27,12 +27,12 @@ import java.nio.channels.ScatteringByteChannel;
|
||||
/**
|
||||
* Big endian Java heap buffer implementation.
|
||||
*/
|
||||
public class HeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
private final Unsafe unsafe = new HeapUnsafe();
|
||||
public class UnpooledHeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
private final ByteBufAllocator alloc;
|
||||
private byte[] array;
|
||||
private ByteBuffer nioBuf;
|
||||
private ByteBuffer tmpNioBuf;
|
||||
private boolean freed;
|
||||
|
||||
/**
|
||||
* Creates a new heap buffer with a newly allocated byte array.
|
||||
@ -40,8 +40,8 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
* @param initialCapacity the initial capacity of the underlying byte array
|
||||
* @param maxCapacity the max capacity of the underlying byte array
|
||||
*/
|
||||
public HeapByteBuf(int initialCapacity, int maxCapacity) {
|
||||
this(new byte[initialCapacity], 0, 0, maxCapacity);
|
||||
public UnpooledHeapByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
|
||||
this(alloc, new byte[initialCapacity], 0, 0, maxCapacity);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -50,12 +50,18 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
* @param initialArray the initial underlying byte array
|
||||
* @param maxCapacity the max capacity of the underlying byte array
|
||||
*/
|
||||
public HeapByteBuf(byte[] initialArray, int maxCapacity) {
|
||||
this(initialArray, 0, initialArray.length, maxCapacity);
|
||||
public UnpooledHeapByteBuf(ByteBufAllocator alloc, byte[] initialArray, int maxCapacity) {
|
||||
this(alloc, initialArray, 0, initialArray.length, maxCapacity);
|
||||
}
|
||||
|
||||
private HeapByteBuf(byte[] initialArray, int readerIndex, int writerIndex, int maxCapacity) {
|
||||
super(ByteOrder.BIG_ENDIAN, maxCapacity);
|
||||
private UnpooledHeapByteBuf(
|
||||
ByteBufAllocator alloc, byte[] initialArray, int readerIndex, int writerIndex, int maxCapacity) {
|
||||
|
||||
super(maxCapacity);
|
||||
|
||||
if (alloc == null) {
|
||||
throw new NullPointerException("alloc");
|
||||
}
|
||||
if (initialArray == null) {
|
||||
throw new NullPointerException("initialArray");
|
||||
}
|
||||
@ -64,13 +70,24 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
"initialCapacity(%d) > maxCapacity(%d)", initialArray.length, maxCapacity));
|
||||
}
|
||||
|
||||
this.alloc = alloc;
|
||||
setArray(initialArray);
|
||||
setIndex(readerIndex, writerIndex);
|
||||
}
|
||||
|
||||
private void setArray(byte[] initialArray) {
|
||||
array = initialArray;
|
||||
nioBuf = ByteBuffer.wrap(initialArray);
|
||||
tmpNioBuf = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufAllocator alloc() {
|
||||
return alloc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteOrder order() {
|
||||
return ByteOrder.BIG_ENDIAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -85,6 +102,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf capacity(int newCapacity) {
|
||||
assert !freed;
|
||||
if (newCapacity < 0 || newCapacity > maxCapacity()) {
|
||||
throw new IllegalArgumentException("newCapacity: " + newCapacity);
|
||||
}
|
||||
@ -118,6 +136,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public byte[] array() {
|
||||
assert !freed;
|
||||
return array;
|
||||
}
|
||||
|
||||
@ -128,13 +147,15 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public byte getByte(int index) {
|
||||
assert !freed;
|
||||
return array[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||
if (dst instanceof HeapByteBuf) {
|
||||
getBytes(index, ((HeapByteBuf) dst).array, dstIndex, length);
|
||||
assert !freed;
|
||||
if (dst instanceof UnpooledHeapByteBuf) {
|
||||
getBytes(index, ((UnpooledHeapByteBuf) dst).array, dstIndex, length);
|
||||
} else {
|
||||
dst.setBytes(dstIndex, array, index, length);
|
||||
}
|
||||
@ -143,39 +164,43 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
assert !freed;
|
||||
System.arraycopy(array, index, dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||
assert !freed;
|
||||
dst.put(array, index, Math.min(capacity() - index, dst.remaining()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, OutputStream out, int length)
|
||||
throws IOException {
|
||||
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
|
||||
assert !freed;
|
||||
out.write(array, index, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBytes(int index, GatheringByteChannel out, int length)
|
||||
throws IOException {
|
||||
return out.write((ByteBuffer) nioBuf.clear().position(index).limit(index + length));
|
||||
public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
|
||||
assert !freed;
|
||||
return out.write((ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setByte(int index, int value) {
|
||||
assert !freed;
|
||||
array[index] = (byte) value;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||
if (src instanceof HeapByteBuf) {
|
||||
setBytes(index, ((HeapByteBuf) src).array, srcIndex, length);
|
||||
assert !freed;
|
||||
if (src instanceof UnpooledHeapByteBuf) {
|
||||
setBytes(index, ((UnpooledHeapByteBuf) src).array, srcIndex, length);
|
||||
} else {
|
||||
src.getBytes(srcIndex, array, index, length);
|
||||
}
|
||||
@ -184,25 +209,29 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
assert !freed;
|
||||
System.arraycopy(src, srcIndex, array, index, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||
assert !freed;
|
||||
src.get(array, index, src.remaining());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBytes(int index, InputStream in, int length) throws IOException {
|
||||
assert !freed;
|
||||
return in.read(array, index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
|
||||
assert !freed;
|
||||
try {
|
||||
return in.read((ByteBuffer) nioBuf.clear().position(index).limit(index + length));
|
||||
return in.read((ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length));
|
||||
} catch (ClosedChannelException e) {
|
||||
return -1;
|
||||
}
|
||||
@ -215,6 +244,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuffer nioBuffer(int index, int length) {
|
||||
assert !freed;
|
||||
return ByteBuffer.wrap(array, index, length);
|
||||
}
|
||||
|
||||
@ -230,11 +260,13 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public short getShort(int index) {
|
||||
assert !freed;
|
||||
return (short) (array[index] << 8 | array[index + 1] & 0xFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnsignedMedium(int index) {
|
||||
assert !freed;
|
||||
return (array[index] & 0xff) << 16 |
|
||||
(array[index + 1] & 0xff) << 8 |
|
||||
array[index + 2] & 0xff;
|
||||
@ -242,6 +274,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public int getInt(int index) {
|
||||
assert !freed;
|
||||
return (array[index] & 0xff) << 24 |
|
||||
(array[index + 1] & 0xff) << 16 |
|
||||
(array[index + 2] & 0xff) << 8 |
|
||||
@ -250,6 +283,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public long getLong(int index) {
|
||||
assert !freed;
|
||||
return ((long) array[index] & 0xff) << 56 |
|
||||
((long) array[index + 1] & 0xff) << 48 |
|
||||
((long) array[index + 2] & 0xff) << 40 |
|
||||
@ -262,6 +296,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf setShort(int index, int value) {
|
||||
assert !freed;
|
||||
array[index] = (byte) (value >>> 8);
|
||||
array[index + 1] = (byte) value;
|
||||
return this;
|
||||
@ -269,6 +304,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf setMedium(int index, int value) {
|
||||
assert !freed;
|
||||
array[index] = (byte) (value >>> 16);
|
||||
array[index + 1] = (byte) (value >>> 8);
|
||||
array[index + 2] = (byte) value;
|
||||
@ -277,6 +313,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf setInt(int index, int value) {
|
||||
assert !freed;
|
||||
array[index] = (byte) (value >>> 24);
|
||||
array[index + 1] = (byte) (value >>> 16);
|
||||
array[index + 2] = (byte) (value >>> 8);
|
||||
@ -286,6 +323,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf setLong(int index, long value) {
|
||||
assert !freed;
|
||||
array[index] = (byte) (value >>> 56);
|
||||
array[index + 1] = (byte) (value >>> 48);
|
||||
array[index + 2] = (byte) (value >>> 40);
|
||||
@ -299,6 +337,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf copy(int index, int length) {
|
||||
assert !freed;
|
||||
if (index < 0 || length < 0 || index + length > array.length) {
|
||||
throw new IndexOutOfBoundsException("Too many bytes to copy - Need "
|
||||
+ (index + length) + ", maximum is " + array.length);
|
||||
@ -306,61 +345,43 @@ public class HeapByteBuf extends AbstractByteBuf {
|
||||
|
||||
byte[] copiedArray = new byte[length];
|
||||
System.arraycopy(array, index, copiedArray, 0, length);
|
||||
return new HeapByteBuf(copiedArray, maxCapacity());
|
||||
return new UnpooledHeapByteBuf(alloc(), copiedArray, maxCapacity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unsafe unsafe() {
|
||||
return unsafe;
|
||||
public ByteBuffer internalNioBuffer() {
|
||||
ByteBuffer tmpNioBuf = this.tmpNioBuf;
|
||||
if (tmpNioBuf == null) {
|
||||
this.tmpNioBuf = tmpNioBuf = ByteBuffer.wrap(array);
|
||||
}
|
||||
return tmpNioBuf;
|
||||
}
|
||||
|
||||
private class HeapUnsafe implements Unsafe {
|
||||
@Override
|
||||
public ByteBuffer nioBuffer() {
|
||||
return nioBuf;
|
||||
@Override
|
||||
public ByteBuffer[] internalNioBuffers() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void discardSomeReadBytes() {
|
||||
final int readerIndex = readerIndex();
|
||||
if (readerIndex == writerIndex()) {
|
||||
discardReadBytes();
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] nioBuffers() {
|
||||
throw new UnsupportedOperationException();
|
||||
if (readerIndex > 0 && readerIndex >= capacity() >>> 1) {
|
||||
discardReadBytes();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf newBuffer(int initialCapacity) {
|
||||
return new HeapByteBuf(initialCapacity, Math.max(initialCapacity, maxCapacity()));
|
||||
}
|
||||
@Override
|
||||
public void free() {
|
||||
freed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void discardSomeReadBytes() {
|
||||
final int readerIndex = readerIndex();
|
||||
if (readerIndex == writerIndex()) {
|
||||
discardReadBytes();
|
||||
return;
|
||||
}
|
||||
|
||||
if (readerIndex > 0 && readerIndex >= capacity() >>> 1) {
|
||||
discardReadBytes();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acquire() {
|
||||
if (refCnt <= 0) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
refCnt ++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
if (refCnt <= 0) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
refCnt --;
|
||||
if (refCnt == 0) {
|
||||
array = null;
|
||||
nioBuf = null;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public ByteBuf unwrap() {
|
||||
return null;
|
||||
}
|
||||
}
|
57
buffer/src/main/java/io/netty/buffer/UnsafeByteBuf.java
Normal file
57
buffer/src/main/java/io/netty/buffer/UnsafeByteBuf.java
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 java.nio.ByteBuffer;
|
||||
|
||||
public interface UnsafeByteBuf extends ByteBuf {
|
||||
|
||||
/**
|
||||
* Returns the internal NIO buffer that is reused for I/O.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the buffer has no internal NIO buffer
|
||||
*/
|
||||
ByteBuffer internalNioBuffer();
|
||||
|
||||
/**
|
||||
* Returns the internal NIO buffer array that is reused for I/O.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the buffer has no internal NIO buffer array
|
||||
*/
|
||||
ByteBuffer[] internalNioBuffers();
|
||||
|
||||
/**
|
||||
* Similar to {@link ByteBuf#discardReadBytes()} except that this method might discard
|
||||
* some, all, or none of read bytes depending on its internal implementation to reduce
|
||||
* overall memory bandwidth consumption at the cost of potentially additional memory
|
||||
* consumption.
|
||||
*/
|
||||
void discardSomeReadBytes();
|
||||
|
||||
/**
|
||||
* Deallocates the internal memory block of this buffer or returns it to the {@link ByteBufAllocator} it came
|
||||
* from. The result of accessing a released buffer is unspecified and can even cause JVM crash.
|
||||
*/
|
||||
void free();
|
||||
|
||||
/**
|
||||
* Return the underlying buffer instance if this buffer is a wrapper.
|
||||
*
|
||||
* @return {@code null} if this buffer is not a wrapper
|
||||
*/
|
||||
ByteBuf unwrap();
|
||||
}
|
@ -1,205 +0,0 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* The common interface for buffer wrappers and derived buffers. Most users won't
|
||||
* need to use this interface. It is used internally in most cases.
|
||||
*/
|
||||
public interface WrappedByteBuf extends ByteBuf {
|
||||
/**
|
||||
* Returns this buffer's parent that this buffer is wrapping.
|
||||
*/
|
||||
ByteBuf unwrap();
|
||||
|
||||
@Override
|
||||
WrappedByteBuf capacity(int newCapacity);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf readerIndex(int readerIndex);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writerIndex(int writerIndex);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setIndex(int readerIndex, int writerIndex);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf clear();
|
||||
|
||||
@Override
|
||||
WrappedByteBuf markReaderIndex();
|
||||
|
||||
@Override
|
||||
WrappedByteBuf resetReaderIndex();
|
||||
|
||||
@Override
|
||||
WrappedByteBuf markWriterIndex();
|
||||
|
||||
@Override
|
||||
WrappedByteBuf resetWriterIndex();
|
||||
|
||||
@Override
|
||||
WrappedByteBuf discardReadBytes();
|
||||
|
||||
@Override
|
||||
WrappedByteBuf ensureWritableBytes(int minWritableBytes);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf getBytes(int index, ByteBuf dst);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf getBytes(int index, ByteBuf dst, int length);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf getBytes(int index, byte[] dst);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf getBytes(int index, byte[] dst, int dstIndex, int length);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf getBytes(int index, ByteBuffer dst);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf getBytes(int index, OutputStream out, int length) throws IOException;
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setBoolean(int index, boolean value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setByte(int index, int value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setShort(int index, int value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setMedium(int index, int value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setInt(int index, int value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setLong(int index, long value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setChar(int index, int value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setFloat(int index, float value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setDouble(int index, double value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setBytes(int index, ByteBuf src);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setBytes(int index, ByteBuf src, int length);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setBytes(int index, byte[] src);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setBytes(int index, byte[] src, int srcIndex, int length);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setBytes(int index, ByteBuffer src);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf setZero(int index, int length);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf readBytes(ByteBuf dst);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf readBytes(ByteBuf dst, int length);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf readBytes(ByteBuf dst, int dstIndex, int length);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf readBytes(byte[] dst);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf readBytes(byte[] dst, int dstIndex, int length);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf readBytes(ByteBuffer dst);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf readBytes(OutputStream out, int length) throws IOException;
|
||||
|
||||
@Override
|
||||
WrappedByteBuf skipBytes(int length);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writeBoolean(boolean value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writeByte(int value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writeShort(int value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writeMedium(int value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writeInt(int value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writeLong(long value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writeChar(int value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writeFloat(float value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writeDouble(double value);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writeBytes(ByteBuf src);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writeBytes(ByteBuf src, int length);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writeBytes(ByteBuf src, int srcIndex, int length);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writeBytes(byte[] src);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writeBytes(byte[] src, int srcIndex, int length);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writeBytes(ByteBuffer src);
|
||||
|
||||
@Override
|
||||
WrappedByteBuf writeZero(int length);
|
||||
}
|
@ -15,10 +15,10 @@
|
||||
*/
|
||||
package io.netty.buffer;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests big-endian heap channel buffers
|
||||
*/
|
||||
@ -39,7 +39,12 @@ public class BigEndianHeapChannelBufferTest extends AbstractChannelBufferTest {
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void shouldNotAllowNullInConstructor() {
|
||||
new HeapByteBuf(null, 0);
|
||||
public void shouldNotAllowNullInConstructor1() {
|
||||
new UnpooledHeapByteBuf(null, new byte[1], 0);
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void shouldNotAllowNullInConstructor2() {
|
||||
new UnpooledHeapByteBuf(UnpooledByteBufAllocator.HEAP_BY_DEFAULT, null, 0);
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,10 @@
|
||||
*/
|
||||
package io.netty.buffer;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests duplicated channel buffers
|
||||
*/
|
||||
@ -28,7 +28,7 @@ public class DuplicateChannelBufferTest extends AbstractChannelBufferTest {
|
||||
|
||||
@Override
|
||||
protected ByteBuf newBuffer(int length) {
|
||||
buffer = new DuplicatedByteBuf(Unpooled.buffer(length));
|
||||
buffer = new DuplicatedByteBuf((UnsafeByteBuf) Unpooled.buffer(length));
|
||||
assertEquals(0, buffer.writerIndex());
|
||||
return buffer;
|
||||
}
|
||||
|
@ -15,9 +15,7 @@
|
||||
*/
|
||||
package io.netty.buffer;
|
||||
|
||||
import static io.netty.buffer.Unpooled.*;
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -26,7 +24,9 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
|
||||
import org.junit.Test;
|
||||
import static io.netty.buffer.Unpooled.*;
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests read-only channel buffers
|
||||
@ -46,7 +46,7 @@ public class ReadOnlyChannelBufferTest {
|
||||
@Test
|
||||
public void testUnwrap() {
|
||||
ByteBuf buf = buffer(1);
|
||||
assertSame(buf, ((WrappedByteBuf) Unpooled.unmodifiableBuffer(buf)).unwrap());
|
||||
assertSame(buf, ((UnsafeByteBuf) Unpooled.unmodifiableBuffer(buf)).unwrap());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -74,7 +74,7 @@ public class ReadOnlyChannelBufferTest {
|
||||
|
||||
@Test
|
||||
public void shouldForwardReadCallsBlindly() throws Exception {
|
||||
ByteBuf buf = createStrictMock(ByteBuf.class);
|
||||
ByteBuf buf = createStrictMock(UnsafeByteBuf.class);
|
||||
expect(buf.order()).andReturn(BIG_ENDIAN).anyTimes();
|
||||
expect(buf.maxCapacity()).andReturn(65536).anyTimes();
|
||||
expect(buf.readerIndex()).andReturn(0).anyTimes();
|
||||
|
@ -16,7 +16,6 @@
|
||||
package io.netty.handler.codec.spdy;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerAdapter;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
@ -64,7 +63,7 @@ public abstract class SpdyOrHttpChooser extends ChannelHandlerAdapter implements
|
||||
|
||||
@Override
|
||||
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||
return Unpooled.buffer();
|
||||
return ctx.alloc().buffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.handler.codec.spdy;
|
||||
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.MessageBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
@ -95,6 +96,16 @@ public class SpdySessionHandler
|
||||
return Unpooled.messageBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
||||
MessageBuf<Object> in = ctx.inboundMessageBuffer();
|
||||
|
@ -16,6 +16,7 @@
|
||||
package io.netty.handler.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.UnsafeByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundByteHandlerAdapter;
|
||||
|
||||
@ -70,7 +71,7 @@ public abstract class ByteToByteDecoder extends ChannelInboundByteHandlerAdapter
|
||||
}
|
||||
}
|
||||
|
||||
in.unsafe().discardSomeReadBytes();
|
||||
((UnsafeByteBuf) in).discardSomeReadBytes();
|
||||
if (out.readableBytes() > oldOutSize) {
|
||||
ctx.fireInboundBufferUpdated();
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
package io.netty.handler.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.UnsafeByteBuf;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelOutboundByteHandlerAdapter;
|
||||
@ -43,7 +44,7 @@ public abstract class ByteToByteEncoder extends ChannelOutboundByteHandlerAdapte
|
||||
}
|
||||
}
|
||||
|
||||
in.unsafe().discardSomeReadBytes();
|
||||
((UnsafeByteBuf) in).discardSomeReadBytes();
|
||||
ctx.flush(future);
|
||||
}
|
||||
|
||||
|
@ -16,12 +16,13 @@
|
||||
package io.netty.handler.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.UnsafeByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelHandlerUtil;
|
||||
import io.netty.channel.ChannelInboundByteHandler;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.ChannelHandlerUtil;
|
||||
|
||||
public abstract class ByteToMessageDecoder<O>
|
||||
extends ChannelInboundHandlerAdapter implements ChannelInboundByteHandler {
|
||||
@ -36,7 +37,12 @@ public abstract class ByteToMessageDecoder<O>
|
||||
|
||||
@Override
|
||||
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||
return Unpooled.buffer();
|
||||
return ctx.alloc().buffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
((UnsafeByteBuf) buf).free();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -92,7 +98,7 @@ public abstract class ByteToMessageDecoder<O>
|
||||
break;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
in.unsafe().discardSomeReadBytes();
|
||||
((UnsafeByteBuf) in).discardSomeReadBytes();
|
||||
|
||||
if (decoded) {
|
||||
decoded = false;
|
||||
@ -107,7 +113,7 @@ public abstract class ByteToMessageDecoder<O>
|
||||
}
|
||||
}
|
||||
|
||||
in.unsafe().discardSomeReadBytes();
|
||||
((UnsafeByteBuf) in).discardSomeReadBytes();
|
||||
|
||||
if (decoded) {
|
||||
ctx.fireInboundBufferUpdated();
|
||||
|
@ -16,7 +16,6 @@
|
||||
package io.netty.handler.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
/**
|
||||
@ -68,7 +67,7 @@ public class FixedLengthFrameDecoder extends ByteToMessageDecoder<Object> {
|
||||
@Override
|
||||
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||
if (allocateFullBuffer) {
|
||||
return Unpooled.buffer(frameLength);
|
||||
return ctx.alloc().buffer(frameLength);
|
||||
} else {
|
||||
return super.newInboundBuffer(ctx);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
package io.netty.handler.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.serialization.ObjectDecoder;
|
||||
|
||||
@ -426,7 +427,7 @@ public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder<Object> {
|
||||
* is overridden to avoid memory copy.
|
||||
*/
|
||||
protected ByteBuf extractFrame(ByteBuf buffer, int index, int length) {
|
||||
ByteBuf frame = buffer.unsafe().newBuffer(length);
|
||||
ByteBuf frame = Unpooled.buffer(length);
|
||||
frame.writeBytes(buffer, index, length);
|
||||
return frame;
|
||||
}
|
||||
|
@ -15,13 +15,14 @@
|
||||
*/
|
||||
package io.netty.handler.codec;
|
||||
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.MessageBuf;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerAdapter;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelHandlerUtil;
|
||||
import io.netty.channel.ChannelInboundMessageHandler;
|
||||
import io.netty.channel.ChannelOutboundMessageHandler;
|
||||
import io.netty.channel.ChannelHandlerUtil;
|
||||
|
||||
public abstract class MessageToMessageCodec<INBOUND_IN, INBOUND_OUT, OUTBOUND_IN, OUTBOUND_OUT>
|
||||
extends ChannelHandlerAdapter
|
||||
@ -72,6 +73,11 @@ public abstract class MessageToMessageCodec<INBOUND_IN, INBOUND_OUT, OUTBOUND_IN
|
||||
return decoder.newInboundBuffer(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundBufferUpdated(
|
||||
ChannelHandlerContext ctx) throws Exception {
|
||||
@ -83,6 +89,11 @@ public abstract class MessageToMessageCodec<INBOUND_IN, INBOUND_OUT, OUTBOUND_IN
|
||||
return encoder.newOutboundBuffer(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush(ChannelHandlerContext ctx, ChannelFuture future) throws Exception {
|
||||
encoder.flush(ctx, future);
|
||||
|
@ -15,12 +15,13 @@
|
||||
*/
|
||||
package io.netty.handler.codec;
|
||||
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.MessageBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelHandlerUtil;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelInboundMessageHandler;
|
||||
import io.netty.channel.ChannelHandlerUtil;
|
||||
|
||||
public abstract class MessageToMessageDecoder<I, O>
|
||||
extends ChannelInboundHandlerAdapter implements ChannelInboundMessageHandler<I> {
|
||||
@ -36,6 +37,11 @@ public abstract class MessageToMessageDecoder<I, O>
|
||||
return Unpooled.messageBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundBufferUpdated(ChannelHandlerContext ctx)
|
||||
throws Exception {
|
||||
|
@ -16,12 +16,12 @@
|
||||
package io.netty.handler.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.UnsafeByteBuf;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.ChannelHandlerUtil;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.util.internal.Signal;
|
||||
|
||||
/**
|
||||
@ -282,8 +282,8 @@ public abstract class ReplayingDecoder<O, S> extends ByteToMessageDecoder<O> {
|
||||
|
||||
static final Signal REPLAY = new Signal(ReplayingDecoder.class.getName() + ".REPLAY");
|
||||
|
||||
private final ByteBuf cumulation = Unpooled.buffer();
|
||||
private final ReplayingDecoderBuffer replayable = new ReplayingDecoderBuffer(cumulation);
|
||||
private ByteBuf cumulation;
|
||||
private ReplayingDecoderBuffer replayable;
|
||||
private S state;
|
||||
private int checkpoint = -1;
|
||||
|
||||
@ -357,6 +357,8 @@ public abstract class ReplayingDecoder<O, S> extends ByteToMessageDecoder<O> {
|
||||
@Override
|
||||
public ByteBuf newInboundBuffer(
|
||||
ChannelHandlerContext ctx) throws Exception {
|
||||
cumulation = ctx.alloc().buffer();
|
||||
replayable = new ReplayingDecoderBuffer(cumulation);
|
||||
return cumulation;
|
||||
}
|
||||
|
||||
@ -457,7 +459,7 @@ public abstract class ReplayingDecoder<O, S> extends ByteToMessageDecoder<O> {
|
||||
|
||||
private void fireInboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in) {
|
||||
final int oldReaderIndex = in.readerIndex();
|
||||
in.unsafe().discardSomeReadBytes();
|
||||
((UnsafeByteBuf) in).discardSomeReadBytes();
|
||||
final int newReaderIndex = in.readerIndex();
|
||||
checkpoint -= oldReaderIndex - newReaderIndex;
|
||||
ctx.fireInboundBufferUpdated();
|
||||
|
@ -16,10 +16,12 @@
|
||||
package io.netty.handler.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.buffer.ByteBufIndexFinder;
|
||||
import io.netty.buffer.ChannelBufType;
|
||||
import io.netty.buffer.SwappedByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.UnsafeByteBuf;
|
||||
import io.netty.util.internal.Signal;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -31,7 +33,7 @@ import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
class ReplayingDecoderBuffer implements ByteBuf {
|
||||
class ReplayingDecoderBuffer implements UnsafeByteBuf {
|
||||
|
||||
private static final Signal REPLAY = ReplayingDecoder.REPLAY;
|
||||
|
||||
@ -79,8 +81,8 @@ class ReplayingDecoderBuffer implements ByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPooled() {
|
||||
return false;
|
||||
public ByteBufAllocator alloc() {
|
||||
return buffer.alloc();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -849,7 +851,27 @@ class ReplayingDecoderBuffer implements ByteBuf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unsafe unsafe() {
|
||||
public ByteBuffer internalNioBuffer() {
|
||||
throw new UnreplayableOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] internalNioBuffers() {
|
||||
throw new UnreplayableOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void discardSomeReadBytes() {
|
||||
throw new UnreplayableOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free() {
|
||||
throw new UnreplayableOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf unwrap() {
|
||||
throw new UnreplayableOperationException();
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package io.netty.handler.codec.base64;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
/**
|
||||
* Utility class for {@link ByteBuf} that encodes and decodes to and from
|
||||
@ -115,10 +116,10 @@ public final class Base64 {
|
||||
}
|
||||
|
||||
int len43 = len * 4 / 3;
|
||||
ByteBuf dest = src.unsafe().newBuffer(
|
||||
ByteBuf dest = Unpooled.buffer(
|
||||
len43 +
|
||||
(len % 3 > 0? 4 : 0) + // Account for padding
|
||||
(breakLines? len43 / MAX_LINE_LENGTH : 0)).order(src.order()); // New lines
|
||||
(len % 3 > 0 ? 4 : 0) + // Account for padding
|
||||
(breakLines ? len43 / MAX_LINE_LENGTH : 0)).order(src.order()); // New lines
|
||||
int d = 0;
|
||||
int e = 0;
|
||||
int len2 = len - 2;
|
||||
@ -219,7 +220,7 @@ public final class Base64 {
|
||||
byte[] DECODABET = decodabet(dialect);
|
||||
|
||||
int len34 = len * 3 / 4;
|
||||
ByteBuf dest = src.unsafe().newBuffer(len34).order(src.order()); // Upper limit on size of output
|
||||
ByteBuf dest = Unpooled.buffer(len34).order(src.order()); // Upper limit on size of output
|
||||
int outBuffPosn = 0;
|
||||
|
||||
byte[] b4 = new byte[4];
|
||||
|
@ -17,6 +17,7 @@ package io.netty.handler.codec.serialization;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufOutputStream;
|
||||
import io.netty.buffer.UnsafeByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import io.netty.util.Attribute;
|
||||
@ -97,7 +98,7 @@ public class CompatibleObjectEncoder extends MessageToByteEncoder<Object> {
|
||||
oos.reset();
|
||||
|
||||
// Also discard the byproduct to avoid OOM on the sending side.
|
||||
out.unsafe().discardSomeReadBytes();
|
||||
((UnsafeByteBuf) out).discardSomeReadBytes();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,8 +15,12 @@
|
||||
*/
|
||||
package io.netty.util.internal;
|
||||
|
||||
import sun.misc.Cleaner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
@ -38,11 +42,11 @@ public final class DetectionUtil {
|
||||
|
||||
private static final int JAVA_VERSION = javaVersion0();
|
||||
private static final boolean HAS_UNSAFE = hasUnsafe(AtomicInteger.class.getClassLoader());
|
||||
private static final boolean CAN_FREE_DIRECT_BUFFER;
|
||||
private static final boolean IS_WINDOWS;
|
||||
private static final boolean IS_ROOT;
|
||||
|
||||
static {
|
||||
|
||||
Pattern PERMISSION_DENIED = Pattern.compile(".*permission.*denied.*");
|
||||
String os = SystemPropertyUtil.get("os.name", "").toLowerCase(Locale.UK);
|
||||
// windows
|
||||
@ -82,6 +86,21 @@ public final class DetectionUtil {
|
||||
}
|
||||
|
||||
IS_ROOT = root;
|
||||
|
||||
boolean canFreeDirectBuffer = false;
|
||||
|
||||
try {
|
||||
ByteBuffer direct = ByteBuffer.allocateDirect(1);
|
||||
Field cleanerField = direct.getClass().getDeclaredField("cleaner");
|
||||
cleanerField.setAccessible(true);
|
||||
Cleaner cleaner = (Cleaner) cleanerField.get(direct);
|
||||
cleaner.clean();
|
||||
canFreeDirectBuffer = true;
|
||||
} catch (Throwable t) {
|
||||
// Ignore.
|
||||
}
|
||||
|
||||
CAN_FREE_DIRECT_BUFFER = canFreeDirectBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,6 +126,10 @@ public final class DetectionUtil {
|
||||
return JAVA_VERSION;
|
||||
}
|
||||
|
||||
public static boolean canFreeDirectBuffer() {
|
||||
return CAN_FREE_DIRECT_BUFFER;
|
||||
}
|
||||
|
||||
private static boolean hasUnsafe(ClassLoader loader) {
|
||||
boolean noUnsafe = SystemPropertyUtil.getBoolean("io.netty.noUnsafe", false);
|
||||
if (noUnsafe) {
|
||||
|
@ -16,7 +16,8 @@
|
||||
package io.netty.handler.logging;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.UnsafeByteBuf;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundByteHandler;
|
||||
@ -108,12 +109,22 @@ public class ByteLoggingHandler
|
||||
}
|
||||
@Override
|
||||
public ByteBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||
return Unpooled.buffer();
|
||||
return ctx.alloc().buffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||
return Unpooled.buffer();
|
||||
return ctx.alloc().buffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
((UnsafeByteBuf) buf).free();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
((UnsafeByteBuf) buf).free();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.handler.logging;
|
||||
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.MessageBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
@ -57,6 +58,16 @@ public class MessageLoggingHandler
|
||||
return Unpooled.messageBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundBufferUpdated(ChannelHandlerContext ctx)
|
||||
throws Exception {
|
||||
|
@ -17,7 +17,8 @@ package io.netty.handler.ssl;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.UnsafeByteBuf;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFlushFutureNotifier;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
@ -32,6 +33,10 @@ import io.netty.logging.InternalLogger;
|
||||
import io.netty.logging.InternalLoggerFactory;
|
||||
import io.netty.util.internal.DetectionUtil;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLEngineResult;
|
||||
import javax.net.ssl.SSLEngineResult.Status;
|
||||
import javax.net.ssl.SSLException;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
@ -44,11 +49,6 @@ import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLEngineResult;
|
||||
import javax.net.ssl.SSLEngineResult.Status;
|
||||
import javax.net.ssl.SSLException;
|
||||
|
||||
/**
|
||||
* Adds <a href="http://en.wikipedia.org/wiki/Transport_Layer_Security">SSL
|
||||
* · TLS</a> and StartTLS support to a {@link Channel}. Please refer
|
||||
@ -376,12 +376,22 @@ public class SslHandler
|
||||
|
||||
@Override
|
||||
public ByteBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||
return Unpooled.buffer();
|
||||
return ctx.alloc().buffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||
return Unpooled.buffer();
|
||||
return ctx.alloc().buffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
((UnsafeByteBuf) buf).free();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
((UnsafeByteBuf) buf).free();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -401,7 +411,7 @@ public class SslHandler
|
||||
final ByteBuf in = ctx.outboundByteBuffer();
|
||||
final ByteBuf out = ctx.nextOutboundByteBuffer();
|
||||
|
||||
out.unsafe().discardSomeReadBytes();
|
||||
((UnsafeByteBuf) out).discardSomeReadBytes();
|
||||
|
||||
// Do not encrypt the first write request if this handler is
|
||||
// created with startTLS flag turned on.
|
||||
@ -473,7 +483,7 @@ public class SslHandler
|
||||
setHandshakeFailure(e);
|
||||
throw e;
|
||||
} finally {
|
||||
in.unsafe().discardSomeReadBytes();
|
||||
((UnsafeByteBuf) in).discardSomeReadBytes();
|
||||
flush0(ctx, bytesConsumed);
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.handler.stream;
|
||||
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.MessageBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.Channel;
|
||||
@ -95,6 +96,11 @@ public class ChunkedWriteHandler
|
||||
return queue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
private boolean isWritable() {
|
||||
return pendingWrites.get() < maxPendingWrites;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.bootstrap;
|
||||
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.MessageBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.Channel;
|
||||
@ -229,6 +230,11 @@ public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap> {
|
||||
return Unpooled.messageBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void inboundBufferUpdated(ChannelHandlerContext ctx) {
|
||||
|
@ -16,6 +16,7 @@
|
||||
package io.netty.channel;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.buffer.MessageBuf;
|
||||
import io.netty.logging.InternalLogger;
|
||||
import io.netty.logging.InternalLoggerFactory;
|
||||
@ -146,6 +147,11 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufAllocator alloc() {
|
||||
return config().getAllocator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventLoop eventLoop() {
|
||||
EventLoop eventLoop = this.eventLoop;
|
||||
|
@ -106,7 +106,7 @@ import java.nio.channels.SelectionKey;
|
||||
*
|
||||
* @apiviz.exclude ^io\.netty\.channel\.([a-z]+\.)+[^\.]+Channel$
|
||||
*/
|
||||
public interface Channel extends AttributeMap, ChannelOutboundInvoker, ChannelFutureFactory, Comparable<Channel> {
|
||||
public interface Channel extends AttributeMap, ChannelOutboundInvoker, ChannelPropertyAccess, Comparable<Channel> {
|
||||
|
||||
/**
|
||||
* Returns the unique integer ID of this channel.
|
||||
@ -131,12 +131,6 @@ public interface Channel extends AttributeMap, ChannelOutboundInvoker, ChannelFu
|
||||
*/
|
||||
ChannelConfig config();
|
||||
|
||||
/**
|
||||
* Returns the {@link ChannelPipeline} which handles {@link ChannelEvent}s
|
||||
* associated with this channel.
|
||||
*/
|
||||
ChannelPipeline pipeline();
|
||||
|
||||
boolean isOpen();
|
||||
boolean isRegistered();
|
||||
boolean isActive();
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.channel;
|
||||
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.channel.socket.SocketChannelConfig;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
@ -136,4 +137,7 @@ public interface ChannelConfig {
|
||||
* if the specified value is {@code 0} or less than {@code 0}
|
||||
*/
|
||||
void setWriteSpinCount(int writeSpinCount);
|
||||
|
||||
ByteBufAllocator getAllocator();
|
||||
ByteBufAllocator setAllocator(ByteBufAllocator bufferPool);
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ import java.util.Set;
|
||||
* @apiviz.owns io.netty.channel.ChannelHandler
|
||||
*/
|
||||
public interface ChannelHandlerContext
|
||||
extends AttributeMap, ChannelFutureFactory,
|
||||
extends AttributeMap, ChannelPropertyAccess,
|
||||
ChannelInboundInvoker, ChannelOutboundInvoker {
|
||||
|
||||
/**
|
||||
@ -134,11 +134,6 @@ public interface ChannelHandlerContext
|
||||
*/
|
||||
Channel channel();
|
||||
|
||||
/**
|
||||
* Return the {@link ChannelPipeline} which belongs this {@link ChannelHandlerContext}.
|
||||
*/
|
||||
ChannelPipeline pipeline();
|
||||
|
||||
/**
|
||||
* The {@link EventExecutor} that is used to dispatch the events. This can also be used to directly
|
||||
* submit tasks that get executed in the event loop. For more informations please refer to the
|
||||
|
@ -16,7 +16,8 @@
|
||||
package io.netty.channel;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.UnsafeByteBuf;
|
||||
|
||||
|
||||
/**
|
||||
@ -34,7 +35,12 @@ public abstract class ChannelInboundByteHandlerAdapter
|
||||
*/
|
||||
@Override
|
||||
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||
return Unpooled.buffer();
|
||||
return ctx.alloc().buffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
((UnsafeByteBuf) buf).free();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -44,7 +50,7 @@ public abstract class ChannelInboundByteHandlerAdapter
|
||||
inboundBufferUpdated(ctx, in);
|
||||
} finally {
|
||||
if (!in.readable()) {
|
||||
in.unsafe().discardSomeReadBytes();
|
||||
((UnsafeByteBuf) in).discardSomeReadBytes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,4 +25,10 @@ public interface ChannelInboundHandler extends ChannelStateHandler {
|
||||
* Return the {@link ChannelBuf} which will be used for inbound data for the given {@link ChannelHandlerContext}.
|
||||
*/
|
||||
ChannelBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception;
|
||||
|
||||
/**
|
||||
* Invoked when this handler is not going to receive any inbound message anymore and thus it's safe to
|
||||
* deallocate its inbound buffer.
|
||||
*/
|
||||
void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.channel;
|
||||
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.MessageBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
@ -33,6 +34,11 @@ public abstract class ChannelInboundMessageHandlerAdapter<I>
|
||||
return Unpooled.messageBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public final void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.channel;
|
||||
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.util.UniqueName;
|
||||
|
||||
import java.net.InetAddress;
|
||||
@ -28,6 +29,7 @@ public class ChannelOption<T> extends UniqueName {
|
||||
|
||||
private static final ConcurrentMap<String, Boolean> names = new ConcurrentHashMap<String, Boolean>();
|
||||
|
||||
public static final ChannelOption<ByteBufAllocator> ALLOCATOR = new ChannelOption<ByteBufAllocator>("ALLOCATOR");
|
||||
public static final ChannelOption<Integer> CONNECT_TIMEOUT_MILLIS =
|
||||
new ChannelOption<Integer>("CONNECT_TIMEOUT_MILLIS");
|
||||
public static final ChannelOption<Integer> WRITE_SPIN_COUNT =
|
||||
|
@ -16,12 +16,18 @@
|
||||
package io.netty.channel;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.UnsafeByteBuf;
|
||||
|
||||
public abstract class ChannelOutboundByteHandlerAdapter
|
||||
extends ChannelOutboundHandlerAdapter implements ChannelOutboundByteHandler {
|
||||
@Override
|
||||
public ByteBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||
return Unpooled.buffer();
|
||||
return ctx.alloc().buffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
((UnsafeByteBuf) buf).free();
|
||||
}
|
||||
}
|
||||
|
@ -19,4 +19,10 @@ import io.netty.buffer.ChannelBuf;
|
||||
|
||||
public interface ChannelOutboundHandler extends ChannelOperationHandler {
|
||||
ChannelBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception;
|
||||
|
||||
/**
|
||||
* Invoked when this handler is not allowed to send any outbound message anymore and thus it's safe to
|
||||
* deallocate its outbound buffer.
|
||||
*/
|
||||
void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.channel;
|
||||
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.MessageBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
@ -24,4 +25,9 @@ public abstract class ChannelOutboundMessageHandlerAdapter<I>
|
||||
public MessageBuf<I> newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||
return Unpooled.messageBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
// Nothing to free
|
||||
}
|
||||
}
|
||||
|
@ -15,11 +15,16 @@
|
||||
*/
|
||||
package io.netty.channel;
|
||||
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
|
||||
/**
|
||||
* Factory which is responsible to create new {@link ChannelFuture}'s
|
||||
*
|
||||
* Provides common methods between {@link Channel} and {@link ChannelHandlerContext}.
|
||||
*/
|
||||
public interface ChannelFutureFactory {
|
||||
interface ChannelPropertyAccess {
|
||||
|
||||
ChannelPipeline pipeline();
|
||||
|
||||
ByteBufAllocator alloc();
|
||||
|
||||
/**
|
||||
* Create a new {@link ChannelFuture}
|
@ -68,12 +68,22 @@ public class CombinedChannelHandler
|
||||
return in.newInboundBuffer(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
in.freeInboundBuffer(ctx, buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelBuf newOutboundBuffer(
|
||||
ChannelHandlerContext ctx) throws Exception {
|
||||
return out.newOutboundBuffer(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
out.freeOutboundBuffer(ctx, buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeAdd(ChannelHandlerContext ctx) throws Exception {
|
||||
if (in == null) {
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package io.netty.channel;
|
||||
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||
import io.netty.channel.socket.SocketChannelConfig;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
@ -28,14 +30,16 @@ import static io.netty.channel.ChannelOption.*;
|
||||
*/
|
||||
public class DefaultChannelConfig implements ChannelConfig {
|
||||
|
||||
private static final ByteBufAllocator DEFAULT_ALLOCATOR = UnpooledByteBufAllocator.HEAP_BY_DEFAULT;
|
||||
private static final int DEFAULT_CONNECT_TIMEOUT = 30000;
|
||||
|
||||
private volatile ByteBufAllocator allocator = DEFAULT_ALLOCATOR;
|
||||
private volatile int connectTimeoutMillis = DEFAULT_CONNECT_TIMEOUT;
|
||||
private volatile int writeSpinCount = 16;
|
||||
|
||||
@Override
|
||||
public Map<ChannelOption<?>, Object> getOptions() {
|
||||
return getOptions(null, CONNECT_TIMEOUT_MILLIS, WRITE_SPIN_COUNT);
|
||||
return getOptions(null, CONNECT_TIMEOUT_MILLIS, WRITE_SPIN_COUNT, ALLOCATOR);
|
||||
}
|
||||
|
||||
protected Map<ChannelOption<?>, Object> getOptions(
|
||||
@ -79,6 +83,9 @@ public class DefaultChannelConfig implements ChannelConfig {
|
||||
if (option == WRITE_SPIN_COUNT) {
|
||||
return (T) Integer.valueOf(getWriteSpinCount());
|
||||
}
|
||||
if (option == ALLOCATOR) {
|
||||
return (T) getAllocator();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -91,6 +98,8 @@ public class DefaultChannelConfig implements ChannelConfig {
|
||||
setConnectTimeoutMillis((Integer) value);
|
||||
} else if (option == WRITE_SPIN_COUNT) {
|
||||
setWriteSpinCount((Integer) value);
|
||||
} else if (option == ALLOCATOR) {
|
||||
setAllocator((ByteBufAllocator) value);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@ -132,4 +141,19 @@ public class DefaultChannelConfig implements ChannelConfig {
|
||||
}
|
||||
this.writeSpinCount = writeSpinCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufAllocator getAllocator() {
|
||||
return allocator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufAllocator setAllocator(ByteBufAllocator allocator) {
|
||||
if (allocator == null) {
|
||||
throw new NullPointerException("allocator");
|
||||
}
|
||||
ByteBufAllocator oldAllocator = this.allocator;
|
||||
this.allocator = allocator;
|
||||
return oldAllocator;
|
||||
}
|
||||
}
|
||||
|
@ -15,11 +15,12 @@
|
||||
*/
|
||||
package io.netty.channel;
|
||||
|
||||
import static io.netty.channel.DefaultChannelPipeline.*;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.MessageBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.UnsafeByteBuf;
|
||||
import io.netty.util.DefaultAttributeMap;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
@ -34,42 +35,47 @@ import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static io.netty.channel.DefaultChannelPipeline.*;
|
||||
|
||||
final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext {
|
||||
|
||||
private static final EnumSet<ChannelHandlerType> EMPTY_TYPE = EnumSet.noneOf(ChannelHandlerType.class);
|
||||
|
||||
static final int DIR_INBOUND = 0x00000001;
|
||||
static final int DIR_OUTBOUND = 0x80000000;
|
||||
static final int DIR_INBOUND = 1;
|
||||
static final int DIR_OUTBOUND = 2;
|
||||
|
||||
private static final int FLAG_NEEDS_LAZY_INIT = 4;
|
||||
|
||||
volatile DefaultChannelHandlerContext next;
|
||||
volatile DefaultChannelHandlerContext prev;
|
||||
|
||||
private final Channel channel;
|
||||
private final DefaultChannelPipeline pipeline;
|
||||
EventExecutor executor; // not thread-safe but OK because it never changes once set.
|
||||
private final String name;
|
||||
private final Set<ChannelHandlerType> type;
|
||||
final int directions;
|
||||
private final ChannelHandler handler;
|
||||
final int flags;
|
||||
final AtomicBoolean readable = new AtomicBoolean(true);
|
||||
|
||||
MessageBuf<Object> inMsgBuf;
|
||||
ByteBuf inByteBuf;
|
||||
MessageBuf<Object> outMsgBuf;
|
||||
ByteBuf outByteBuf;
|
||||
EventExecutor executor; // not thread-safe but OK because it never changes once set.
|
||||
|
||||
private MessageBuf<Object> inMsgBuf;
|
||||
private UnsafeByteBuf inByteBuf;
|
||||
private MessageBuf<Object> outMsgBuf;
|
||||
private UnsafeByteBuf outByteBuf;
|
||||
|
||||
// When the two handlers run in a different thread and they are next to each other,
|
||||
// each other's buffers can be accessed at the same time resulting in a race condition.
|
||||
// To avoid such situation, we lazily creates an additional thread-safe buffer called
|
||||
// 'bridge' so that the two handlers access each other's buffer only via the bridges.
|
||||
// The content written into a bridge is flushed into the actual buffer by flushBridge().
|
||||
final AtomicReference<MessageBridge> inMsgBridge;
|
||||
final AtomicReference<MessageBridge> outMsgBridge;
|
||||
final AtomicReference<ByteBridge> inByteBridge;
|
||||
final AtomicReference<ByteBridge> outByteBridge;
|
||||
|
||||
final AtomicBoolean readable = new AtomicBoolean(true);
|
||||
private final AtomicReference<MessageBridge> inMsgBridge;
|
||||
AtomicReference<MessageBridge> outMsgBridge;
|
||||
private final AtomicReference<ByteBridge> inByteBridge;
|
||||
AtomicReference<ByteBridge> outByteBridge;
|
||||
|
||||
// Runnables that calls handlers
|
||||
final Runnable fireChannelRegisteredTask = new Runnable() {
|
||||
private final Runnable fireChannelRegisteredTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
||||
@ -80,7 +86,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
}
|
||||
}
|
||||
};
|
||||
final Runnable fireChannelUnregisteredTask = new Runnable() {
|
||||
private final Runnable fireChannelUnregisteredTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
||||
@ -91,7 +97,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
}
|
||||
}
|
||||
};
|
||||
final Runnable fireChannelActiveTask = new Runnable() {
|
||||
private final Runnable fireChannelActiveTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
||||
@ -102,7 +108,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
}
|
||||
}
|
||||
};
|
||||
final Runnable fireChannelInactiveTask = new Runnable() {
|
||||
private final Runnable fireChannelInactiveTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
||||
@ -113,7 +119,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
}
|
||||
}
|
||||
};
|
||||
final Runnable curCtxFireInboundBufferUpdatedTask = new Runnable() {
|
||||
private final Runnable curCtxFireInboundBufferUpdatedTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
||||
@ -148,6 +154,55 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
}
|
||||
}
|
||||
};
|
||||
private final Runnable freeInboundBufferTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
||||
if (ctx.handler instanceof ChannelInboundHandler) {
|
||||
ChannelInboundHandler h = (ChannelInboundHandler) ctx.handler;
|
||||
try {
|
||||
if (ctx.inByteBuf != null) {
|
||||
h.freeInboundBuffer(ctx, ctx.inByteBuf);
|
||||
} else {
|
||||
h.freeInboundBuffer(ctx, ctx.inMsgBuf);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
pipeline.notifyHandlerException(t);
|
||||
}
|
||||
}
|
||||
|
||||
DefaultChannelHandlerContext nextCtx = nextContext(ctx.next, DIR_INBOUND);
|
||||
if (nextCtx != null) {
|
||||
nextCtx.callFreeInboundBuffer();
|
||||
} else {
|
||||
// Freed all inbound buffers. Free all outbound buffers in a reverse order.
|
||||
pipeline.firstContext(DIR_OUTBOUND).callFreeOutboundBuffer();
|
||||
}
|
||||
}
|
||||
};
|
||||
private final Runnable freeOutboundBufferTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
||||
if (ctx.handler instanceof ChannelOutboundHandler) {
|
||||
ChannelOutboundHandler h = (ChannelOutboundHandler) ctx.handler;
|
||||
try {
|
||||
if (ctx.outByteBuf != null) {
|
||||
h.freeOutboundBuffer(ctx, ctx.outByteBuf);
|
||||
} else {
|
||||
h.freeOutboundBuffer(ctx, ctx.outMsgBuf);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
pipeline.notifyHandlerException(t);
|
||||
}
|
||||
}
|
||||
|
||||
DefaultChannelHandlerContext nextCtx = nextContext(ctx.prev, DIR_OUTBOUND);
|
||||
if (nextCtx != null) {
|
||||
nextCtx.callFreeOutboundBuffer();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
DefaultChannelHandlerContext(
|
||||
@ -162,25 +217,25 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
throw new NullPointerException("handler");
|
||||
}
|
||||
|
||||
int flags = 0;
|
||||
|
||||
// Determine the type of the specified handler.
|
||||
int typeValue = 0;
|
||||
EnumSet<ChannelHandlerType> type = EMPTY_TYPE.clone();
|
||||
if (handler instanceof ChannelStateHandler) {
|
||||
type.add(ChannelHandlerType.STATE);
|
||||
typeValue |= DIR_INBOUND;
|
||||
flags |= DIR_INBOUND;
|
||||
if (handler instanceof ChannelInboundHandler) {
|
||||
type.add(ChannelHandlerType.INBOUND);
|
||||
}
|
||||
}
|
||||
if (handler instanceof ChannelOperationHandler) {
|
||||
type.add(ChannelHandlerType.OPERATION);
|
||||
typeValue |= DIR_OUTBOUND;
|
||||
flags |= DIR_OUTBOUND;
|
||||
if (handler instanceof ChannelOutboundHandler) {
|
||||
type.add(ChannelHandlerType.OUTBOUND);
|
||||
}
|
||||
}
|
||||
this.type = Collections.unmodifiableSet(type);
|
||||
directions = typeValue;
|
||||
|
||||
this.prev = prev;
|
||||
this.next = next;
|
||||
@ -217,8 +272,8 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
throw new ChannelPipelineException("A user handler's newInboundBuffer() returned null");
|
||||
}
|
||||
|
||||
if (buf instanceof ByteBuf) {
|
||||
inByteBuf = (ByteBuf) buf;
|
||||
if (buf instanceof UnsafeByteBuf) {
|
||||
inByteBuf = (UnsafeByteBuf) buf;
|
||||
inByteBridge = new AtomicReference<ByteBridge>();
|
||||
inMsgBuf = null;
|
||||
inMsgBridge = null;
|
||||
@ -238,29 +293,15 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
}
|
||||
|
||||
if (type.contains(ChannelHandlerType.OUTBOUND)) {
|
||||
ChannelBuf buf;
|
||||
try {
|
||||
buf = ((ChannelOutboundHandler) handler).newOutboundBuffer(this);
|
||||
} catch (Exception e) {
|
||||
throw new ChannelPipelineException("A user handler failed to create a new outbound buffer.", e);
|
||||
}
|
||||
|
||||
if (buf == null) {
|
||||
throw new ChannelPipelineException("A user handler's newOutboundBuffer() returned null");
|
||||
}
|
||||
|
||||
if (buf instanceof ByteBuf) {
|
||||
outByteBuf = (ByteBuf) buf;
|
||||
outByteBridge = new AtomicReference<ByteBridge>();
|
||||
outMsgBuf = null;
|
||||
outMsgBridge = null;
|
||||
} else if (buf instanceof MessageBuf) {
|
||||
outByteBuf = null;
|
||||
outByteBridge = null;
|
||||
outMsgBuf = (MessageBuf<Object>) buf;
|
||||
outMsgBridge = new AtomicReference<MessageBridge>();
|
||||
if (prev == null) {
|
||||
// Special case: if pref == null, it means this context for HeadHandler.
|
||||
// HeadHandler is an outbound handler instantiated by the constructor of DefaultChannelPipeline.
|
||||
// Because Channel is not really fully initialized at this point, we should not call
|
||||
// newOutboundBuffer() yet because it will usually lead to NPE.
|
||||
// To work around this problem, we lazily initialize the outbound buffer for this special case.
|
||||
flags |= FLAG_NEEDS_LAZY_INIT;
|
||||
} else {
|
||||
throw new Error();
|
||||
initOutboundBuffer();
|
||||
}
|
||||
} else {
|
||||
outByteBuf = null;
|
||||
@ -268,6 +309,43 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
outMsgBuf = null;
|
||||
outMsgBridge = null;
|
||||
}
|
||||
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
private void lazyInitOutboundBuffer() {
|
||||
if ((flags & FLAG_NEEDS_LAZY_INIT) != 0) {
|
||||
if (outByteBuf == null && outMsgBuf == null) {
|
||||
initOutboundBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initOutboundBuffer() {
|
||||
ChannelBuf buf;
|
||||
try {
|
||||
buf = ((ChannelOutboundHandler) handler).newOutboundBuffer(this);
|
||||
} catch (Exception e) {
|
||||
throw new ChannelPipelineException("A user handler failed to create a new outbound buffer.", e);
|
||||
}
|
||||
|
||||
if (buf == null) {
|
||||
throw new ChannelPipelineException("A user handler's newOutboundBuffer() returned null");
|
||||
}
|
||||
|
||||
if (buf instanceof UnsafeByteBuf) {
|
||||
outByteBuf = (UnsafeByteBuf) buf;
|
||||
outByteBridge = new AtomicReference<ByteBridge>();
|
||||
outMsgBuf = null;
|
||||
outMsgBridge = null;
|
||||
} else if (buf instanceof MessageBuf) {
|
||||
outByteBuf = null;
|
||||
outByteBridge = null;
|
||||
outMsgBuf = (MessageBuf<Object>) buf;
|
||||
outMsgBridge = new AtomicReference<MessageBridge>();
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
void fillBridge() {
|
||||
@ -309,6 +387,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
}
|
||||
}
|
||||
|
||||
lazyInitOutboundBuffer();
|
||||
if (outMsgBridge != null) {
|
||||
MessageBridge bridge = outMsgBridge.get();
|
||||
if (bridge != null) {
|
||||
@ -332,6 +411,11 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufAllocator alloc() {
|
||||
return channel.config().getAllocator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventExecutor executor() {
|
||||
if (executor == null) {
|
||||
@ -405,16 +489,22 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
|
||||
@Override
|
||||
public boolean hasOutboundByteBuffer() {
|
||||
lazyInitOutboundBuffer();
|
||||
return outByteBuf != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOutboundMessageBuffer() {
|
||||
lazyInitOutboundBuffer();
|
||||
return outMsgBuf != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf outboundByteBuffer() {
|
||||
if (outMsgBuf == null) {
|
||||
lazyInitOutboundBuffer();
|
||||
}
|
||||
|
||||
if (outByteBuf == null) {
|
||||
if (handler instanceof ChannelOutboundHandler) {
|
||||
throw new NoSuchBufferException(String.format(
|
||||
@ -434,6 +524,10 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> MessageBuf<T> outboundMessageBuffer() {
|
||||
if (outMsgBuf == null) {
|
||||
initOutboundBuffer();
|
||||
}
|
||||
|
||||
if (outMsgBuf == null) {
|
||||
if (handler instanceof ChannelOutboundHandler) {
|
||||
throw new NoSuchBufferException(String.format(
|
||||
@ -470,7 +564,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
* @throws ChannelPipelineException with a {@link Throwable} as a cause, if the task threw another type of
|
||||
* {@link Throwable}.
|
||||
*/
|
||||
<T> T executeOnEventLoop(Callable<T> c) throws Exception {
|
||||
private <T> T executeOnEventLoop(Callable<T> c) throws Exception {
|
||||
return getFromFuture(executor().submit(c));
|
||||
}
|
||||
|
||||
@ -513,7 +607,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
* @throws ChannelPipelineException with a {@link Throwable} as a cause, if the task threw another type of
|
||||
* {@link Throwable}.
|
||||
*/
|
||||
<T> T getFromFuture(Future<T> future) throws Exception {
|
||||
private static <T> T getFromFuture(Future<T> future) throws Exception {
|
||||
try {
|
||||
return future.get();
|
||||
} catch (ExecutionException ex) {
|
||||
@ -547,7 +641,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
* @throws ChannelPipelineException with a {@link Throwable} as a cause, if the task threw another type of
|
||||
* {@link Throwable}.
|
||||
*/
|
||||
void waitForFuture(Future future) {
|
||||
static void waitForFuture(Future<?> future) {
|
||||
try {
|
||||
future.get();
|
||||
} catch (ExecutionException ex) {
|
||||
@ -585,7 +679,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
|
||||
ByteBuf currentInboundByteBuf = inboundByteBuffer();
|
||||
|
||||
this.inByteBuf = newInboundByteBuf;
|
||||
inByteBuf = (UnsafeByteBuf) newInboundByteBuf;
|
||||
return currentInboundByteBuf;
|
||||
}
|
||||
|
||||
@ -611,7 +705,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
|
||||
MessageBuf<T> currentInboundMsgBuf = inboundMessageBuffer();
|
||||
|
||||
this.inMsgBuf = (MessageBuf<Object>) newInboundMsgBuf;
|
||||
inMsgBuf = (MessageBuf<Object>) newInboundMsgBuf;
|
||||
return currentInboundMsgBuf;
|
||||
}
|
||||
|
||||
@ -636,7 +730,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
|
||||
ByteBuf currentOutboundByteBuf = outboundByteBuffer();
|
||||
|
||||
this.outByteBuf = newOutboundByteBuf;
|
||||
outByteBuf = (UnsafeByteBuf) newOutboundByteBuf;
|
||||
return currentOutboundByteBuf;
|
||||
}
|
||||
|
||||
@ -662,7 +756,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
|
||||
MessageBuf<T> currentOutboundMsgBuf = outboundMessageBuffer();
|
||||
|
||||
this.outMsgBuf = (MessageBuf<Object>) newOutboundMsgBuf;
|
||||
outMsgBuf = (MessageBuf<Object>) newOutboundMsgBuf;
|
||||
return currentOutboundMsgBuf;
|
||||
}
|
||||
|
||||
@ -696,12 +790,36 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
|
||||
@Override
|
||||
public boolean hasNextOutboundByteBuffer() {
|
||||
return DefaultChannelPipeline.hasNextOutboundByteBuffer(prev);
|
||||
DefaultChannelHandlerContext ctx = prev;
|
||||
for (;;) {
|
||||
if (ctx == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx.lazyInitOutboundBuffer();
|
||||
|
||||
if (ctx.outByteBridge != null) {
|
||||
return true;
|
||||
}
|
||||
ctx = ctx.prev;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNextOutboundMessageBuffer() {
|
||||
return DefaultChannelPipeline.hasNextOutboundMessageBuffer(prev);
|
||||
DefaultChannelHandlerContext ctx = prev;
|
||||
for (;;) {
|
||||
if (ctx == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx.lazyInitOutboundBuffer();
|
||||
|
||||
if (ctx.outMsgBridge != null) {
|
||||
return true;
|
||||
}
|
||||
ctx = ctx.prev;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -728,7 +846,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
} else {
|
||||
ByteBridge bridge = ctx.inByteBridge.get();
|
||||
if (bridge == null) {
|
||||
bridge = new ByteBridge();
|
||||
bridge = new ByteBridge(ctx);
|
||||
if (!ctx.inByteBridge.compareAndSet(null, bridge)) {
|
||||
bridge = ctx.inByteBridge.get();
|
||||
}
|
||||
@ -779,12 +897,12 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
|
||||
@Override
|
||||
public ByteBuf nextOutboundByteBuffer() {
|
||||
return DefaultChannelPipeline.nextOutboundByteBuffer(prev);
|
||||
return pipeline.nextOutboundByteBuffer(prev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuf<Object> nextOutboundMessageBuffer() {
|
||||
return DefaultChannelPipeline.nextOutboundMessageBuffer(prev);
|
||||
return pipeline.nextOutboundMessageBuffer(prev);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -876,8 +994,8 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
} else {
|
||||
logger.warn(
|
||||
"An exceptionCaught() event was fired, and it reached at the end of the " +
|
||||
"pipeline. It usually means the last inbound handler in the pipeline did not " +
|
||||
"handle the exception.", cause);
|
||||
"pipeline. It usually means the last inbound handler in the pipeline did not " +
|
||||
"handle the exception.", cause);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1011,6 +1129,25 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
return pipeline.write(prev, message, future);
|
||||
}
|
||||
|
||||
void callFreeInboundBuffer() {
|
||||
EventExecutor executor = executor();
|
||||
if (executor.inEventLoop()) {
|
||||
freeInboundBufferTask.run();
|
||||
} else {
|
||||
executor.execute(freeInboundBufferTask);
|
||||
}
|
||||
}
|
||||
|
||||
/** Invocation initiated by {@link #freeInboundBufferTask} after freeing all inbound buffers. */
|
||||
private void callFreeOutboundBuffer() {
|
||||
EventExecutor executor = executor();
|
||||
if (executor.inEventLoop()) {
|
||||
freeOutboundBufferTask.run();
|
||||
} else {
|
||||
executor.execute(freeOutboundBufferTask);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture newFuture() {
|
||||
return channel.newFuture();
|
||||
@ -1028,9 +1165,10 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
|
||||
static final class MessageBridge {
|
||||
final MessageBuf<Object> msgBuf = Unpooled.messageBuffer();
|
||||
final Queue<Object[]> exchangeBuf = new ConcurrentLinkedQueue<Object[]>();
|
||||
|
||||
void fill() {
|
||||
private final Queue<Object[]> exchangeBuf = new ConcurrentLinkedQueue<Object[]>();
|
||||
|
||||
private void fill() {
|
||||
if (msgBuf.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@ -1039,7 +1177,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
exchangeBuf.add(data);
|
||||
}
|
||||
|
||||
void flush(MessageBuf<Object> out) {
|
||||
private void flush(MessageBuf<Object> out) {
|
||||
for (;;) {
|
||||
Object[] data = exchangeBuf.poll();
|
||||
if (data == null) {
|
||||
@ -1052,26 +1190,48 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
||||
}
|
||||
|
||||
static final class ByteBridge {
|
||||
final ByteBuf byteBuf = Unpooled.buffer();
|
||||
final Queue<ByteBuf> exchangeBuf = new ConcurrentLinkedQueue<ByteBuf>();
|
||||
final UnsafeByteBuf byteBuf;
|
||||
|
||||
void fill() {
|
||||
private final Queue<UnsafeByteBuf> exchangeBuf = new ConcurrentLinkedQueue<UnsafeByteBuf>();
|
||||
private final ChannelHandlerContext ctx;
|
||||
|
||||
ByteBridge(ChannelHandlerContext ctx) {
|
||||
this.ctx = ctx;
|
||||
// TODO Choose whether to use heap or direct buffer depending on the context's buffer type.
|
||||
byteBuf = (UnsafeByteBuf) ctx.alloc().buffer();
|
||||
}
|
||||
|
||||
private void fill() {
|
||||
if (!byteBuf.readable()) {
|
||||
return;
|
||||
}
|
||||
ByteBuf data = byteBuf.readBytes(byteBuf.readableBytes());
|
||||
byteBuf.discardReadBytes();
|
||||
exchangeBuf.add(data);
|
||||
|
||||
int dataLen = byteBuf.readableBytes();
|
||||
ByteBuf data;
|
||||
if (byteBuf.isDirect()) {
|
||||
data = ctx.alloc().directBuffer(dataLen, dataLen);
|
||||
} else {
|
||||
data = ctx.alloc().buffer(dataLen, dataLen);
|
||||
}
|
||||
|
||||
byteBuf.readBytes(data);
|
||||
byteBuf.discardSomeReadBytes();
|
||||
|
||||
exchangeBuf.add((UnsafeByteBuf) data);
|
||||
}
|
||||
|
||||
void flush(ByteBuf out) {
|
||||
private void flush(ByteBuf out) {
|
||||
for (;;) {
|
||||
ByteBuf data = exchangeBuf.poll();
|
||||
UnsafeByteBuf data = exchangeBuf.poll();
|
||||
if (data == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
out.writeBytes(data);
|
||||
try {
|
||||
out.writeBytes(data);
|
||||
} finally {
|
||||
data.free();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.MessageBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.UnsafeByteBuf;
|
||||
import io.netty.logging.InternalLogger;
|
||||
import io.netty.logging.InternalLoggerFactory;
|
||||
|
||||
@ -358,7 +359,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
|
||||
private DefaultChannelHandlerContext remove(final DefaultChannelHandlerContext ctx) {
|
||||
DefaultChannelHandlerContext context;
|
||||
Future future;
|
||||
Future<?> future;
|
||||
|
||||
synchronized (this) {
|
||||
if (head == tail) {
|
||||
@ -407,7 +408,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
// Run the following 'waiting' code outside of the above synchronized block
|
||||
// in order to avoid deadlock
|
||||
|
||||
context.waitForFuture(future);
|
||||
waitForFuture(future);
|
||||
|
||||
return context;
|
||||
}
|
||||
@ -497,9 +498,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
|
||||
private ChannelHandler replace(
|
||||
final DefaultChannelHandlerContext ctx, final String newName, ChannelHandler newHandler) {
|
||||
Future future;
|
||||
DefaultChannelHandlerContext context;
|
||||
|
||||
Future<?> future;
|
||||
synchronized (this) {
|
||||
if (ctx == head) {
|
||||
throw new IllegalArgumentException();
|
||||
@ -528,7 +527,6 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
}
|
||||
}
|
||||
});
|
||||
context = oldTail;
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -555,7 +553,6 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
}
|
||||
}
|
||||
});
|
||||
context = newCtx;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -563,7 +560,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
// Run the following 'waiting' code outside of the above synchronized block
|
||||
// in order to avoid deadlock
|
||||
|
||||
context.waitForFuture(future);
|
||||
waitForFuture(future);
|
||||
|
||||
return ctx.handler();
|
||||
}
|
||||
@ -866,33 +863,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
return nextOutboundByteBuffer(tail);
|
||||
}
|
||||
|
||||
static boolean hasNextOutboundByteBuffer(DefaultChannelHandlerContext ctx) {
|
||||
for (;;) {
|
||||
if (ctx == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctx.outByteBridge != null) {
|
||||
return true;
|
||||
}
|
||||
ctx = ctx.prev;
|
||||
}
|
||||
}
|
||||
|
||||
static boolean hasNextOutboundMessageBuffer(DefaultChannelHandlerContext ctx) {
|
||||
for (;;) {
|
||||
if (ctx == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctx.outMsgBridge != null) {
|
||||
return true;
|
||||
}
|
||||
ctx = ctx.prev;
|
||||
}
|
||||
}
|
||||
|
||||
static ByteBuf nextOutboundByteBuffer(DefaultChannelHandlerContext ctx) {
|
||||
ByteBuf nextOutboundByteBuffer(DefaultChannelHandlerContext ctx) {
|
||||
final DefaultChannelHandlerContext initialCtx = ctx;
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
for (;;) {
|
||||
@ -910,13 +881,13 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.outByteBuf != null) {
|
||||
if (ctx.hasOutboundByteBuffer()) {
|
||||
if (ctx.executor().inEventLoop(currentThread)) {
|
||||
return ctx.outByteBuf;
|
||||
return ctx.outboundByteBuffer();
|
||||
} else {
|
||||
ByteBridge bridge = ctx.outByteBridge.get();
|
||||
if (bridge == null) {
|
||||
bridge = new ByteBridge();
|
||||
bridge = new ByteBridge(ctx);
|
||||
if (!ctx.outByteBridge.compareAndSet(null, bridge)) {
|
||||
bridge = ctx.outByteBridge.get();
|
||||
}
|
||||
@ -928,7 +899,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
}
|
||||
}
|
||||
|
||||
static MessageBuf<Object> nextOutboundMessageBuffer(DefaultChannelHandlerContext ctx) {
|
||||
MessageBuf<Object> nextOutboundMessageBuffer(DefaultChannelHandlerContext ctx) {
|
||||
final DefaultChannelHandlerContext initialCtx = ctx;
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
for (;;) {
|
||||
@ -946,9 +917,9 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.outMsgBuf != null) {
|
||||
if (ctx.hasOutboundMessageBuffer()) {
|
||||
if (ctx.executor().inEventLoop(currentThread)) {
|
||||
return ctx.outMsgBuf;
|
||||
return ctx.outboundMessageBuffer();
|
||||
} else {
|
||||
MessageBridge bridge = ctx.outMsgBridge.get();
|
||||
if (bridge == null) {
|
||||
@ -972,6 +943,11 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
@Override
|
||||
public void fireChannelUnregistered() {
|
||||
head.fireChannelUnregistered();
|
||||
|
||||
// Free all buffers if channel is closed and unregistered.
|
||||
if (!channel.isOpen()) {
|
||||
head.callFreeInboundBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1232,8 +1208,8 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
} catch (Throwable t) {
|
||||
notifyHandlerException(t);
|
||||
} finally {
|
||||
if (ctx.outByteBuf != null) {
|
||||
ByteBuf buf = ctx.outByteBuf;
|
||||
if (ctx.hasOutboundByteBuffer()) {
|
||||
ByteBuf buf = ctx.outboundByteBuffer();
|
||||
if (!buf.readable()) {
|
||||
buf.discardReadBytes();
|
||||
}
|
||||
@ -1289,10 +1265,10 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
|
||||
if (executor.inEventLoop()) {
|
||||
if (msgBuf) {
|
||||
ctx.outMsgBuf.add(message);
|
||||
ctx.outboundMessageBuffer().add(message);
|
||||
} else {
|
||||
ByteBuf buf = (ByteBuf) message;
|
||||
ctx.outByteBuf.writeBytes(buf, buf.readerIndex(), buf.readableBytes());
|
||||
ctx.outboundByteBuffer().writeBytes(buf, buf.readerIndex(), buf.readableBytes());
|
||||
}
|
||||
flush0(ctx, future);
|
||||
return future;
|
||||
@ -1325,12 +1301,12 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
}
|
||||
}
|
||||
|
||||
private DefaultChannelHandlerContext firstContext(int direction) {
|
||||
DefaultChannelHandlerContext firstContext(int direction) {
|
||||
assert direction == DIR_INBOUND || direction == DIR_OUTBOUND;
|
||||
if (direction > 0) {
|
||||
return nextContext(head.next, direction);
|
||||
} else {
|
||||
return nextContext(tail, direction);
|
||||
if (direction == DIR_INBOUND) {
|
||||
return nextContext(head.next, DIR_INBOUND);
|
||||
} else { // DIR_OUTBOUND
|
||||
return nextContext(tail, DIR_OUTBOUND);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1342,15 +1318,15 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
}
|
||||
|
||||
DefaultChannelHandlerContext realCtx = ctx;
|
||||
if (direction > 0) {
|
||||
while ((realCtx.directions & direction) == 0) {
|
||||
if (direction == DIR_INBOUND) {
|
||||
while ((realCtx.flags & DIR_INBOUND) == 0) {
|
||||
realCtx = realCtx.next;
|
||||
if (realCtx == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while ((realCtx.directions & direction) == 0) {
|
||||
} else { // DIR_OUTBOUND
|
||||
while ((realCtx.flags & DIR_OUTBOUND) == 0) {
|
||||
realCtx = realCtx.prev;
|
||||
if (realCtx == null) {
|
||||
return null;
|
||||
@ -1448,8 +1424,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
public ChannelBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||
switch (channel.metadata().bufferType()) {
|
||||
case BYTE:
|
||||
// TODO: Use a direct buffer once buffer pooling is implemented.
|
||||
return Unpooled.buffer();
|
||||
return ctx.alloc().ioBuffer();
|
||||
case MESSAGE:
|
||||
return Unpooled.messageBuffer();
|
||||
default:
|
||||
@ -1457,6 +1432,13 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) {
|
||||
if (buf instanceof UnsafeByteBuf) {
|
||||
((UnsafeByteBuf) buf).free();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeAdd(ChannelHandlerContext ctx) throws Exception {
|
||||
// NOOP
|
||||
|
@ -19,6 +19,7 @@ import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.MessageBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.UnsafeByteBuf;
|
||||
import io.netty.channel.AbstractChannel;
|
||||
import io.netty.channel.ChannelConfig;
|
||||
import io.netty.channel.ChannelException;
|
||||
@ -211,6 +212,11 @@ public abstract class AbstractEmbeddedChannel extends AbstractChannel {
|
||||
return lastInboundMessageBuffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
||||
// Do nothing.
|
||||
@ -235,6 +241,11 @@ public abstract class AbstractEmbeddedChannel extends AbstractChannel {
|
||||
return lastInboundByteBuffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
((UnsafeByteBuf) buf).free();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
||||
// No nothing
|
||||
|
@ -17,8 +17,10 @@ package io.netty.channel.local;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ChannelBuf;
|
||||
import io.netty.buffer.MessageBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.UnsafeByteBuf;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerAdapter;
|
||||
@ -349,6 +351,16 @@ public class LocalTransportThreadModelTest {
|
||||
return Unpooled.messageBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundBufferUpdated(
|
||||
ChannelHandlerContext ctx) throws Exception {
|
||||
@ -393,7 +405,17 @@ public class LocalTransportThreadModelTest {
|
||||
|
||||
@Override
|
||||
public ByteBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||
return Unpooled.buffer();
|
||||
return ctx.alloc().buffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) {
|
||||
((UnsafeByteBuf) buf).free();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -440,7 +462,7 @@ public class LocalTransportThreadModelTest {
|
||||
out.add(msg);
|
||||
}
|
||||
}
|
||||
in.unsafe().discardSomeReadBytes();
|
||||
((UnsafeByteBuf) in).discardSomeReadBytes();
|
||||
if (swallow) {
|
||||
future.setSuccess();
|
||||
} else {
|
||||
@ -472,7 +494,7 @@ public class LocalTransportThreadModelTest {
|
||||
@Override
|
||||
public ByteBuf newInboundBuffer(
|
||||
ChannelHandlerContext ctx) throws Exception {
|
||||
return Unpooled.buffer();
|
||||
return ctx.alloc().buffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -481,6 +503,16 @@ public class LocalTransportThreadModelTest {
|
||||
return Unpooled.messageBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
((UnsafeByteBuf) buf).free();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundBufferUpdated(
|
||||
ChannelHandlerContext ctx) throws Exception {
|
||||
@ -556,6 +588,16 @@ public class LocalTransportThreadModelTest {
|
||||
return Unpooled.messageBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
||||
Thread t = this.t;
|
||||
@ -632,6 +674,16 @@ public class LocalTransportThreadModelTest {
|
||||
return Unpooled.messageBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) {
|
||||
// Nothing to free
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
||||
Thread t = this.t;
|
||||
|
Loading…
Reference in New Issue
Block a user