コード例 #1
0
        private void AllocateNextSegment(int required, bool allowGrowth)
        {
            //TODO: protect from documents larger than 1GB

            // 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       nextSegmentSize = Math.Max(Bits.NextPowerOf2(required), _current.Allocation.SizeInBytes * 2);
            const int oneMb           = 1024 * 1024;

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

            if (allowGrowth &&
                // we successfully grew the allocation, nothing to do
                _context.GrowAllocation(_current.Allocation, nextSegmentSize))
            {
                return;
            }

            var allocatedMemoryData = _context.GetMemory(nextSegmentSize);

            _current = new Segment
            {
                Address           = (byte *)allocatedMemoryData.Address,
                Allocation        = allocatedMemoryData,
                Used              = 0,
                Previous          = _current,
                PreviousAllocated = _current
            };
        }
コード例 #2
0
        private void AllocateNextSegment(int required, bool allowGrowth)
        {
            Debug.Assert(required > 0);

            if (required > ArenaMemoryAllocator.MaxArenaSize)
            {
                ThrowOnAllocationSizeExceeded(required, ArenaMemoryAllocator.MaxArenaSize);
            }

            // 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       requiredPowerOfTwo = Bits.PowerOf2(required);
            var       segmentSize        = Math.Max(requiredPowerOfTwo, _head.Allocation.SizeInBytes * 2);
            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);

            if (allocation.SizeInBytes < required)
            {
                ThrowOnAllocationSizeMismatch(allocation.SizeInBytes, required);
            }

            // 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;
        }