// TODO: Test if adding padding helps under contention //private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; internal PoolThreadCache(PoolArena <T> heapArena, PoolArena <T> directArena, int tinyCacheSize, int smallCacheSize, int normalCacheSize, int maxCachedBufferCapacity, int freeSweepAllocationThreshold) { Contract.Requires(maxCachedBufferCapacity >= 0); Contract.Requires(freeSweepAllocationThreshold > 0); this.freeSweepAllocationThreshold = freeSweepAllocationThreshold; this.HeapArena = heapArena; this.DirectArena = directArena; if (directArena != null) { this.tinySubPageDirectCaches = CreateSubPageCaches( tinyCacheSize, PoolArena <T> .NumTinySubpagePools, SizeClass.Tiny); this.smallSubPageDirectCaches = CreateSubPageCaches( smallCacheSize, directArena.NumSmallSubpagePools, SizeClass.Small); this.numShiftsNormalDirect = Log2(directArena.PageSize); this.normalDirectCaches = CreateNormalCaches( normalCacheSize, maxCachedBufferCapacity, directArena); directArena.IncrementNumThreadCaches(); } else { // No directArea is configured so just null out all caches this.tinySubPageDirectCaches = null; this.smallSubPageDirectCaches = null; this.normalDirectCaches = null; this.numShiftsNormalDirect = -1; } if (heapArena != null) { // Create the caches for the heap allocations this.tinySubPageHeapCaches = CreateSubPageCaches( tinyCacheSize, PoolArena <T> .NumTinySubpagePools, SizeClass.Tiny); this.smallSubPageHeapCaches = CreateSubPageCaches( smallCacheSize, heapArena.NumSmallSubpagePools, SizeClass.Small); this.numShiftsNormalHeap = Log2(heapArena.PageSize); this.normalHeapCaches = CreateNormalCaches( normalCacheSize, maxCachedBufferCapacity, heapArena); heapArena.IncrementNumThreadCaches(); } else { // No heapArea is configured so just null out all caches this.tinySubPageHeapCaches = null; this.smallSubPageHeapCaches = null; this.normalHeapCaches = null; this.numShiftsNormalHeap = -1; } // We only need to watch the thread when any cache is used. if (this.tinySubPageDirectCaches != null || this.smallSubPageDirectCaches != null || this.normalDirectCaches != null || this.tinySubPageHeapCaches != null || this.smallSubPageHeapCaches != null || this.normalHeapCaches != null) { this.freeTask = this.Free0; this.deathWatchThread = Thread.CurrentThread; // The thread-local cache will keep a list of pooled buffers which must be returned to // the pool when the thread is not alive anymore. ThreadDeathWatcher.Watch(this.deathWatchThread, this.freeTask); } else { this.freeTask = null; this.deathWatchThread = null; } }
MemoryRegionCache CacheForTiny(PoolArena <T> area, int normCapacity) { int idx = PoolArena <T> .TinyIdx(normCapacity); return(Cache(area.IsDirect ? this.tinySubPageDirectCaches : this.tinySubPageHeapCaches, idx)); }
MemoryRegionCache CacheForSmall(PoolArena <T> area, int normCapacity) { int idx = PoolArena <T> .SmallIdx(normCapacity); return(Cache(area.IsDirect ? this.smallSubPageDirectCaches : this.smallSubPageHeapCaches, idx)); }
/** * Try to allocate a small buffer out of the cache. Returns {@code true} if successful {@code false} otherwise */ internal bool AllocateNormal(PoolArena <T> area, PooledByteBuffer <T> buf, int reqCapacity, int normCapacity) => this.Allocate(this.CacheForNormal(area, normCapacity), buf, reqCapacity);