pooledmm.pp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. {
  2. $Id: header,v 1.1 2000/07/13 06:33:45 michael Exp $
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {
  12. Author: Mattias Gaertner
  13. Abstract:
  14. Defines TPooledMemManager, which is the base class for various
  15. memory managers in the lcl and its interfaces.
  16. An own memory manager is somewhat faster and makes debugging and
  17. profiling easier.
  18. }
  19. unit pooledmm;
  20. {$mode objfpc}{$H+}
  21. interface
  22. uses
  23. Classes;
  24. type
  25. PPooledMemManagerItem = ^TPooledMemManagerItem;
  26. TPooledMemManagerItem = record
  27. Next: PPooledMemManagerItem;
  28. end;
  29. { memory manager template }
  30. TPooledMemManager = class
  31. private
  32. procedure SetMaxFreeRatio(NewValue: integer);
  33. procedure SetMinFree(NewValue: integer);
  34. protected
  35. FFirstFree: PPooledMemManagerItem;
  36. FFreeCount: integer;
  37. FCount: integer;
  38. FMinFree: integer;
  39. FMaxFreeRatio: integer;
  40. FAllocatedCount: int64;
  41. FFreedCount: int64;
  42. procedure DisposeItem(AnItem: PPooledMemManagerItem);
  43. function NewItem: PPooledMemManagerItem;
  44. procedure FreeFirstItem; virtual;
  45. public
  46. property MinimumFreeCount: integer read FMinFree write SetMinFree;
  47. property MaximumFreeCountRatio: integer
  48. read FMaxFreeRatio write SetMaxFreeRatio; // in one eighth steps
  49. property Count: integer read FCount;
  50. property FreeCount: integer read FFreeCount;
  51. property AllocatedCount: int64 read FAllocatedCount;
  52. property FreedCount: int64 read FFreedCount;
  53. procedure Clear;
  54. constructor Create;
  55. destructor Destroy; override;
  56. end;
  57. { TNonFreePooledMemManager - a memory manager for records without freeing }
  58. TEnumItemsMethod = procedure(Item: Pointer) of object;
  59. TNonFreePooledMemManager = class
  60. private
  61. FItemSize: integer;
  62. FItems: TFPList;
  63. FCurItem: Pointer;
  64. FEndItem: Pointer;
  65. FCurSize: integer;
  66. FFirstSize: integer;
  67. public
  68. ClearOnCreate: boolean;
  69. property ItemSize: integer read FItemSize;
  70. procedure Clear;
  71. constructor Create(TheItemSize: integer);
  72. destructor Destroy; override;
  73. function NewItem: Pointer;
  74. procedure EnumerateItems(const Method: TEnumItemsMethod);
  75. end;
  76. implementation
  77. {$IFOpt R+}{$Define RangeChecksOn}{$Endif}
  78. { TPooledMemManager }
  79. procedure TPooledMemManager.Clear;
  80. begin
  81. while FFirstFree<>nil do begin
  82. FreeFirstItem;
  83. inc(FFreedCount);
  84. end;
  85. FFreeCount:=0;
  86. end;
  87. constructor TPooledMemManager.Create;
  88. begin
  89. inherited Create;
  90. FFirstFree:=nil;
  91. FFreeCount:=0;
  92. FCount:=0;
  93. FAllocatedCount:=0;
  94. FFreedCount:=0;
  95. FMinFree:=100000;
  96. FMaxFreeRatio:=8; // 1:1
  97. end;
  98. destructor TPooledMemManager.Destroy;
  99. begin
  100. Clear;
  101. inherited Destroy;
  102. end;
  103. procedure TPooledMemManager.DisposeItem(AnItem: PPooledMemManagerItem);
  104. begin
  105. if AnItem<>nil then begin
  106. if (FFreeCount<FMinFree) or (FFreeCount<((FCount shr 3)*FMaxFreeRatio)) then
  107. begin
  108. // add ANode to Free list
  109. //AddItemToFreeList(AnItem);
  110. inc(FFreeCount);
  111. end else begin
  112. // free list full -> free the ANode
  113. //FreeItem(AnItem);
  114. {$push}{$R-}
  115. inc(FFreedCount);
  116. {$pop}
  117. end;
  118. dec(FCount);
  119. end;
  120. end;
  121. function TPooledMemManager.NewItem: PPooledMemManagerItem;
  122. begin
  123. if FFirstFree<>nil then begin
  124. // take from free list
  125. Result:=FFirstFree;
  126. FFirstFree:=FFirstFree^.Next;
  127. Result^.Next:=nil;
  128. dec(FFreeCount);
  129. end else begin
  130. // free list empty -> create new node
  131. New(Result);
  132. {$push}{$R-}
  133. inc(FAllocatedCount);
  134. {$pop}
  135. end;
  136. inc(FCount);
  137. end;
  138. procedure TPooledMemManager.SetMaxFreeRatio(NewValue: integer);
  139. begin
  140. if NewValue<0 then NewValue:=0;
  141. if NewValue=FMaxFreeRatio then exit;
  142. FMaxFreeRatio:=NewValue;
  143. end;
  144. procedure TPooledMemManager.SetMinFree(NewValue: integer);
  145. begin
  146. if NewValue<0 then NewValue:=0;
  147. if NewValue=FMinFree then exit;
  148. FMinFree:=NewValue;
  149. end;
  150. procedure TPooledMemManager.FreeFirstItem;
  151. var Item: PPooledMemManagerItem;
  152. begin
  153. Item:=FFirstFree;
  154. FFirstFree:=FFirstFree^.Next;
  155. Dispose(Item);
  156. end;
  157. { TNonFreePooledMemManager }
  158. procedure TNonFreePooledMemManager.Clear;
  159. var
  160. i: Integer;
  161. p: Pointer;
  162. begin
  163. if FItems<>nil then begin
  164. for i:=0 to FItems.Count-1 do begin
  165. p:=FItems[i];
  166. FreeMem(p);
  167. end;
  168. FItems.Free;
  169. FItems:=nil;
  170. end;
  171. FCurItem:=nil;
  172. FEndItem:=nil;
  173. FCurSize:=FItemSize*4; // 4 items
  174. end;
  175. constructor TNonFreePooledMemManager.Create(TheItemSize: integer);
  176. begin
  177. FItemSize:=TheItemSize;
  178. FFirstSize:=FItemSize*4; // 4 items => the first item has 8 entries
  179. FCurSize:=FFirstSize;
  180. end;
  181. destructor TNonFreePooledMemManager.Destroy;
  182. begin
  183. Clear;
  184. inherited Destroy;
  185. end;
  186. function TNonFreePooledMemManager.NewItem: Pointer;
  187. begin
  188. if (FCurItem=FEndItem) then begin
  189. // each item has double the size of its predecessor
  190. inc(FCurSize,FCurSize);
  191. GetMem(FCurItem,FCurSize);
  192. if ClearOnCreate then
  193. FillChar(FCurItem^,FCurSize,0);
  194. if FItems=nil then FItems:=TFPList.Create;
  195. FItems.Add(FCurItem);
  196. FEndItem := FCurItem;
  197. Inc(FEndItem, FCurSize);
  198. end;
  199. Result:=FCurItem;
  200. Inc(FCurItem, FItemSize);
  201. end;
  202. procedure TNonFreePooledMemManager.EnumerateItems(
  203. const Method: TEnumItemsMethod);
  204. var
  205. Cnt: Integer;
  206. i: Integer;
  207. p: Pointer;
  208. Size: Integer;
  209. Last: Pointer;
  210. begin
  211. if FItems<>nil then begin
  212. Cnt:=FItems.Count;
  213. Size:=FFirstSize;
  214. for i:=0 to Cnt-1 do begin
  215. // each item has double the size of its predecessor
  216. inc(Size,Size);
  217. p:=FItems[i];
  218. Last := p;
  219. Inc(Last, Size);
  220. if i=Cnt-1 then
  221. Last:=FEndItem;
  222. while p<>Last do begin
  223. Method(p);
  224. Inc(p, FItemSize);
  225. end;
  226. end;
  227. end;
  228. end;
  229. end.