Table of Contents |
---|
Overview
ByteBuffers are not meant to be accessed concurrently. But our NioFilter classes, particularly, NioSslEngine manipulate ByteBuffers, and are themselves subject to concurrent access. As a result it's often necessary to protect ByteBuffers from concurrent access.
Not only must we protect ByteBuffers from concurrent access, we also need to ensure that ByteBuffers are returned to their pool when they are no longer needed.
The purpose of the ByteBuffer sharing framework is to provide this coordination and pool management.
The framework leverages the try-with-resources syntax to deliver exclusive ByteBuffer access in lexical blocks. The ByteBufferSharing class provides a couple open() methods (one of which supports timeout). These methods return an AutoCloseable "resource", suitable for assignment in a try-with-resources variable declaration. The Java language guarantees that close() will be called on such a resource when the lexical block is left (either through normal program flow or exception). The framework leverages that close() call as a signal to release locks and reduce reference counts.
PlantUML |
---|
@startuml
interface AutoCloseable {
void close()
}
interface ByteBufferSharing extends AutoCloseable {
ByteBuffer getBuffer()
ByteBuffer expandWriteBufferIfNeeded(int newCapacity)
ByteBuffer expandReadBufferIfNeeded(int newCapacity)
}
class ByteBufferVendor {
ByteBufferVendor(ByteBuffer bufferArg, BufferType bufferType, BufferPool bufferPool)
ByteBufferSharing open()
ByteBufferSharing open(long time, TimeUnit unit)
void destruct()
}
ByteBufferVendor .. ByteBuffer : derived\nassociation
@enduml |
more
Internals
PlantUML |
---|
@startuml interface AutoCloseable { void close() } interface ByteBufferSharing extends AutoCloseable { ByteBuffer getBuffer() ByteBuffer expandWriteBufferIfNeeded(int newCapacity) ByteBuffer expandReadBufferIfNeeded(int newCapacity) } class ByteBufferVendor { ByteBufferVendor(ByteBuffer bufferArg, BufferType bufferType, BufferPool bufferPool) ByteBufferSharing open() ByteBufferSharing open(long time, TimeUnit unit) void destruct() } interface ByteBufferVendor.ByteBufferSharingInternal extends ByteBufferSharing { void releaseBuffer() } class ByteBufferVendor.ByteBufferSharingInternalImpl implements ByteBufferVendor.ByteBufferSharingInternal {} ByteBufferVendor "sharing" *-- ByteBufferVendor.ByteBufferSharingInternal ByteBufferVendor "lock" *-- ReentrantLock ByteBufferVendor "isDestructed" *-- AtomicBoolean ByteBufferVendor "counter" *-- AtomicInteger ByteBufferVendor.ByteBufferSharingInternalImpl "buffer\n0..1" --> "1" ByteBuffer ByteBufferVendor.ByteBufferSharingInternalImpl "bufferPool\n*" --> "1" BufferPool ByteBufferVendor.ByteBufferSharingInternalImpl "bufferType\n*" --> "1" BufferType ByteBufferVendor .. ByteBuffer : derived\nassociation @enduml |
ByteBuffers are not meant to be accessed concurrently. But our NioFilter classes, particularly, NioSslEngine manipulate ByteBuffers, and are themselves subject to concurrent access. As a result it's often necessary to protect ByteBuffers from concurrent access.
Not only must we protect ByteBuffers from concurrent access, we also need to ensure that ByteBuffers are returned to their pool when they are no longer needed.
The purpose of the ByteBuffer sharing framework is to provide this coordination and pool management.
...
The ByteBufferSharingInternalImpl class (a private, static internal class of ByteBufferVendor) is the main implementation of the "resource" class just mentioned. It implements AutoCloseable so it's usable as a resource in try-with-resources. It also implements a public interface, ByteBufferSharing, for use by clients within a try-with-resources block. It's this interface that a user of ByteBuffers will be most interested in:
...