/// Moves the {@link PoolChunk} down the {@link PoolChunkList} linked-list so it will end up in the right /// {@link PoolChunkList} that has the correct minUsage / maxUsage in respect to {@link PoolChunk#usage()}. bool Move0(PoolChunk <T> chunk) { if (this.prevList == null) { // There is no previous PoolChunkList so return false which result in having the PoolChunk destroyed and // all memory associated with the PoolChunk will be released. Debug.Assert(chunk.Usage == 0); return(false); } return(this.prevList.Move(chunk)); }
internal bool Free(PoolChunk <T> chunk, long handle) { chunk.Free(handle); if (chunk.Usage < this.minUsage) { this.Remove(chunk); // Move the PoolChunk down the PoolChunkList linked-list. return(this.Move0(chunk)); } return(true); }
internal void Destroy(PoolArena <T> poolArena) { PoolChunk <T> chunk = this.head; while (chunk != null) { poolArena.DestroyChunk(chunk); chunk = chunk.Next; } this.head = null; }
IEnumerator <IPoolChunkMetric> GetEnumeratorInternal() { lock (this.arena) { for (PoolChunk <T> cur = this.head; cur != null;) { yield return(cur); cur = cur.Next; } } }
protected internal override void DestroyChunk(PoolChunk <byte[]> chunk) { for (int i = 0; i < this.memoryChunks.Count; i++) { MemoryChunk memoryChunk = this.memoryChunks[i]; if (ReferenceEquals(chunk.Memory, memoryChunk.Bytes)) { this.memoryChunks.Remove(memoryChunk); memoryChunk.Dispose(); break; } } }
/** * Add to cache if not already full. */ public bool Add(PoolChunk <T> chunk, long handle) { Entry entry = NewEntry(chunk, handle); bool queued = this.queue.TryEnqueue(entry); if (!queued) { // If it was not possible to cache the chunk, immediately recycle the entry entry.Recycle(); } return(queued); }
internal void Reallocate(PooledByteBuffer <T> buf, int newCapacity, bool freeOldMemory) { Contract.Requires(newCapacity >= 0 && newCapacity <= buf.MaxCapacity); int oldCapacity = buf.Length; if (oldCapacity == newCapacity) { return; } PoolChunk <T> oldChunk = buf.Chunk; long oldHandle = buf.Handle; T oldMemory = buf.Memory; int oldOffset = buf.Offset; int oldMaxLength = buf.MaxLength; int readerIndex = buf.ReaderIndex; int writerIndex = buf.WriterIndex; this.Allocate(this.Parent.ThreadCache <T>(), buf, newCapacity); if (newCapacity > oldCapacity) { this.MemoryCopy( oldMemory, oldOffset, buf.Memory, buf.Offset, oldCapacity); } else if (newCapacity < oldCapacity) { if (readerIndex < newCapacity) { if (writerIndex > newCapacity) { writerIndex = newCapacity; } this.MemoryCopy( oldMemory, oldOffset + readerIndex, buf.Memory, buf.Offset + readerIndex, writerIndex - readerIndex); } else { readerIndex = writerIndex = newCapacity; } } buf.SetIndex(readerIndex, writerIndex); if (freeOldMemory) { this.Free(oldChunk, oldHandle, oldMaxLength, buf.Cache); } }
void Init0(PoolChunk <T> chunk, long handle, int offset, int length, int maxLength, PoolThreadCache <T> cache) { Debug.Assert(handle >= 0); Debug.Assert(chunk != null); this.Chunk = chunk; this.Memory = chunk.Memory; this.allocator = chunk.Arena.Parent; this.Cache = cache; this.Handle = handle; this.Offset = offset; this.Length = length; this.MaxLength = maxLength; }
bool Move(PoolChunk <T> chunk) { Contract.Assert(chunk.Usage < this.maxUsage); if (chunk.Usage < this.minUsage) { // Move the PoolChunk down the PoolChunkList linked-list. return(this.Move0(chunk)); } // PoolChunk fits into this PoolChunkList, adding it here. this.Add0(chunk); return(true); }
/// Adds the {@link PoolChunk} to this {@link PoolChunkList}. void Add0(PoolChunk <T> chunk) { chunk.Parent = this; if (this.head == null) { this.head = chunk; chunk.Prev = null; chunk.Next = null; } else { chunk.Prev = null; chunk.Next = this.head; this.head.Prev = chunk; this.head = chunk; } }
void AllocateNormal(PooledByteBuffer <T> buf, int reqCapacity, int normCapacity) { if (this.q050.Allocate(buf, reqCapacity, normCapacity) || this.q025.Allocate(buf, reqCapacity, normCapacity) || this.q000.Allocate(buf, reqCapacity, normCapacity) || this.qInit.Allocate(buf, reqCapacity, normCapacity) || this.q075.Allocate(buf, reqCapacity, normCapacity)) { return; } // Add a new chunk. PoolChunk <T> c = this.NewChunk(this.PageSize, this.maxOrder, this.PageShifts, this.ChunkSize); long handle = c.Allocate(normCapacity); Debug.Assert(handle > 0); c.InitBuf(buf, handle, reqCapacity); this.qInit.Add(c); }
void Remove(PoolChunk <T> cur) { if (cur == this.head) { this.head = cur.Next; if (this.head != null) { this.head.Prev = null; } } else { PoolChunk <T> next = cur.Next; cur.Prev.Next = next; if (next != null) { next.Prev = cur.Prev; } } }
internal void Free(PoolChunk <T> chunk, long handle, int normCapacity, PoolThreadCache <T> cache) { if (chunk.Unpooled) { int size = chunk.ChunkSize; this.DestroyChunk(chunk); Interlocked.Add(ref this.activeBytesHuge, -size); Interlocked.Increment(ref this.deallocationsHuge); } else { SizeClass sizeClass = this.SizeClass(normCapacity); if (cache != null && cache.Add(this, chunk, handle, normCapacity, sizeClass)) { // cached so not free it. return; } this.FreeChunk(chunk, handle, sizeClass); } }
internal void Recycle() { this.Chunk = null; this.Handle = -1; this.recyclerHandle.Release(this); }
/** * Init the {@link PooledByteBuffer} using the provided chunk and handle with the capacity restrictions. */ protected abstract void InitBuf(PoolChunk <T> chunk, long handle, PooledByteBuffer <T> buf, int reqCapacity);
protected override void InitBuf( PoolChunk <T> chunk, long handle, PooledByteBuffer <T> buf, int reqCapacity) => chunk.InitBuf(buf, handle, reqCapacity);
protected internal override void DestroyChunk(PoolChunk <byte[]> chunk) { // Rely on GC. }
protected internal abstract void DestroyChunk(PoolChunk <T> chunk);
internal override void Init(PoolChunk <byte[]> chunk, long handle, int offset, int length, int maxLength, PoolThreadCache <byte[]> cache) { base.Init(chunk, handle, offset, length, maxLength, cache); this.InitMemoryAddress(); }
internal override void InitUnpooled(PoolChunk <byte[]> chunk, int length) { base.InitUnpooled(chunk, length); this.InitMemoryAddress(); }
internal virtual void InitUnpooled(PoolChunk <T> chunk, int length) => this.Init0(chunk, 0, 0, length, length, null);
internal virtual void Init(PoolChunk <T> chunk, long handle, int offset, int length, int maxLength, PoolThreadCache <T> cache) => this.Init0(chunk, handle, offset, length, maxLength, cache);