private void UnlikelyEnsureSingleChunk(out byte *ptr, out int size) { // we are using multiple segments, but the current one can fit all // the required memory if (_head.Allocation.SizeInBytes - _head.Used > SizeInBytes) { CopyTo(_head.Address + _head.Used); // we need to fit in the beginning of the chunk, so we must move it backward. Memory.Move(_head.Address, _head.Address + _head.Used, SizeInBytes); ptr = _head.Address; size = SizeInBytes; _head.Used = SizeInBytes; // Ensure we are thought of as a single chunk _head.Previous = null; return; } var totalSize = SizeInBytes; // We might need to allocate, but we don't want to allocate the usual power of 2 * 3 // because we know _exactly_ what we need using (_context.AvoidOverAllocation()) { // If we are here, then we have multiple chunks, we can't // allow a growth of the last chunk, since we'll by copying over it // so we force a whole new chunk AllocateNextSegment(totalSize, false); } // Go back in time to before we had the last chunk var realHead = _head; _head = realHead.Previous; // Copy all of the data structure into the new chunk's memory CopyTo(realHead.Address); realHead.Used = totalSize; realHead.AccumulatedSizeInBytes = totalSize; // Back to the future! _head = realHead; // Ensure we are thought of as a single chunk _head.Previous = null; ptr = _head.Address; size = _head.Used; }