Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

402 lines
13 KiB

  1. #ifndef _POOL_HPP_
  2. #define _POOL_HPP_
  3. // Ruler
  4. // 1 2 3 4 5 6 7 8
  5. //345678901234567890123456789012345678901234567890123456789012345678901234567890
  6. /********************************************************************/
  7. /* */
  8. /* The standard layout. */
  9. /* */
  10. /* The standard layout for 'hpp' files for this code is as */
  11. /* follows: */
  12. /* */
  13. /* 1. Include files. */
  14. /* 2. Constants exported from the class. */
  15. /* 3. Data structures exported from the class. */
  16. /* 4. Forward references to other data structures. */
  17. /* 5. Class specifications (including inline functions). */
  18. /* 6. Additional large inline functions. */
  19. /* */
  20. /* Any portion that is not required is simply omitted. */
  21. /* */
  22. /********************************************************************/
  23. #include "Global.hpp"
  24. #include "Delay.hpp"
  25. #include "Lock.hpp"
  26. #include "New.hpp"
  27. #include "Stack.hpp"
  28. #include "Vector.hpp"
  29. /********************************************************************/
  30. /* */
  31. /* Constants exported from the class. */
  32. /* */
  33. /* The server constants specify the size of the server queue */
  34. /* per processor stacks. */
  35. /* */
  36. /********************************************************************/
  37. CONST SBIT16 MinPoolSize = 64;
  38. CONST SBIT16 PoolStackSize = 32;
  39. /********************************************************************/
  40. /* */
  41. /* Pools and pool management. */
  42. /* */
  43. /* This class provides general purpose memory pool along with */
  44. /* basic management. The pools are optimized for very high */
  45. /* performance on SMP systems (although this calls does not */
  46. /* perform the actual locking. Whenever possible multiple */
  47. /* items should allocated and deallocated at the same time. */
  48. /* */
  49. /********************************************************************/
  50. template <class TYPE,class LOCK=NO_LOCK> class POOL : public LOCK
  51. {
  52. //
  53. // Private type definitions.
  54. //
  55. typedef struct { CHAR TypeSize[sizeof(TYPE)]; } TYPE_SIZE;
  56. //
  57. // Private data.
  58. //
  59. SBIT32 MaxSize;
  60. SBIT32 MinSize;
  61. DELAY< VECTOR<TYPE_SIZE> > Delay;
  62. STACK<POINTER> Stack;
  63. public:
  64. //
  65. // Public functions.
  66. //
  67. POOL( SBIT32 NewMinSize = MinPoolSize );
  68. TYPE **MultiplePopPool
  69. (
  70. SBIT32 Requested,
  71. SBIT32 *Size
  72. );
  73. VOID MultiplePushPool
  74. (
  75. CONST TYPE *Type[],
  76. CONST SBIT32 Size
  77. );
  78. TYPE *PopPool( VOID );
  79. VOID PushPool( CONST TYPE *Type );
  80. ~POOL( VOID );
  81. private:
  82. //
  83. // Private functions.
  84. //
  85. VOID ExpandSize( SBIT32 MaxSize );
  86. //
  87. // Disabled operations.
  88. //
  89. POOL( CONST POOL & Copy );
  90. VOID operator=( CONST POOL & Copy );
  91. };
  92. /********************************************************************/
  93. /* */
  94. /* Class constructor. */
  95. /* */
  96. /* Create a new pool and prepare it for use. This call is */
  97. /* not thread safe and should only be made in a single thread */
  98. /* environment. */
  99. /* */
  100. /********************************************************************/
  101. template <class TYPE,class LOCK> POOL<TYPE,LOCK>::POOL( SBIT32 NewMinSize ) :
  102. //
  103. // Call the constructors for the contained classes.
  104. //
  105. Stack( NewMinSize )
  106. {
  107. #ifdef DEBUGGING
  108. if ( NewMinSize > 0 )
  109. {
  110. #endif
  111. //
  112. // We need to keep a note of the amount of elements
  113. // we have allocated so far.
  114. //
  115. MaxSize = 0;
  116. MinSize = NewMinSize;
  117. #ifdef DEBUGGING
  118. }
  119. else
  120. { Failure( "Min size in constructor for POOL" ); }
  121. #endif
  122. }
  123. /********************************************************************/
  124. /* */
  125. /* Expand size. */
  126. /* */
  127. /* Expand the current memory allocation. This call is not */
  128. /* thread safe and should only be made in a single thread */
  129. /* environment. */
  130. /* */
  131. /********************************************************************/
  132. template <class TYPE,class LOCK> VOID POOL<TYPE,LOCK>::ExpandSize
  133. (
  134. SBIT32 NewSize
  135. )
  136. {
  137. REGISTER SBIT32 Count1;
  138. REGISTER SBIT32 Count2;
  139. REGISTER SBIT32 ActualSize =
  140. ((NewSize <= MinSize) ? MinSize : NewSize);
  141. REGISTER VECTOR<TYPE> *NewBlock =
  142. (
  143. (VECTOR<TYPE>*) new VECTOR<TYPE_SIZE>
  144. (
  145. ActualSize,
  146. CacheLineSize,
  147. CacheLineSize
  148. )
  149. );
  150. //
  151. // We need to keep a note of the number of elements
  152. // we have allocated thus far.
  153. //
  154. MaxSize += ActualSize;
  155. //
  156. // We put the address of each element we allocate on
  157. // a stack to enable high speed allocation and
  158. // deallocation.
  159. //
  160. for
  161. (
  162. Count1 = 0;
  163. Count1 < ActualSize;
  164. Count1 += PoolStackSize
  165. )
  166. {
  167. AUTO POINTER NewCalls[ PoolStackSize ];
  168. //
  169. // We add elements to the stack in blocks
  170. // to reduce the number of call to the
  171. // stack code.
  172. //
  173. for
  174. (
  175. Count2 = 0;
  176. ((Count1 + Count2) < ActualSize)
  177. &&
  178. (Count2 < PoolStackSize);
  179. Count2 ++
  180. )
  181. {
  182. REGISTER TYPE *NewCall =
  183. (
  184. & (*NewBlock)[ (Count1 + Count2) ]
  185. );
  186. NewCalls[ Count2 ] = (POINTER) NewCall;
  187. }
  188. //
  189. // Add the next block for free work packets to
  190. // the global free stack.
  191. //
  192. Stack.MultiplePushStack
  193. (
  194. NewCalls,
  195. Count2
  196. );
  197. }
  198. //
  199. // Add the newly allocated block to the list of
  200. // things to be deleted when this class is deleted.
  201. //
  202. Delay.DeferedDelete( ((VECTOR<TYPE_SIZE>*) NewBlock) );
  203. }
  204. /********************************************************************/
  205. /* */
  206. /* Remove multiple items from the pool. */
  207. /* */
  208. /* We allocate a multiple elements from the allocation pool. */
  209. /* */
  210. /********************************************************************/
  211. template <class TYPE,class LOCK> INLINE TYPE **POOL<TYPE,LOCK>::MultiplePopPool
  212. (
  213. SBIT32 Requested,
  214. SBIT32 *Size
  215. )
  216. {
  217. AUTO TYPE *Type[ PoolStackSize ];
  218. REGISTER SBIT32 Count;
  219. //
  220. // Compute the actual request size.
  221. //
  222. Requested = ((Requested <= PoolStackSize) ? Requested : PoolStackSize);
  223. //
  224. // Claim an exclisive lock (if enabled).
  225. //
  226. ClaimExclusiveLock();
  227. //
  228. // Extract as may elements from the stack as possible.
  229. // If the stack is empty then allocate more.
  230. //
  231. while ( ! Stack.MultiplePopStack( Requested,(POINTER*) Type,Size ) )
  232. { ExpandSize( MaxSize ); }
  233. //
  234. // Release and lock we claimed earlier.
  235. //
  236. ReleaseExclusiveLock();
  237. //
  238. // Call the constructors.
  239. //
  240. for ( Count=0;Count < (*Size); Count ++ )
  241. { (VOID) PLACEMENT_NEW( NewPool[ Count ], TYPE ); }
  242. return Type;
  243. }
  244. /********************************************************************/
  245. /* */
  246. /* Add multiple items to the pool. */
  247. /* */
  248. /* We push multiple existing elements into the pool for reuse. */
  249. /* */
  250. /********************************************************************/
  251. template <class TYPE,class LOCK> INLINE VOID POOL<TYPE,LOCK>::MultiplePushPool
  252. (
  253. CONST TYPE *Type[],
  254. CONST SBIT32 Size
  255. )
  256. {
  257. REGISTER SBIT32 Count;
  258. //
  259. // Call the destructors.
  260. //
  261. for ( Count=(Size - 1);Count >= 0; Count -- )
  262. { PLACEMENT_DELETE( Type[ Count ],TYPE ); }
  263. //
  264. // Claim an exclisive lock (if enabled).
  265. //
  266. ClaimExclusiveLock();
  267. //
  268. // Push the elements back onto the free stack.
  269. //
  270. Stack.MultiplePushStack( (POINTER*) Type,Size );
  271. //
  272. // Release and lock we claimed earlier.
  273. //
  274. ReleaseExclusiveLock();
  275. }
  276. /********************************************************************/
  277. /* */
  278. /* Remove a single item from the pool. */
  279. /* */
  280. /* We allocate a new element from the allocation pool. */
  281. /* */
  282. /********************************************************************/
  283. template <class TYPE,class LOCK> INLINE TYPE *POOL<TYPE,LOCK>::PopPool( VOID )
  284. {
  285. AUTO TYPE *Type;
  286. //
  287. // Claim an exclisive lock (if enabled).
  288. //
  289. ClaimExclusiveLock();
  290. //
  291. // We pop an element off the stack if the
  292. // stack is empty we create more elements.
  293. //
  294. while ( ! Stack.PopStack( (POINTER*) & Type ) )
  295. { ExpandSize( MaxSize ); }
  296. //
  297. // Release and lock we claimed earlier.
  298. //
  299. ReleaseExclusiveLock();
  300. //
  301. // Call the constructor.
  302. //
  303. (VOID) PLACEMENT_NEW( Type, TYPE );
  304. return Type;
  305. }
  306. /********************************************************************/
  307. /* */
  308. /* Add a single item to the pool. */
  309. /* */
  310. /* We push an existing element into the pool for reuse. */
  311. /* */
  312. /********************************************************************/
  313. template <class TYPE,class LOCK> INLINE VOID POOL<TYPE,LOCK>::PushPool
  314. (
  315. CONST TYPE *Type
  316. )
  317. {
  318. //
  319. // Call the destructor.
  320. //
  321. PLACEMENT_DELETE( Type,TYPE );
  322. //
  323. // Claim an exclisive lock (if enabled).
  324. //
  325. ClaimExclusiveLock();
  326. //
  327. // Push the element back onto the free stack.
  328. //
  329. Stack.PushStack( (POINTER) Type );
  330. //
  331. // Release and lock we claimed earlier.
  332. //
  333. ReleaseExclusiveLock();
  334. }
  335. /********************************************************************/
  336. /* */
  337. /* Class destructor. */
  338. /* */
  339. /* Destory the stack. This call is not thread safe and should */
  340. /* only be made in a single thread environment. */
  341. /* */
  342. /********************************************************************/
  343. template <class TYPE,class LOCK> POOL<TYPE,LOCK>::~POOL( VOID )
  344. { /* void */ }
  345. #endif