Class 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).