Exemple #1
0
        private void AllocateNextSegment(int required, bool allowGrowth)
        {
            Debug.Assert(required > 0);

            // Grow by doubling segment size until we get to 1 MB, then just use 1 MB segments
            // otherwise a document with 17 MB will waste 15 MB and require very big allocations
            var powerOfTwoRequestSize = Bits.NextPowerOf2(required);
            var segmentSize           = Math.Max(powerOfTwoRequestSize, _head.Allocation.SizeInBytes * 2);

            if (powerOfTwoRequestSize < segmentSize ||
                segmentSize > ArenaMemoryAllocator.MaxArenaSize)
            {
                // don't grow _too_ much.
                segmentSize = powerOfTwoRequestSize;
            }
            const int oneMb = 1024 * 1024;

            if (segmentSize > oneMb && required <= oneMb)
            {
                segmentSize = oneMb;
            }

            // We can sometimes ask the context to grow the allocation size;
            // it may do so at its own discretion; if this happens, then we
            // are good to go.
            if (allowGrowth && _context.GrowAllocation(_head.Allocation, segmentSize))
            {
                return;
            }

            // Can't change _head because there may be copies of the current
            // instance of UnmanagedWriteBuffer going around. Thus, we simply
            // mutate it to ensure all copies have the same allocations.
            var allocation = _context.GetMemory(segmentSize);

            // Copy the head
            Segment previousHead = _head.ShallowCopy();

            // Reset the head (this change happens in all instances at the
            // same time, albeit not atomically).
            _head.Previous = previousHead;
            _head.DeallocationPendingPrevious = previousHead;
            _head.Allocation             = allocation;
            _head.Address                = allocation.Address;
            _head.Used                   = 0;
            _head.AccumulatedSizeInBytes = previousHead.AccumulatedSizeInBytes;
        }