Source code of Windows XP (NT5)
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.

221 lines
5.6 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1996, Microsoft Corporation
  4. //
  5. // File: tpriq.hxx
  6. //
  7. // Contents: priority queue template
  8. //
  9. // Classes: TPriorityQueue
  10. //
  11. // History: 12-Jan-96 dlee Created
  12. //
  13. //----------------------------------------------------------------------------
  14. #pragma once
  15. //+---------------------------------------------------------------------------
  16. //
  17. // Class: TPriorityQueue
  18. //
  19. // Purpose: Priority queue class implemented using a sorted array.
  20. //
  21. // History: 12-Jan-96 dlee Created
  22. //
  23. // Notes: Class T must implement two methods:
  24. //
  25. // BOOL IsGreaterThan( T & rItem )
  26. //
  27. // returns TRUE if "this" is greater than rItem
  28. //
  29. // unsigned GetSize()
  30. //
  31. // returns size of the item, generally 1
  32. //
  33. //----------------------------------------------------------------------------
  34. template <class T> class TPriorityQueue
  35. {
  36. public:
  37. TPriorityQueue( BOOL fSizeIsOne,
  38. unsigned maxTotalSize ) :
  39. _maxTotalSize( maxTotalSize ),
  40. _curSize( 0 ),
  41. _aItems( fSizeIsOne ? maxTotalSize : 16 )
  42. {
  43. }
  44. ~TPriorityQueue() {}
  45. BOOL DeQueue( T & rItem );
  46. void EnQueue( T & rItem );
  47. BOOL ShouldEnQueue( T & rItem, unsigned & cDeQueue );
  48. void Remove( unsigned iItem );
  49. T & PeekTop()
  50. {
  51. Win4Assert( 0 != Count() );
  52. return _aItems[ 0 ];
  53. }
  54. T & Peek( unsigned iItem )
  55. {
  56. // Peek() is not guaranteed to return the items in any given order
  57. Win4Assert( iItem < Count() );
  58. return _aItems[ iItem ];
  59. }
  60. unsigned CurrentSize() { return _curSize; }
  61. unsigned Count() { return _aItems.Count(); }
  62. unsigned MaxTotalSize() { return _maxTotalSize; }
  63. private:
  64. unsigned _maxTotalSize;
  65. unsigned _curSize;
  66. CDynArrayInPlace<T> _aItems;
  67. };
  68. //+-------------------------------------------------------------------------
  69. //
  70. // Member: CPriorityQueue::DeQueue, public
  71. //
  72. // Synopsis: Removes the highest-most priority item.
  73. //
  74. // History: 12-Jan-96 dlee Created
  75. //
  76. //--------------------------------------------------------------------------
  77. template<class T> BOOL TPriorityQueue<T>::DeQueue(
  78. T & rItem )
  79. {
  80. if ( 0 != _aItems.Count() )
  81. {
  82. // Return the item at the top of the queue
  83. rItem = _aItems[0];
  84. _curSize -= rItem.GetSize();
  85. _aItems.Remove( 0 );
  86. vqDebugOut( ( DEB_TRACE,
  87. "TPriorityQueue::DeQueue, %d items remain\n",
  88. Count() ) );
  89. return TRUE;
  90. }
  91. return FALSE;
  92. } //DeQueue
  93. template<class T> void TPriorityQueue<T>::EnQueue(
  94. T & rItem )
  95. {
  96. // Find the insertion point
  97. for ( unsigned i = 0; i < _aItems.Count(); i++ )
  98. {
  99. if ( !_aItems[ i ].IsGreaterThan( rItem ) )
  100. break;
  101. }
  102. _aItems.Insert( rItem, i );
  103. _curSize += rItem.GetSize();
  104. vqDebugOut(( DEB_TRACE, "CPriorityQueue::EnQueue %d items\n", Count() ) );
  105. } //EnQueue
  106. //+---------------------------------------------------------------------------
  107. //
  108. // Member: TPriorityQueue<T>::ShouldEnQueue, public
  109. //
  110. // Synopsis: Determines if new item should be added to queue
  111. //
  112. // Arguments: [rItem] -- Item to add
  113. // [cDequeue] -- Count of items which must be dequeued before
  114. // adding [rItem].
  115. //
  116. // Returns: TRUE if item should be added to queue
  117. //
  118. // History: 7-Aug-97 Created
  119. //
  120. //----------------------------------------------------------------------------
  121. template<class T> BOOL TPriorityQueue<T>::ShouldEnQueue(
  122. T & rItem,
  123. unsigned & cDeQueue )
  124. {
  125. cDeQueue = 0;
  126. // Determine if we have to dequeue an item to get this item in the queue
  127. if ( 0 == Count() )
  128. return ( rItem.GetSize() <= _maxTotalSize );
  129. if ( ( rItem.GetSize() + _curSize ) > _maxTotalSize )
  130. {
  131. //
  132. // Is new item lower-priority than top item on queue?
  133. // If so, we can immediately reject this item.
  134. //
  135. if ( rItem.IsGreaterThan( _aItems[ 0 ] ) )
  136. {
  137. vqDebugOut(( DEB_TRACE,
  138. "CPriorityQueue::EnQueue item rejected (low priority)\n" ) );
  139. return FALSE;
  140. }
  141. //
  142. // Can we remove enough lower priority items to fit this on?
  143. //
  144. int SizeRemaining = rItem.GetSize();
  145. int FreeSpace = _maxTotalSize - _curSize;
  146. Win4Assert( SizeRemaining > FreeSpace );
  147. SizeRemaining -= FreeSpace;
  148. while ( cDeQueue < Count() &&
  149. SizeRemaining > 0 &&
  150. !rItem.IsGreaterThan( _aItems[ cDeQueue ] ) )
  151. {
  152. SizeRemaining -= _aItems[ cDeQueue ].GetSize();
  153. cDeQueue++;
  154. }
  155. //
  156. // We might have removed everything and still not have enough space.
  157. //
  158. if ( cDeQueue == Count() )
  159. {
  160. return ( rItem.GetSize() <= _maxTotalSize );
  161. }
  162. //
  163. // Or we may have failed to remove everything and not have enough space.
  164. //
  165. else if ( SizeRemaining > 0 )
  166. {
  167. vqDebugOut(( DEB_TRACE,
  168. "CPriorityQueue::EnQueue item rejected (can't fit)\n" ) );
  169. cDeQueue = 0;
  170. return FALSE;
  171. }
  172. }
  173. return TRUE;
  174. } //ShouldEnQueue
  175. template<class T> void TPriorityQueue<T>::Remove(
  176. unsigned iItem )
  177. {
  178. Win4Assert( iItem < Count() );
  179. _curSize -= _aItems[ iItem ].GetSize();
  180. _aItems.Remove( iItem );
  181. } //Remove