Exemplo n.º 1
0
        public void Layout(MemoryRegion region)
        {
            var itemsBySize            = region.Items.OrderByDescending(item => item.Size);
            SortedSet <MemRgn> freeSet = new SortedSet <MemRgn>();
            MemRgn             top     = new MemRgn(0, long.MaxValue);

            freeSet.Add(top);
            uint  alignment    = region.MarshalInfo.Alignment;
            bool  alignPow2    = region.MarshalInfo.UseStrongPow2Alignment;
            ulong requiredSize = 0;

            foreach (MemoryMappedStorage item in itemsBySize)
            {
                MemRgn req   = new MemRgn(0, item.Size);
                var    avail = freeSet.GetViewBetween(req, top);
                bool   found = false;
                foreach (MemRgn rgn in avail)
                {
                    ulong offset = rgn.Offset;
                    offset = MathExt.Align(offset, alignment);
                    if (alignPow2)
                    {
                        ulong alignedSize = MathExt.CeilPow2(item.Size);
                        offset = (offset + alignedSize - 1) & ~(alignedSize - 1);
                    }
                    if (offset + item.Size <= rgn.Offset + rgn.Size)
                    {
                        item.Offset = offset;
                        freeSet.Remove(rgn);
                        if (rgn.Offset < offset)
                        {
                            MemRgn left = new MemRgn(rgn.Offset, offset - rgn.Offset);
                            freeSet.Add(left);
                        }
                        if (offset + item.Size < rgn.Offset + rgn.Size)
                        {
                            MemRgn right = new MemRgn(offset + item.Size, rgn.Offset + rgn.Size - offset - item.Size);
                            freeSet.Add(right);
                        }
                        requiredSize = Math.Max(requiredSize, offset + item.Size);
                        found        = true;
                        break;
                    }
                }
                if (!found)
                {
                    throw new MemoryLayoutFailedException();
                }
                region.RequiredSize = requiredSize;
            }
            region.Seal();
        }