mirror of
https://github.com/ValveSoftware/GameNetworkingSockets.git
synced 2026-05-29 16:20:34 +00:00
Minor tweaks to CUtlPriorityQueue
To bring it in sync with the version in //Steam/main P4:8088082
This commit is contained in:
@@ -7,22 +7,22 @@
|
||||
|
||||
#ifndef UTLPRIORITYQUEUE_H
|
||||
#define UTLPRIORITYQUEUE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <functional>
|
||||
template<typename T> using CDefLess = std::less<T>;
|
||||
|
||||
#include "utlvector.h"
|
||||
template < typename T >
|
||||
class CDefUtlPriorityQueueSetIndexFunc
|
||||
{
|
||||
public:
|
||||
inline static void SetIndex( T &heapElement, int nNewIndex ) { }
|
||||
inline static void SetIndex( T &heapElement, int nNewIndex, void *pContext ) { }
|
||||
};
|
||||
|
||||
// T is the type stored in the queue, it must include the priority
|
||||
// The head of the list contains the element with GREATEST priority
|
||||
// configure the LessFunc_t to get the desired queue order
|
||||
template< class T, class L = bool (*)( T const&, T const& ), class SetIndexFunc = CDefUtlPriorityQueueSetIndexFunc<T> >
|
||||
template< class T, class L = CDefLess<T>, class SetIndexFunc = CDefUtlPriorityQueueSetIndexFunc<T> >
|
||||
class CUtlPriorityQueue
|
||||
{
|
||||
public:
|
||||
@@ -33,10 +33,9 @@ public:
|
||||
|
||||
typedef T ElemType_t;
|
||||
|
||||
// constructor: lessfunc is required, but may be set after the constructor with
|
||||
// SetLessFunc
|
||||
CUtlPriorityQueue( int growSize = 0, int initSize = 0, LessFunc_t lessfunc = LessFunc_t() );
|
||||
CUtlPriorityQueue( T *pMemory, int numElements, LessFunc_t lessfunc = LessFunc_t() );
|
||||
// constructor: lessfunc is required
|
||||
CUtlPriorityQueue( int growSize = 0, int initSize = 0, LessFunc_t lessfunc = {} );
|
||||
CUtlPriorityQueue( T *pMemory, int numElements, LessFunc_t lessfunc = {} );
|
||||
|
||||
// gets particular elements
|
||||
inline T const& ElementAtHead() const { return m_heap.Element(0); }
|
||||
@@ -52,9 +51,7 @@ public:
|
||||
|
||||
// O(lgn) to rebalance heap
|
||||
void Insert( T const &element );
|
||||
// Sets the less func
|
||||
void SetLessFunc( LessFunc_t func );
|
||||
|
||||
|
||||
// Returns the count of elements in the queue
|
||||
inline int Count() const { return m_heap.Count(); }
|
||||
|
||||
@@ -64,19 +61,28 @@ public:
|
||||
// Memory deallocation
|
||||
void Purge() { m_heap.Purge(); }
|
||||
|
||||
int InvalidIndex() const { return m_heap.InvalidIndex(); }
|
||||
|
||||
inline const T & Element( int index ) const { return m_heap.Element(index); }
|
||||
|
||||
inline T &ElementMutable( int index ) { return m_heap.Element( index ); }
|
||||
|
||||
void SetSetIndexContext( void *pContext ) { m_pSetIndexContext = pContext; }
|
||||
|
||||
#ifdef DBGFLAG_VALIDATE
|
||||
void Validate( CValidator &validator, const char *pchName );
|
||||
void RecursiveValidate( CValidator &validator, const char *pchName );
|
||||
#endif // DBGFLAG_VALIDATE
|
||||
|
||||
protected:
|
||||
CUtlVector<T> m_heap;
|
||||
|
||||
void Swap( int index1, int index2 );
|
||||
void Swap( int parent, int child );
|
||||
int PercolateDown( int nIndex );
|
||||
int PercolateUp( int nIndex );
|
||||
|
||||
void *m_pSetIndexContext = NULL;
|
||||
|
||||
// Used for sorting.
|
||||
LessFunc_t m_LessFunc;
|
||||
};
|
||||
@@ -96,15 +102,15 @@ inline CUtlPriorityQueue<T, LessFunc, SetIndexFunc>::CUtlPriorityQueue( T *pMemo
|
||||
template <class T, class LessFunc, class SetIndexFunc>
|
||||
inline void CUtlPriorityQueue<T, LessFunc, SetIndexFunc>::RemoveAtHead()
|
||||
{
|
||||
SetIndexFunc::SetIndex( m_heap[ 0 ], m_heap.InvalidIndex() );
|
||||
SetIndexFunc::SetIndex( m_heap[ 0 ], m_heap.InvalidIndex(), m_pSetIndexContext );
|
||||
m_heap.FastRemove( 0 );
|
||||
|
||||
if ( Count() > 0 )
|
||||
{
|
||||
SetIndexFunc::SetIndex( m_heap[ 0 ], 0 );
|
||||
SetIndexFunc::SetIndex( m_heap[ 0 ], 0, m_pSetIndexContext );
|
||||
PercolateDown( 0 );
|
||||
}
|
||||
|
||||
PercolateDown( 0 );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -112,20 +118,25 @@ template <class T, class LessFunc, class SetIndexFunc>
|
||||
inline void CUtlPriorityQueue<T, LessFunc, SetIndexFunc>::RemoveAt( int index )
|
||||
{
|
||||
Assert(m_heap.IsValidIndex(index));
|
||||
SetIndexFunc::SetIndex( m_heap[ index ], m_heap.InvalidIndex() );
|
||||
SetIndexFunc::SetIndex( m_heap[ index ], m_heap.InvalidIndex(), m_pSetIndexContext );
|
||||
m_heap.FastRemove( index );
|
||||
|
||||
if ( index < Count() )
|
||||
{
|
||||
SetIndexFunc::SetIndex( m_heap[ index ], index );
|
||||
SetIndexFunc::SetIndex( m_heap[ index ], index, m_pSetIndexContext );
|
||||
RevaluateElement( index );
|
||||
}
|
||||
|
||||
RevaluateElement( index );
|
||||
}
|
||||
|
||||
template <class T, class LessFunc, class SetIndexFunc>
|
||||
inline void CUtlPriorityQueue<T, LessFunc, SetIndexFunc >::RevaluateElement( int nStartingIndex )
|
||||
{
|
||||
if ( (unsigned)nStartingIndex >= (unsigned)Count() )
|
||||
{
|
||||
Assert( false );
|
||||
return;
|
||||
}
|
||||
|
||||
int index = PercolateDown( nStartingIndex );
|
||||
|
||||
// If index is still the same as the starting index, then the specified element was larger than
|
||||
@@ -141,21 +152,22 @@ template< class T, class LessFunc, class SetIndexFunc >
|
||||
inline int CUtlPriorityQueue<T, LessFunc, SetIndexFunc >::PercolateDown( int index )
|
||||
{
|
||||
int count = Count();
|
||||
|
||||
int half = count/2;
|
||||
DbgAssert( (unsigned)index < (unsigned)count );
|
||||
|
||||
int larger = index;
|
||||
while ( index < half )
|
||||
for (;;)
|
||||
{
|
||||
int child = ((index+1) * 2) - 1; // if we wasted an element, this math would be more compact (1 based array)
|
||||
if ( child < count )
|
||||
if ( child >= count )
|
||||
break;
|
||||
|
||||
// Item has been filtered down to its proper place, terminate.
|
||||
if ( m_LessFunc( m_heap[index], m_heap[child] ) )
|
||||
{
|
||||
// Item has been filtered down to its proper place, terminate.
|
||||
if ( m_LessFunc( m_heap[index], m_heap[child] ) )
|
||||
{
|
||||
// mark the potential swap and check the other child
|
||||
larger = child;
|
||||
}
|
||||
// mark the potential swap and check the other child
|
||||
larger = child;
|
||||
}
|
||||
|
||||
// go to sibling
|
||||
child++;
|
||||
if ( child < count )
|
||||
@@ -179,13 +191,14 @@ inline int CUtlPriorityQueue<T, LessFunc, SetIndexFunc >::PercolateDown( int ind
|
||||
template< class T, class LessFunc, class SetIndexFunc >
|
||||
inline int CUtlPriorityQueue<T, LessFunc, SetIndexFunc >::PercolateUp( int index )
|
||||
{
|
||||
if ( index >= Count() )
|
||||
return index;
|
||||
DbgAssert( (unsigned)index < (unsigned)Count() );
|
||||
|
||||
while ( index != 0 )
|
||||
while ( index > 0 )
|
||||
{
|
||||
int parent = ((index+1) / 2) - 1;
|
||||
if ( m_LessFunc( m_heap[index], m_heap[parent] ) )
|
||||
|
||||
// Heap condition satisfied? Then we're done
|
||||
if ( !m_LessFunc( m_heap[parent], m_heap[index] ) )
|
||||
break;
|
||||
|
||||
// swap with parent and repeat
|
||||
@@ -201,25 +214,26 @@ inline void CUtlPriorityQueue<T, LessFunc, SetIndexFunc >::Insert( T const &elem
|
||||
{
|
||||
int index = m_heap.AddToTail();
|
||||
m_heap[index] = element;
|
||||
SetIndexFunc::SetIndex( m_heap[ index ], index );
|
||||
SetIndexFunc::SetIndex( m_heap[ index ], index, m_pSetIndexContext );
|
||||
|
||||
PercolateUp( index );
|
||||
}
|
||||
|
||||
template <class T, class LessFunc, class SetIndexFunc>
|
||||
void CUtlPriorityQueue<T, LessFunc, SetIndexFunc>::Swap( int index1, int index2 )
|
||||
void CUtlPriorityQueue<T, LessFunc, SetIndexFunc>::Swap( int parent, int child )
|
||||
{
|
||||
T tmp = m_heap[index1];
|
||||
m_heap[index1] = m_heap[index2];
|
||||
m_heap[index2] = tmp;
|
||||
SetIndexFunc::SetIndex( m_heap[ index1 ], index1 );
|
||||
SetIndexFunc::SetIndex( m_heap[ index2 ], index2 );
|
||||
}
|
||||
// Our current code should never call this unless there is a heap violation,
|
||||
// otherwise we are wasting work. Also we assume that
|
||||
// this internal function will only be called with the parent
|
||||
// in the first operand
|
||||
DbgAssert( parent < child );
|
||||
DbgAssert( m_LessFunc( m_heap[parent], m_heap[child] ) );
|
||||
|
||||
template <class T, class LessFunc, class SetIndexFunc>
|
||||
void CUtlPriorityQueue<T, LessFunc, SetIndexFunc>::SetLessFunc( LessFunc_t lessfunc )
|
||||
{
|
||||
m_LessFunc = lessfunc;
|
||||
T tmp = m_heap[parent];
|
||||
m_heap[parent] = m_heap[child];
|
||||
m_heap[child] = tmp;
|
||||
SetIndexFunc::SetIndex( m_heap[ parent ], parent, m_pSetIndexContext );
|
||||
SetIndexFunc::SetIndex( m_heap[ child ], child, m_pSetIndexContext );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -239,6 +253,15 @@ void CUtlPriorityQueue<T, LessFunc, SetIndexFunc>::Validate( CValidator &validat
|
||||
|
||||
validator.Pop();
|
||||
}
|
||||
|
||||
template <class T, class LessFunc, class SetIndexFunc>
|
||||
void CUtlPriorityQueue<T, LessFunc, SetIndexFunc>::RecursiveValidate( CValidator &validator, const char *pchName )
|
||||
{
|
||||
VALIDATE_SCOPE();
|
||||
|
||||
ValidateRecursive( m_heap );
|
||||
|
||||
}
|
||||
#endif // DBGFLAG_VALIDATE
|
||||
|
||||
#endif // UTLPRIORITYQUEUE_H
|
||||
|
||||
@@ -37,7 +37,7 @@ struct ThinkerLess
|
||||
class ThinkerSetIndex
|
||||
{
|
||||
public:
|
||||
static void SetIndex( IThinker *p, int idx ) { p->m_queueIndex = idx; }
|
||||
static void SetIndex( IThinker *p, int idx, void *pContext ) { p->m_queueIndex = idx; }
|
||||
};
|
||||
|
||||
static CUtlPriorityQueue<IThinker*,ThinkerLess,ThinkerSetIndex> s_queueThinkers;
|
||||
|
||||
Reference in New Issue
Block a user