COMPACT.MOD 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. IMPLEMENTATION MODULE Compact;
  2. (* A memory handler that allows the heap to be compacted *)
  3. (* For the time being will only work with one 64K segment *)
  4. (* Note that this is for demonstration purposes and therefore is designed
  5. to be visible rather than fast. A rewrite would be in order before using
  6. this thing in anger*)
  7. IMPORT Storage,Lib;
  8. VAR
  9. Head:MemRecP; (* If more that one segment this would be more complex *)
  10. NextHandle:HandleType;
  11. PROCEDURE MergeBlanks();
  12. VAR
  13. Finger:MemRecP;
  14. BEGIN
  15. Finger:=Head;
  16. WHILE (Finger<>NIL) AND (Finger^.Next<>NIL) DO
  17. IF (Finger^.Handle=NotAHandle) AND (Finger^.Next^.Handle=NotAHandle) THEN
  18. Finger^.Length:=Finger^.Length+Finger^.Next^.Length+SIZE(MemRec);
  19. Finger^.Next:=Finger^.Next^.Next
  20. ELSE
  21. Finger:=Finger^.Next;
  22. END;
  23. END
  24. END MergeBlanks;
  25. PROCEDURE Deallocate(x:HandleType);
  26. VAR
  27. Finger:MemRecP;
  28. BEGIN
  29. Finger:=Head;
  30. WHILE (Finger<>NIL) AND (Finger^.Handle<>x) DO
  31. Finger:=Finger^.Next
  32. END;
  33. IF Finger<>NIL THEN
  34. Finger^.Handle:=NotAHandle;
  35. MergeBlanks();
  36. END
  37. END Deallocate;
  38. PROCEDURE CompactMemory();
  39. VAR
  40. Temp,Finger:MemRecP;
  41. OldSize,ComingSize:CARDINAL;
  42. BEGIN
  43. Finger:=Head;
  44. WHILE (Finger<>NIL) AND (Finger^.Next<>NIL) DO
  45. IF Finger^.Handle=NotAHandle THEN (* Two blanks so merge *)
  46. ComingSize:=Finger^.Next^.Length+SIZE(MemRec);
  47. IF Finger^.Next^.Handle=NotAHandle THEN
  48. Finger^.Length:=Finger^.Length+ComingSize;
  49. Finger^.Next:=Finger^.Next^.Next;
  50. ELSE
  51. OldSize:=Finger^.Length;
  52. Lib.Move(Finger^.Next,Finger,ComingSize); (* Move data down *)
  53. Temp:=Lib.AddAddr(Finger,ComingSize); (* Create the new blank record *)
  54. Temp^.Handle:=NotAHandle;
  55. Temp^.Length:=OldSize;
  56. Temp^.Next:=Finger^.Next;
  57. Finger^.Next:=Temp;
  58. END
  59. ELSE
  60. Finger:=Finger^.Next;
  61. END
  62. END;
  63. END CompactMemory;
  64. PROCEDURE DerefHandle(x:HandleType):ADDRESS;
  65. VAR
  66. Finger:MemRecP;
  67. BEGIN
  68. Finger:=Head;
  69. WHILE (Finger<>NIL) AND (Finger^.Handle<>x) DO
  70. Finger:=Finger^.Next
  71. END;
  72. IF Finger=NIL THEN
  73. RETURN ADDRESS(0)
  74. ELSE
  75. RETURN Lib.AddAddr(Finger,SIZE(MemRec))
  76. END
  77. END DerefHandle;
  78. PROCEDURE Allocate(size:CARDINAL):HandleType;
  79. VAR
  80. SecondTry:BOOLEAN;
  81. Value:HandleType;
  82. Temp,Finger:MemRecP;
  83. BEGIN
  84. SecondTry:=TRUE;
  85. IF size<SmallestAlloc THEN
  86. size:=SmallestAlloc
  87. END;
  88. Value:=NotAHandle;
  89. REPEAT
  90. SecondTry:=NOT SecondTry;
  91. Finger:=Head;
  92. WHILE (Finger<>NIL) AND (
  93. (Finger^.Handle<>NotAHandle) OR (Finger^.Length<size)) DO
  94. Finger:=Finger^.Next
  95. END;
  96. IF Finger=NIL THEN
  97. IF NOT SecondTry THEN
  98. CompactMemory
  99. END
  100. ELSE
  101. INC(NextHandle);
  102. Value:=NextHandle;
  103. IF Finger^.Length>size+SIZE(MemRec) THEN (* Insert new blank record *)
  104. Temp:=Lib.AddAddr(Finger,size+SIZE(MemRec));
  105. Temp^.Length:=Finger^.Length-size-SIZE(MemRec);
  106. Temp^.Handle:=NotAHandle;
  107. Temp^.Next:=Finger^.Next;
  108. Finger^.Next:=Temp;
  109. Finger^.Length:=size;
  110. ELSE
  111. size:=Finger^.Length;
  112. END;
  113. Finger^.Handle:=Value;
  114. END;
  115. UNTIL SecondTry OR (Value<>NotAHandle);
  116. RETURN Value;
  117. END Allocate;
  118. BEGIN
  119. Storage.ALLOCATE(Head,64*1024);
  120. Head^.Length:=64*1024-SIZE(MemRec);
  121. Head^.Next:=NIL;
  122. Head^.Handle:=MAX(CARDINAL);
  123. NextHandle:=NotAHandle;
  124. END Compact.