Class AdaptivePoolingAllocator.SharedSizeClassedChunkCache

java.lang.Object
io.netty.buffer.AdaptivePoolingAllocator.SizeClassedChunkCache
io.netty.buffer.AdaptivePoolingAllocator.SharedSizeClassedChunkCache
All Implemented Interfaces:
AdaptivePoolingAllocator.ChunkCache
Enclosing class:
AdaptivePoolingAllocator

static final class AdaptivePoolingAllocator.SharedSizeClassedChunkCache extends AdaptivePoolingAllocator.SizeClassedChunkCache
MPMC queue cache for shared (cross-thread) chunk reuse.

scanForCapacity — LRU preference with fallback:

   fast path: head chunk has purgeEpoch == 0 and capacity → return O(1)

   slow path: scan for epoch=0 chunk, hold first idle (epoch > 0) as fallback
     queue: [E>0, E>0, E=0, E>0, ...]
             skip   skip  ↑ return (put fallback back)

   no epoch=0 found → use fallback, reset its epoch to 0
 

The LRU preference creates a natural separation: recently-used chunks (epoch=0, returned via offerChunk(io.netty.buffer.AdaptivePoolingAllocator.Chunk) after magazine use) cycle at the front. Idle chunks (epoch > 0, aged by purge) are scanned past but never returned — they age undisturbed. When no recently-used chunks exist, idle ones are reused (fallback) rather than allocating new chunks.

All re-offered chunks are stamped with lastScanGeneration for cycle detection. The >= check terminates the scan when encountering any chunk already processed by this or a later scan, preventing livelock under concurrent access.

runPurgeScan (every AdaptivePoolingAllocator.CHUNK_PURGE_POLLS_SHARED polls): drains the queue, ages full chunks (epoch++), resets non-full (epoch=0). Non-candidate capacity chunks are re-offered inline. Eviction candidates (full, epoch past threshold) and no-capacity chunks are deferred to a buffer. After the drain, the buffer is walked with the known total: candidates are evicted while above AdaptivePoolingAllocator.CHUNK_REUSE_QUEUE, remainder re-offered. No selection — that is scanForCapacity's job (called after purge via pollChunk).