- Fixes#826
Unsafe.isFreed(), free(), suspend/resumeIntermediaryAllocations() are not that dangerous. internalNioBuffer() and internalNioBuffers() are dangerous but it seems like nobody is using it even inside Netty. Removing those two methods also removes the necessity to keep Unsafe interface at all.
* UnsafeByteBuf is gone. I added ByteBuf.unsafe() back.
* To avoid extra instantiation, all ByteBuf implementations implement the ByteBuf.Unsafe interface.
* To hide this implementation detail, all ByteBuf implementations are package-private.
* AbstractByteBuf and SwappedByteBuf are public and they do not implement ByteBuf.Unsafe because they don't need to.
* unwrap() is not an unsafe operation anymore.
* ChannelBuf also has unsafe() and Unsafe. ByteBuf.Unsafe extends ChannelBuf.unsafe(). ChannelBuf.unsafe() provides free() operation so that a user does not need to down-cast the buffer in freeInbound/OutboundBuffer().
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
- Add EventExecutorGroup and EventLoopGroup
- EventExecutor and EventLoop extends EventExecutorGroup and
EventLoopGroup
- They form their own group so that .next() returns itself.
- Rename Bootstrap.eventLoop() to group()
- Rename parameter names such as executor to group
- Rename *EventLoop/Executor to *EventLoop/ExecutorGroup
- Rename *ChildEventLoop/Executor to *EventLoop/Executor
- Replace ByteBufferBackedByteBuf with DirectByteBuf
- Make DirectByteBuf and HeapByteBuf dynamic
- Remove DynamicByteBuf
- Replace Unpooled.dynamicBuffer() with Unpooled.buffer() and
directBuffer()
- Remove ByteBufFactory (will be replaced with ByteBufPool later)
- Add ByteBuf.Unsafe (might change in the future)
- Add Channel.metadata() and remove Channel.bufferType()
- DefaultPipeline automatically redirects disconnect() request to
close() if the channel has no disconnect operation
- Remove unnecessary disconnect() implementations
- ChannelInboundHandler and ChannelOutboundHandler does not have a type
parameter anymore.
- User should implement ChannelInboundMessageHandler or
ChannelOutboundMessageHandler.
- ChannelBuffer gives a perception that it's a buffer of a
channel, but channel's buffer is now a byte buffer or a message
buffer. Therefore letting it be as is is going to be confusing.
- In computing, 'stream' means both byte stream and message stream,
which is confusing.
- Also, we were already mixing stream and byte in some places and
it's better use the terms consistently.
(e.g. inboundByteBuffer & inbound stream)
- Added EventExecutor.inEventLoop(Thread) and replaced executor identity
comparison in DefaultChannelPipeline with it - more elegant IMO
- Removed the test classes that needs rewrite or is of no use
- LoggingHandler now only logs state and operations
- StreamLoggingHandler and MessageLoggingHandler log the buffer content
- Added ChannelOperationHandlerAdapter
- Used by WriteTimeoutHandler
- Extracted some handler methods from ChannelInboundHandler into
ChannelStateHandler
- Extracted some handler methods from ChannelOutboundHandler into
ChannelOperationHandler
- Moved exceptionCaught and userEventTriggered are now in
ChannelHandler
- Channel(Inbound|Outbound)HandlerContext is merged into
ChannelHandlerContext
- ChannelHandlerContext adds direct access methods for inboud and
outbound buffers
- The use of ChannelBufferHolder is minimal now.
- Before: inbound().byteBuffer()
- After: inboundByteBuffer()
- Simpler and better performance
- Bypass buffer types were removed because it just does not work at all
with the thread model.
- All handlers that uses a bypass buffer are broken. Will fix soon.
- CombinedHandlerAdapter does not make sense anymore either because
there are four handler interfaces to consider and often the two
handlers will implement the same handler interface such as
ChannelStateHandler. Thinking of better ways to provide this feature