ArenaAllocator.cs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. using System.Collections.Generic;
  2. namespace Ryujinx.HLE.Memory
  3. {
  4. class ArenaAllocator
  5. {
  6. private class Region
  7. {
  8. public long Position { get; set; }
  9. public long Size { get; set; }
  10. public Region(long Position, long Size)
  11. {
  12. this.Position = Position;
  13. this.Size = Size;
  14. }
  15. }
  16. private LinkedList<Region> FreeRegions;
  17. public long TotalAvailableSize { get; private set; }
  18. public long TotalUsedSize { get; private set; }
  19. public ArenaAllocator(long ArenaSize)
  20. {
  21. TotalAvailableSize = ArenaSize;
  22. FreeRegions = new LinkedList<Region>();
  23. FreeRegions.AddFirst(new Region(0, ArenaSize));
  24. }
  25. public bool TryAllocate(long Size, out long Position)
  26. {
  27. LinkedListNode<Region> Node = FreeRegions.First;
  28. while (Node != null)
  29. {
  30. Region Rg = Node.Value;
  31. if ((ulong)Rg.Size >= (ulong)Size)
  32. {
  33. Position = Rg.Position;
  34. Rg.Position += Size;
  35. Rg.Size -= Size;
  36. TotalUsedSize += Size;
  37. return true;
  38. }
  39. Node = Node.Next;
  40. }
  41. Position = 0;
  42. return false;
  43. }
  44. public void Free(long Position, long Size)
  45. {
  46. long End = Position + Size;
  47. Region NewRg = new Region(Position, Size);
  48. LinkedListNode<Region> Node = FreeRegions.First;
  49. LinkedListNode<Region> PrevSz = Node;
  50. while (Node != null)
  51. {
  52. LinkedListNode<Region> NextNode = Node.Next;
  53. Region Rg = Node.Value;
  54. long RgEnd = Rg.Position + Rg.Size;
  55. if (Rg.Position == End)
  56. {
  57. NewRg.Size += Rg.Size;
  58. FreeRegions.Remove(Node);
  59. }
  60. else if (RgEnd == Position)
  61. {
  62. NewRg.Position = Rg.Position;
  63. NewRg.Size += Rg.Size;
  64. FreeRegions.Remove(Node);
  65. }
  66. else if ((ulong)Rg.Size < (ulong)NewRg.Size &&
  67. (ulong)Rg.Size > (ulong)PrevSz.Value.Size)
  68. {
  69. PrevSz = Node;
  70. }
  71. Node = NextNode;
  72. }
  73. if ((ulong)PrevSz.Value.Size < (ulong)Size)
  74. {
  75. FreeRegions.AddAfter(PrevSz, NewRg);
  76. }
  77. else
  78. {
  79. FreeRegions.AddFirst(NewRg);
  80. }
  81. TotalUsedSize -= Size;
  82. }
  83. }
  84. }