void FreeEntry(Entry entry) { PoolChunk <T> chunk = entry.Chunk; long handle = entry.Handle; // recycle now so PoolChunk can be GC'ed. entry.Recycle(); chunk.Arena.FreeChunk(chunk, handle, this.sizeClass); }
/** * Add {@link PoolChunk} and {@code handle} to the cache if there is enough room. * Returns {@code true} if it fit into the cache {@code false} otherwise. */ internal bool Add(PoolArena <T> area, PoolChunk <T> chunk, long handle, int normCapacity, SizeClass sizeClass) { MemoryRegionCache c = this.Cache(area, normCapacity, sizeClass); if (c == null) { return(false); } return(c.Add(chunk, handle)); }
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); }
/// 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._freeBytes > _freeMaxThreshold) { Remove(chunk); // Move the PoolChunk down the PoolChunkList linked-list. return(Move0(chunk)); } return(true); }
protected internal sealed override void Deallocate() { if (this.Handle >= 0) { long handle = this.Handle; this.Handle = -1; this.Memory = default(T); this.Chunk.Arena.Free(this.Chunk, handle, this.MaxLength, this.Cache); this.Chunk = null; this.Recycle(); } }
IEnumerator <IPoolChunkMetric> GetEnumeratorInternal() { lock (this.arena) { for (PoolChunk <T> cur = this.head; cur != null;) { yield return(cur); cur = cur.Next; } } }
internal void Destroy(PoolArena <T> poolArena) { PoolChunk <T> chunk = _head; while (chunk is object) { poolArena.DestroyChunk(chunk); chunk = chunk.Next; } _head = null; }
internal void Destroy(PoolArena <T> poolArena) { PoolChunk <T> chunk = this.head; while (chunk != null) { poolArena.DestroyChunk(chunk); chunk = chunk.Next; } this.head = null; }
internal void InitUnpooled(PoolChunk <T> chunk, int length) { Contract.Assert(chunk != null); this.Chunk = chunk; this.Handle = 0; this.Memory = chunk.Memory; this.Offset = 0; this.Length = this.MaxLength = length; this.SetIndex(0, 0); //tmpNioBuf = null; this.Cache = null; }
protected internal override void DestroyChunk(PoolChunk <byte[]> chunk) { for (int i = 0; i < _memoryChunks.Count; i++) { MemoryChunk memoryChunk = _memoryChunks[i]; if (ReferenceEquals(chunk.Memory, memoryChunk.Bytes)) { _ = _memoryChunks.Remove(memoryChunk); memoryChunk.Dispose(); break; } } }
/// <summary> /// Add to cache if not already full. /// </summary> public bool Add(PoolChunk <T> chunk, long handle) { Entry entry = NewEntry(chunk, handle); bool queued = _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); } }
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); }
bool Move(PoolChunk <T> chunk) { Debug.Assert(chunk.Usage < _maxUsage); if (chunk._freeBytes > _freeMaxThreshold) { // Move the PoolChunk down the PoolChunkList linked-list. return(Move0(chunk)); } // PoolChunk fits into this PoolChunkList, adding it here. Add0(chunk); return(true); }
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; }
unsafe void Init0(PoolChunk <T> chunk, long handle, int offset, int length, int maxLength, PoolThreadCache <T> cache) { Debug.Assert(handle >= 0); Debug.Assert(chunk is object); Chunk = chunk; Memory = chunk.Memory; _allocator = chunk.Arena.Parent; Origin = chunk.NativePointer; Cache = cache; Handle = handle; Offset = offset; Length = length; MaxLength = maxLength; }
internal void Init(PoolChunk <T> chunk, long handle, int offset, int length, int maxLength, PoolThreadCache <T> cache) { Contract.Assert(handle >= 0); Contract.Assert(chunk != null); this.Chunk = chunk; this.Handle = handle; this.Memory = chunk.Memory; this.Offset = offset; this.Length = length; this.MaxLength = maxLength; this.SetIndex(0, 0); this.DiscardMarkers(); //tmpNioBuf = null; this.Cache = cache; }
/// 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); }
public IEnumerator <IPoolChunkMetric> GetEnumerator() { lock (_arena) { if (_head is null) { return(Enumerable.Empty <IPoolChunkMetric>().GetEnumerator()); } var metrics = new List <IPoolChunkMetric>(); for (PoolChunk <T> cur = _head; cur is object;) { metrics.Add(cur); cur = cur.Next; } return(metrics.GetEnumerator()); } }
/// Adds the {@link PoolChunk} to this {@link PoolChunkList}. void Add0(PoolChunk <T> chunk) { chunk.Parent = this; if (_head is null) { _head = chunk; chunk.Prev = null; chunk.Next = null; } else { chunk.Prev = null; chunk.Next = _head; _head.Prev = chunk; _head = chunk; } }
void AllocateNormal(PooledByteBuffer <T> buf, int reqCapacity, int normCapacity, PoolThreadCache <T> threadCache) { if (_q050.Allocate(buf, reqCapacity, normCapacity, threadCache) || _q025.Allocate(buf, reqCapacity, normCapacity, threadCache) || _q000.Allocate(buf, reqCapacity, normCapacity, threadCache) || _qInit.Allocate(buf, reqCapacity, normCapacity, threadCache) || _q075.Allocate(buf, reqCapacity, normCapacity, threadCache)) { return; } // Add a new chunk. PoolChunk <T> c = NewChunk(PageSize, _maxOrder, PageShifts, ChunkSize); bool success = c.Allocate(buf, reqCapacity, normCapacity, threadCache); Debug.Assert(success); _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; } } }
void Remove(PoolChunk <T> cur) { if (cur == _head) { _head = cur.Next; if (_head is object) { _head.Prev = null; } } else { PoolChunk <T> next = cur.Next; cur.Prev.Next = next; if (next is object) { 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.Decrement(ref this.deallocationsHuge); } else { SizeClass sc = this.SizeClass(normCapacity); if (cache != null && cache.Add(this, chunk, handle, normCapacity, sc)) { // cached so not free it. return; } this.FreeChunk(chunk, handle, sc); } }
internal void Free(PoolChunk <T> chunk, long handle, int normCapacity, PoolThreadCache <T> cache) { if (chunk.Unpooled) { int size = chunk.ChunkSize; DestroyChunk(chunk); _ = Interlocked.Add(ref _activeBytesHuge, -size); _ = Interlocked.Increment(ref _deallocationsHuge); } else { SizeClass sizeClass = SizeClass(normCapacity); if (cache is object && cache.Add(this, chunk, handle, normCapacity, sizeClass)) { // cached so not free it. return; } FreeChunk(chunk, handle, sizeClass, false); } }
internal void Reallocate(PooledByteBuffer <T> buf, int newCapacity, bool freeOldMemory) { if (/*newCapacity < 0 || */ (uint)newCapacity > (uint)buf.MaxCapacity) { ThrowHelper.ThrowIndexOutOfRangeException(); } 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; // This does not touch buf's reader/writer indices Allocate(Parent.ThreadCache <T>(), buf, newCapacity); int bytesToCopy; if (newCapacity > oldCapacity) { bytesToCopy = oldCapacity; } else { buf.TrimIndicesToCapacity(newCapacity); bytesToCopy = newCapacity; } MemoryCopy(oldMemory, oldOffset, buf.Memory, buf.Offset, bytesToCopy); if (freeOldMemory) { Free(oldChunk, oldHandle, oldMaxLength, buf.Cache); } }
public override string ToString() { if (this.head == null) { return("none"); } var buf = new StringBuilder(); for (PoolChunk <T> cur = this.head;;) { buf.Append(cur); cur = cur.Next; if (cur == null) { break; } buf.Append(Environment.NewLine); // todo: StringUtil.NEWLINE } return(buf.ToString()); }
internal bool Allocate(PooledByteBuffer <T> buf, int reqCapacity, int normCapacity, PoolThreadCache <T> threadCache) { if (_head is null || normCapacity > _maxCapacity) { // Either this PoolChunkList is empty or the requested capacity is larger then the capacity which can // be handled by the PoolChunks that are contained in this PoolChunkList. return(false); } for (PoolChunk <T> cur = _head; cur is object; cur = cur.Next) { if (cur.Allocate(buf, reqCapacity, normCapacity, threadCache)) { if (cur._freeBytes <= _freeMinThreshold) { Remove(cur); _nextList.Add(cur); } return(true); } } return(false); }