windows-nt/Source/XPSP1/NT/inetsrv/query/h/tpriq.hxx

222 lines
5.6 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
//+---------------------------------------------------------------------------
//
// Copyright (C) 1996, Microsoft Corporation
//
// File: tpriq.hxx
//
// Contents: priority queue template
//
// Classes: TPriorityQueue
//
// History: 12-Jan-96 dlee Created
//
//----------------------------------------------------------------------------
#pragma once
//+---------------------------------------------------------------------------
//
// Class: TPriorityQueue
//
// Purpose: Priority queue class implemented using a sorted array.
//
// History: 12-Jan-96 dlee Created
//
// Notes: Class T must implement two methods:
//
// BOOL IsGreaterThan( T & rItem )
//
// returns TRUE if "this" is greater than rItem
//
// unsigned GetSize()
//
// returns size of the item, generally 1
//
//----------------------------------------------------------------------------
template <class T> class TPriorityQueue
{
public:
TPriorityQueue( BOOL fSizeIsOne,
unsigned maxTotalSize ) :
_maxTotalSize( maxTotalSize ),
_curSize( 0 ),
_aItems( fSizeIsOne ? maxTotalSize : 16 )
{
}
~TPriorityQueue() {}
BOOL DeQueue( T & rItem );
void EnQueue( T & rItem );
BOOL ShouldEnQueue( T & rItem, unsigned & cDeQueue );
void Remove( unsigned iItem );
T & PeekTop()
{
Win4Assert( 0 != Count() );
return _aItems[ 0 ];
}
T & Peek( unsigned iItem )
{
// Peek() is not guaranteed to return the items in any given order
Win4Assert( iItem < Count() );
return _aItems[ iItem ];
}
unsigned CurrentSize() { return _curSize; }
unsigned Count() { return _aItems.Count(); }
unsigned MaxTotalSize() { return _maxTotalSize; }
private:
unsigned _maxTotalSize;
unsigned _curSize;
CDynArrayInPlace<T> _aItems;
};
//+-------------------------------------------------------------------------
//
// Member: CPriorityQueue::DeQueue, public
//
// Synopsis: Removes the highest-most priority item.
//
// History: 12-Jan-96 dlee Created
//
//--------------------------------------------------------------------------
template<class T> BOOL TPriorityQueue<T>::DeQueue(
T & rItem )
{
if ( 0 != _aItems.Count() )
{
// Return the item at the top of the queue
rItem = _aItems[0];
_curSize -= rItem.GetSize();
_aItems.Remove( 0 );
vqDebugOut( ( DEB_TRACE,
"TPriorityQueue::DeQueue, %d items remain\n",
Count() ) );
return TRUE;
}
return FALSE;
} //DeQueue
template<class T> void TPriorityQueue<T>::EnQueue(
T & rItem )
{
// Find the insertion point
for ( unsigned i = 0; i < _aItems.Count(); i++ )
{
if ( !_aItems[ i ].IsGreaterThan( rItem ) )
break;
}
_aItems.Insert( rItem, i );
_curSize += rItem.GetSize();
vqDebugOut(( DEB_TRACE, "CPriorityQueue::EnQueue %d items\n", Count() ) );
} //EnQueue
//+---------------------------------------------------------------------------
//
// Member: TPriorityQueue<T>::ShouldEnQueue, public
//
// Synopsis: Determines if new item should be added to queue
//
// Arguments: [rItem] -- Item to add
// [cDequeue] -- Count of items which must be dequeued before
// adding [rItem].
//
// Returns: TRUE if item should be added to queue
//
// History: 7-Aug-97 Created
//
//----------------------------------------------------------------------------
template<class T> BOOL TPriorityQueue<T>::ShouldEnQueue(
T & rItem,
unsigned & cDeQueue )
{
cDeQueue = 0;
// Determine if we have to dequeue an item to get this item in the queue
if ( 0 == Count() )
return ( rItem.GetSize() <= _maxTotalSize );
if ( ( rItem.GetSize() + _curSize ) > _maxTotalSize )
{
//
// Is new item lower-priority than top item on queue?
// If so, we can immediately reject this item.
//
if ( rItem.IsGreaterThan( _aItems[ 0 ] ) )
{
vqDebugOut(( DEB_TRACE,
"CPriorityQueue::EnQueue item rejected (low priority)\n" ) );
return FALSE;
}
//
// Can we remove enough lower priority items to fit this on?
//
int SizeRemaining = rItem.GetSize();
int FreeSpace = _maxTotalSize - _curSize;
Win4Assert( SizeRemaining > FreeSpace );
SizeRemaining -= FreeSpace;
while ( cDeQueue < Count() &&
SizeRemaining > 0 &&
!rItem.IsGreaterThan( _aItems[ cDeQueue ] ) )
{
SizeRemaining -= _aItems[ cDeQueue ].GetSize();
cDeQueue++;
}
//
// We might have removed everything and still not have enough space.
//
if ( cDeQueue == Count() )
{
return ( rItem.GetSize() <= _maxTotalSize );
}
//
// Or we may have failed to remove everything and not have enough space.
//
else if ( SizeRemaining > 0 )
{
vqDebugOut(( DEB_TRACE,
"CPriorityQueue::EnQueue item rejected (can't fit)\n" ) );
cDeQueue = 0;
return FALSE;
}
}
return TRUE;
} //ShouldEnQueue
template<class T> void TPriorityQueue<T>::Remove(
unsigned iItem )
{
Win4Assert( iItem < Count() );
_curSize -= _aItems[ iItem ].GetSize();
_aItems.Remove( iItem );
} //Remove