prioritylst.h
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 20k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //-------------------------------------------------------------------------//
  2. //
  3. // TPriorityList.h
  4. //
  5. //-------------------------------------------------------------------------//
  6. // @doc
  7. #ifndef __TPRIORITYLIST_H__
  8. #define __TPRIORITYLIST_H__
  9. #ifndef ALL_WARNINGS
  10. # pragma warning(disable: 4114)
  11. #endif
  12. #include "cpool.h"
  13. #if defined(_NTDDK_) || defined(_NTIFS_)
  14. # define NT_KERNELMODE
  15. //# pragma message( "ttTPriorityList.h - NT Kernel Mode build" )
  16. #elif defined(_WIN32)
  17. # define WIN32_USERMODE
  18. //# pragma message( "ttTPriorityList.h - NT Kernel Mode build" )
  19. #endif
  20. #define TPRIORITYLIST_TEMPLATE template <class ELEMENT_TYPE>
  21. #define TPRIORITYLIST TPriorityList<ELEMENT_TYPE>
  22. #define DEFAULT_LIST_PRIORITY 0L 
  23. //-------------------------------------------------------------------------//
  24. // @class Doubly-linked priority list collection.<nl><nl>
  25. // The TPriorityList template is a versatile collection class that 
  26. // can serve as a doubly- or singly-linked priority list, priority stack,
  27. // or a priority queue, or as a non-prioritized list, stack or queue.<nl><nl>
  28. // Priority is assigned to collection elements via an argument passed to the
  29. // <mf TPriorityList.InsertHead> and <mf TPriorityList.AppendTail> methods.
  30. // To implement a non-prioritized collection, use DEFAULT_LIST_PRIORITY as 
  31. // the value of the priority parameter.  Otherwise, elements will be sorted in 
  32. // descending priority when added to the list.
  33. // @tcarg class | ELEMENT_TYPE | Collection member type.
  34. template <class ELEMENT_TYPE> class TPriorityList
  35. //-------------------------------------------------------------------------//
  36. {
  37. public:
  38. // @access Public construction, destruction
  39. #ifdef NT_KERNELMODE
  40. // @cmember Constructs a TPriorityList instance.
  41. TPriorityList( POOL_TYPE PoolType = NonPagedPool, ULONG nBlockSize = 16 ) ;
  42. #endif
  43. #ifdef WIN32_USERMODE
  44. TPriorityList( ULONG nBlockSize = 16 ) ;
  45. #endif
  46. virtual ~TPriorityList() ;
  47. // @access Public attributes
  48. public:
  49. // @cmember Returns the number of elements in the list.
  50. int Count() const ;
  51. // @cmember Reports whether the list is empty.
  52. BOOLEAN IsEmpty() const ;
  53. // @access Thread synchronization <em-> Public members
  54. public:
  55. // @cmember Acquires a mutual exclusion lock on the list.
  56. // This should be done immediately prior to each call to
  57. // a non-const method.
  58. void AcquireMutex() ;
  59. // @cmember Releases a mutual exclusion lock on the list.
  60. // This should be done immediately following each call to
  61. // a non-const method.
  62. void ReleaseMutex() ;
  63. // @access Element insertion <em-> Public methods
  64. public:
  65. // @cmember Inserts an element at the head of its priority group in the list.
  66. // This call should be synchronized with Acquire/ReleaseMutex.
  67. BOOLEAN InsertHead( const ELEMENT_TYPE& val, ULONG priority=DEFAULT_LIST_PRIORITY ) ;
  68. // @cmember Appends an element to the tail of its priority group in the list.
  69. // This call should be synchronized with Acquire/ReleaseMutex.
  70. BOOLEAN AppendTail( const ELEMENT_TYPE& val, ULONG priority=DEFAULT_LIST_PRIORITY ) ;
  71. // @access Element removal <em-> Public members
  72. public:
  73. // @cmember Removes the element at the head of the list.
  74. // This call should be synchronized with Acquire/ReleaseMutex.
  75. BOOLEAN PopHead( ELEMENT_TYPE* pVal=NULL ) ;
  76.     //  @cmember Removes the specified element from the list.
  77.     //  This call should be synchronized with Acquire/ReleaseMutex.
  78.     BOOLEAN RemoveAt( HANDLE hEnumOrFind ) ;
  79. // @cmember Removes the element at the tail of the list.
  80. // This call should be synchronized with Acquire/ReleaseMutex.
  81. BOOLEAN PopTail( ELEMENT_TYPE* pVal=NULL ) ;
  82. // @cmember Removes all elements of the list.
  83. virtual void Clear() ;
  84.     //  @cmember Notifies derived class that an element has been freed.
  85.     virtual void OnFreeElement( ELEMENT_TYPE& type ) {
  86.         UNREFERENCED_PARAMETER( type ) ;
  87.     }
  88. // @access Element retrieval and enumeration <em-> Public members
  89. public:
  90. // Note: An entire enumeration sequence (EnumHead/Tail, EnumNext/Prev, EndEnum)
  91. // should be synchonized as a block; i.e., call AcquireMutex() before
  92. // beginning enumeration, and don't release it until enumeration
  93. // is finished.
  94. // @cmember Begins enumeration from the head of the list.
  95. HANDLE EnumHead( ELEMENT_TYPE& val, ULONG nPriority=DEFAULT_LIST_PRIORITY ) const ;
  96. // @cmember Begins enumeration from the tail of the list.
  97. HANDLE  EnumTail( ELEMENT_TYPE& val, ULONG nPriority=DEFAULT_LIST_PRIORITY ) const ;
  98. // @cmember Retrieves next element in enumeration
  99. BOOLEAN EnumNext( HANDLE hEnum, ELEMENT_TYPE& val ) const ;
  100. // @cmember Retrieves previous element in enumeration
  101. BOOLEAN EnumPrev( HANDLE hEnum, ELEMENT_TYPE& val ) const ;
  102. // @cmember Terminates an enumeration begun with EnumHead() or EnumTail().
  103. void EndEnum( HANDLE hEnum ) const ;
  104. // @cmember Retrieves the address of the element at the head of the list.
  105. // This call should be synchronized with Acquire/ReleaseMutex.
  106. // Multithread Warning: After releasing the list's mutex, 
  107. // the head's value may change at any time!.
  108. BOOLEAN PeekHead( ELEMENT_TYPE** ppVal ) ;
  109. // @cmember Retrieves the address of the element at the tail of the list.
  110. // This call should be synchronized with Acquire/ReleaseMutex.
  111. // Multithread Warning: After releasing the list's mutex, 
  112. // the tail's value may change at any time!.
  113. BOOLEAN PeekTail( ELEMENT_TYPE** ppVal ) ;
  114. //--- Implementation Details...
  115. // Diagnostics
  116. #ifdef _DEBUG
  117. void Trace();
  118. #endif _DEBUG
  119. struct ELEMENT {
  120. LIST_ENTRY link ;
  121. ULONG priority ;
  122. ELEMENT_TYPE data ;
  123. } ;
  124. protected:
  125. // Protected enumeration structure.
  126. struct ENUM {
  127. ELEMENT* pE ;
  128. ULONG  priority ;
  129. } ;
  130. // Helper routines and macros
  131. ELEMENT* Head() const ;
  132. ELEMENT* Tail() const ;
  133.     ELEMENT*            Next( ELEMENT *pE ) const { return (ELEMENT*)pE->link.Flink ; }
  134. ELEMENT*            Prev( ELEMENT *pE ) const { return (ELEMENT*)pE->link.Blink ; }
  135. #define AssignNext( pE, pOther ) (((PLIST_ENTRY)pE)->Flink = (PLIST_ENTRY)pOther)
  136. #define AssignPrev( pE, pOther ) (((PLIST_ENTRY)pE)->Blink = (PLIST_ENTRY)pOther)
  137. ELEMENT* AllocElement() ;
  138. void             FreeElement( ELEMENT* ) ;
  139. void InsertAfter( ELEMENT* pDest, ELEMENT* ) ;
  140. void InsertBefore( ELEMENT* pDest, ELEMENT* ) ;
  141. // Data members
  142. ULONG m_cElements ;
  143. ELEMENT *m_pHead,
  144. *m_pFreeHead ;
  145. struct CPool *m_pBlocks ;
  146. ULONG m_nBlockSize ;
  147. #ifdef WIN32_USERMODE
  148. CRITICAL_SECTION m_critsect ;
  149. #endif
  150. #ifdef NT_KERNELMODE
  151. POOL_TYPE m_poolType ;
  152. BOOLEAN m_fPassive ;
  153. KSPIN_LOCK m_spinLock ;
  154. KIRQL m_spinLockIrql ;
  155. FAST_MUTEX m_fastmutex ;
  156. #endif
  157. } ;
  158. #ifdef NT_KERNELMODE
  159. //-------------------------------------------------------------------------//
  160. TPRIORITYLIST_TEMPLATE
  161. TPRIORITYLIST::TPriorityList( POOL_TYPE poolType, ULONG nBlockSize )
  162. : m_poolType(poolType),
  163. m_fPassive(poolType==PagedPool||poolType==PagedPoolCacheAligned),
  164. m_spinLockIrql(PASSIVE_LEVEL),
  165. m_pHead(NULL),
  166. m_pFreeHead(NULL),
  167. m_pBlocks(NULL),
  168. m_nBlockSize(nBlockSize),
  169. m_cElements(0)
  170. {
  171. if( m_fPassive ) {
  172. ExInitializeFastMutex( &m_fastmutex ) ;
  173. }
  174. else {
  175. KeInitializeSpinLock( &m_spinLock ) ;
  176. }
  177. }
  178. #else
  179. //-------------------------------------------------------------------------//
  180. TPRIORITYLIST_TEMPLATE
  181. TPRIORITYLIST::TPriorityList( ULONG nBlockSize )
  182. : m_pHead(NULL),
  183. m_pFreeHead(NULL),
  184. m_pBlocks(NULL),
  185. m_nBlockSize(nBlockSize),
  186. m_cElements(0)
  187. {
  188. InitializeCriticalSection( &m_critsect ) ;
  189. }
  190. #endif
  191. //-------------------------------------------------------------------------//
  192. TPRIORITYLIST_TEMPLATE
  193. TPRIORITYLIST::~TPriorityList()
  194. {
  195. Clear() ;
  196. ASSERT( m_cElements==0 ) ;
  197. #ifdef WIN32_USERMODE
  198. DeleteCriticalSection( &m_critsect ) ;
  199. #endif
  200. }
  201. //-------------------------------------------------------------------------//
  202. // Acquires a mutual exclusion lock on the list.
  203. // This should be done immediately prior to each call to
  204. // a non-const method.
  205. TPRIORITYLIST_TEMPLATE
  206. void TPRIORITYLIST::AcquireMutex()
  207. {
  208. #ifdef NT_KERNELMODE
  209. if( m_fPassive ) {
  210. ExAcquireFastMutex( &m_fastmutex ) ;
  211. }
  212. else {
  213. KeAcquireSpinLock( &m_spinLock, &m_spinLockIrql ) ;
  214. }
  215. #endif
  216. #ifdef WIN32_USERMODE
  217. EnterCriticalSection( &m_critsect ) ;
  218. #endif
  219. }
  220. //-------------------------------------------------------------------------//
  221. // Releases a mutual exclusion lock on the list.
  222. // This should be done immediately following each call to
  223. // a non-const method.
  224. TPRIORITYLIST_TEMPLATE
  225. void TPRIORITYLIST::ReleaseMutex()
  226. {
  227. #ifdef NT_KERNELMODE
  228. if( m_fPassive ) {
  229. ExReleaseFastMutex( &m_fastmutex ) ;
  230. }
  231. else {
  232. KeReleaseSpinLock( &m_spinLock, m_spinLockIrql ) ;
  233. }
  234. #endif
  235. #ifdef WIN32_USERMODE
  236. LeaveCriticalSection( &m_critsect ) ;
  237. #endif
  238. }
  239. //-------------------------------------------------------------------------//
  240. TPRIORITYLIST_TEMPLATE
  241. void TPRIORITYLIST::Clear()
  242. {
  243. // Kill our pools and reinitialize our stats.
  244. m_cElements = 0 ;
  245. m_pHead = NULL ;
  246. m_pFreeHead = NULL ;
  247. m_pBlocks->FreeChain() ;
  248. m_pBlocks = NULL ;
  249. }
  250. //-------------------------------------------------------------------------//
  251. TPRIORITYLIST_TEMPLATE
  252. inline int TPRIORITYLIST::Count() const { 
  253. return m_cElements ;
  254. }
  255. //-------------------------------------------------------------------------//
  256. TPRIORITYLIST_TEMPLATE
  257. inline BOOLEAN TPRIORITYLIST::IsEmpty() const { 
  258. return m_cElements == 0  ;
  259. }
  260. //-------------------------------------------------------------------------//
  261. // Entry allocation helper
  262. TPRIORITYLIST_TEMPLATE
  263. TPRIORITYLIST::ELEMENT* TPRIORITYLIST::AllocElement()
  264. {
  265. ELEMENT* pE ;
  266. if( m_pFreeHead == NULL )
  267. {
  268. // add another block
  269. #if defined(WIN32_USERMODE)
  270. // user-mode version:
  271. CPool* newBlock = CPool::Create( m_pBlocks, m_nBlockSize, sizeof(ELEMENT) ) ;
  272. #elif defined(NT_KERNELMODE)
  273. // kernel-mode version:
  274. CPool* newBlock = CPool::Create( m_poolType, m_pBlocks, m_nBlockSize, sizeof(ELEMENT) ) ;
  275. #endif
  276. // chain them into free list
  277. pE = (ELEMENT*)newBlock->data() ;
  278. // free in reverse order to make it easier to debug
  279. pE += m_nBlockSize - 1 ;
  280. for ( int i = m_nBlockSize-1 ; i >= 0 ; i--, pE-- )
  281. {
  282. AssignNext( pE, m_pFreeHead ) ;
  283. m_pFreeHead = pE ;
  284. }
  285. }
  286. ASSERT( m_pFreeHead != NULL ) ; // we must have a list of free entries!
  287. // Pull head element off the free list...
  288. pE = m_pFreeHead ;
  289. m_pFreeHead = Next( pE ) ; // Assign element's "next" as new free head
  290. AssignNext( pE, NULL ) ; // orphan the element
  291. AssignPrev( pE, NULL ) ; // ""
  292. m_cElements++ ; // increment count of elements
  293. ASSERT( m_cElements > 0 ) ; // make sure we don't overflow
  294. return pE ;
  295. }
  296. //-------------------------------------------------------------------------//
  297. TPRIORITYLIST_TEMPLATE
  298. void TPRIORITYLIST::FreeElement( ELEMENT* pE )
  299. {
  300. if( !pE ) return ;
  301. // splice element out of list.
  302. if( Prev( pE ) )
  303. AssignNext( Prev( pE ), Next( pE ) ) ;
  304. if( Next( pE ) )
  305. AssignPrev( Next( pE ), Prev( pE ) ) ;
  306. // Reassign head as necessary
  307. if( pE==m_pHead )
  308. m_pHead = Next( pE ) ;
  309. OnFreeElement( pE->data ) ;
  310.     
  311.     // Only one element?  Clear everything.
  312. if( !m_pHead )
  313. Clear() ;
  314. else
  315. {
  316. // Clear the contents of the freed element.
  317. memset( &pE->data, 0, sizeof(pE->data) ) ;
  318. // Make freed element head of free list.
  319. if( m_pFreeHead )
  320. AssignPrev( m_pFreeHead, pE ) ;
  321. AssignNext( pE, m_pFreeHead ) ;
  322. AssignPrev( pE, NULL ) ;
  323. m_pFreeHead = pE ;
  324. // Decrement element count
  325. m_cElements-- ;
  326. }
  327. }
  328. //-------------------------------------------------------------------------//
  329. TPRIORITYLIST_TEMPLATE
  330. inline TPRIORITYLIST::ELEMENT* TPRIORITYLIST::Head() const
  331. {
  332. return m_pHead ;
  333. }
  334. //-------------------------------------------------------------------------//
  335. TPRIORITYLIST_TEMPLATE
  336. inline TPRIORITYLIST::ELEMENT* TPRIORITYLIST::Tail() const
  337. {
  338. ELEMENT *pE, *pTail ;
  339. if( !m_pHead ) return NULL ;
  340. for( pE = Next( m_pHead ), pTail = m_pHead; pE ; 
  341.  pE = Next( pE ) )
  342. pTail = pE ;
  343. ASSERT( pTail ) ;
  344. return pTail ;
  345. }
  346. //-------------------------------------------------------------------------//
  347. // Inserts an element at the head of the list
  348. TPRIORITYLIST_TEMPLATE
  349. BOOLEAN TPRIORITYLIST::InsertHead( const ELEMENT_TYPE& val, ULONG priority )
  350. {
  351. BOOLEAN bRet = FALSE ;
  352. ELEMENT *pE ;
  353. if( (pE = AllocElement()) )
  354. {
  355. pE->priority = priority ;
  356. pE->data = val ;
  357. if( !m_pHead )
  358. {
  359. m_pHead = pE ;
  360. bRet = TRUE ;
  361. }
  362. else
  363. {
  364. // Walk list looking for insertion point
  365. ELEMENT* pHead ;
  366. for( pHead = m_pHead; pHead; pHead=Next( pHead ) )
  367. {
  368. if( pHead->priority<=priority )
  369. {
  370. InsertBefore( pHead, pE ) ;
  371. if( pHead==m_pHead )
  372. m_pHead = pE ;
  373. bRet = TRUE ;
  374. break ;
  375. }
  376. }
  377. }
  378. ASSERT( bRet ) ;
  379. }
  380. return bRet ;
  381. }
  382. //-------------------------------------------------------------------------//
  383. // Appends an element to the tail of the list
  384. TPRIORITYLIST_TEMPLATE
  385. BOOLEAN TPRIORITYLIST::AppendTail( const ELEMENT_TYPE& val, ULONG priority )
  386. {
  387. BOOLEAN bRet = FALSE ;
  388. ELEMENT *pE, *pTail ;
  389. if( !m_pHead )
  390. return InsertHead( val, priority ) ;
  391. if( (pE = AllocElement()) )
  392. {
  393. pE->priority = priority ;
  394. pE->data = val ;
  395. // Walk list looking for insertion point
  396. for( pTail=Tail(); pTail; pTail = Prev( pTail ) )
  397. {
  398. // Have we encountered a priority higher than us?
  399. if( pTail->priority>=priority )
  400. {
  401. // Yes, insert after
  402. InsertAfter( pTail, pE ) ;
  403. bRet = TRUE ;
  404. break ;
  405. }
  406. // Otherwise, have we reached the head?
  407. else if( pTail==m_pHead )
  408. {
  409. // Yes, insert as new head.
  410. InsertBefore( pTail, pE ) ;
  411. m_pHead = pE ;
  412. bRet = TRUE ;
  413. break ;
  414. }
  415. }
  416. ASSERT( bRet ) ;
  417. }
  418. return bRet ;
  419. }
  420. //-------------------------------------------------------------------------//
  421. TPRIORITYLIST_TEMPLATE
  422. void TPRIORITYLIST::InsertAfter( ELEMENT* pDest, ELEMENT* pSrc )
  423. {
  424. ASSERT( pSrc ) ;
  425. if( pDest )
  426. {
  427. AssignPrev( pSrc, pDest ) ;
  428. if( AssignNext( pSrc, Next( pDest ) ) )
  429. AssignPrev( Next( pSrc ), pSrc ) ;
  430. AssignNext( pDest, pSrc ) ;
  431. }
  432. else
  433. {
  434. AssignPrev( pSrc, NULL ) ;
  435. AssignNext( pSrc, NULL ) ;
  436. }
  437. }
  438. //-------------------------------------------------------------------------//
  439. TPRIORITYLIST_TEMPLATE
  440. void TPRIORITYLIST::InsertBefore( ELEMENT* pDest, ELEMENT* pSrc )
  441. {
  442. ASSERT( pSrc ) ;
  443. if( pDest )
  444. {
  445. AssignNext( pSrc, pDest ) ;
  446. if( AssignPrev( pSrc, Prev( pDest ) ) )
  447. AssignNext( Prev( pSrc ), pSrc ) ;
  448. AssignPrev( pDest, pSrc ) ;
  449. }
  450. else
  451. {
  452. AssignPrev( pSrc, NULL ) ;
  453. AssignNext( pSrc, NULL ) ;
  454. }
  455. }
  456. //-------------------------------------------------------------------------//
  457. // Retrieves the element at the head of the list.
  458. TPRIORITYLIST_TEMPLATE
  459. BOOLEAN TPRIORITYLIST::PeekHead( ELEMENT_TYPE** ppVal )
  460. {
  461. ELEMENT* pE ;
  462. ASSERT( ppVal ) ;
  463. *ppVal = NULL ;
  464. if( (pE = Head())==NULL )
  465. return FALSE ;
  466. *ppVal = &m_pHead->data ;
  467. return TRUE ;
  468. }
  469. //-------------------------------------------------------------------------//
  470. // Retrieves the element at the tail of the list.
  471. TPRIORITYLIST_TEMPLATE
  472. BOOLEAN TPRIORITYLIST::PeekTail( ELEMENT_TYPE** ppVal )
  473. {
  474. ELEMENT* pTail ;
  475. ASSERT( ppVal ) ;
  476. *ppVal = NULL ;
  477. if( (pTail = Tail())==NULL )
  478. return FALSE ;
  479. (*ppVal) = &pTail->data ;
  480. return TRUE ;
  481. }
  482. //-------------------------------------------------------------------------//
  483. // Removes the element at the head of the list.
  484. TPRIORITYLIST_TEMPLATE
  485. BOOLEAN TPRIORITYLIST::PopHead( ELEMENT_TYPE* pVal )
  486. {
  487. ELEMENT* pE ; 
  488. if( (pE = Head())==NULL )
  489. return FALSE ;
  490. if( pVal )
  491. *pVal = pE->data ;
  492. FreeElement( pE ) ;
  493. return TRUE ;
  494. }
  495. //-------------------------------------------------------------------------//
  496. //  
  497. TPRIORITYLIST_TEMPLATE
  498. BOOLEAN TPRIORITYLIST::RemoveAt( HANDLE hEnum )
  499. {
  500. ENUM         *pEnum ;
  501.     ELEMENT      *pE = NULL ; 
  502.     ELEMENT_TYPE next ;
  503. if( !( (pEnum = (ENUM*)hEnum) && (pE = pEnum->pE) ) )
  504. return FALSE ;
  505.     //  Skip past this one
  506.     EnumNext( hEnum, next ) ;
  507.     FreeElement( pE ) ;
  508.     return TRUE ;
  509. }
  510. //-------------------------------------------------------------------------//
  511. // Removes the element at the tail of the list.
  512. TPRIORITYLIST_TEMPLATE
  513. BOOLEAN TPRIORITYLIST::PopTail( ELEMENT_TYPE* pVal )
  514. {
  515. ELEMENT* pE ;
  516. if( (pE = Tail())==NULL )
  517. return FALSE ;
  518. if( pVal )
  519. *pVal = pE->data ;
  520. FreeElement( pE ) ;
  521. return TRUE ;
  522. }
  523. //-------------------------------------------------------------------------//
  524. // Begins enumeration from the head of the list.
  525. TPRIORITYLIST_TEMPLATE
  526. HANDLE TPRIORITYLIST::EnumHead( ELEMENT_TYPE& val, ULONG nPriority ) const
  527. {
  528. ENUM* pEnum = NULL ;
  529. ELEMENT* pE ;
  530. if( !m_pHead )
  531. return pEnum ;
  532. for( pE = m_pHead; pE; pE = Next( pE ) ) {
  533. if( nPriority == DEFAULT_LIST_PRIORITY || pE->priority==nPriority )
  534. break ;
  535. }
  536. if( !(pE && (pEnum = new ENUM)) )
  537. return NULL ;
  538. memset( pEnum, 0, sizeof(*pEnum) ) ;
  539.     pEnum->pE = pE ;
  540. pEnum->priority = nPriority ;
  541. val = pE->data ;
  542. return pEnum ;
  543. }
  544. //-------------------------------------------------------------------------//
  545. // Begins enumeration from the tail of the list.
  546. TPRIORITYLIST_TEMPLATE
  547. HANDLE TPRIORITYLIST::EnumTail( ELEMENT_TYPE& val, ULONG nPriority ) const
  548. {
  549. ENUM *pEnum = NULL ;
  550. ELEMENT *pE, *pTail ;
  551. if( !(pTail=Tail()) )
  552. return pEnum ;
  553. for( pE = pTail; pE; pE = Prev( pE ) ) {
  554. if( nPriority==DEFAULT_LIST_PRIORITY || pE->priority==nPriority )
  555. {
  556. val = pE->data ;
  557. break ;
  558. }
  559. }
  560. if( !(pE && (pEnum = new ENUM)) )
  561. return NULL ;
  562. memset( pEnum, 0, sizeof(*pEnum) ) ;
  563.     pEnum->pE = pE ;
  564. pEnum->priority = nPriority ;
  565. return pEnum ;
  566. }
  567. //-------------------------------------------------------------------------//
  568. // Retrieves next element in enumeration
  569. TPRIORITYLIST_TEMPLATE
  570. BOOLEAN TPRIORITYLIST::EnumNext( HANDLE hEnum, ELEMENT_TYPE& val ) const
  571. {
  572. ENUM *pEnum ;
  573. if( !((pEnum = (ENUM*)hEnum) && pEnum->pE) )
  574. return FALSE ;
  575. for( pEnum->pE = Next( pEnum->pE ); 
  576.  pEnum->pE; 
  577.  pEnum->pE = Next( pEnum->pE ) )
  578. {
  579. if( pEnum->priority==DEFAULT_LIST_PRIORITY || 
  580. pEnum->pE->priority==pEnum->priority )
  581. {
  582. val = pEnum->pE->data ;
  583. break ;
  584. }
  585. }
  586. return pEnum->pE != NULL ;
  587. }
  588. //-------------------------------------------------------------------------//
  589. // Retrieves previous element in enumeration
  590. TPRIORITYLIST_TEMPLATE
  591. BOOLEAN TPRIORITYLIST::EnumPrev( HANDLE hEnum, ELEMENT_TYPE& val ) const
  592. {
  593. ENUM *pEnum ;
  594. if( !((pEnum = (ENUM*)hEnum) && pEnum->pE) )
  595. return FALSE ;
  596. for( pEnum->pE = Prev( pEnum->pE ) ; 
  597.  pEnum->pE ; 
  598.  pEnum->pE = Prev( pEnum->pE ) )
  599. {
  600. if( pEnum->priority==DEFAULT_LIST_PRIORITY || 
  601. pEnum->pE->priority==pEnum->priority )
  602. {
  603. val = pEnum->pE->data ;
  604. break ;
  605. }
  606. }
  607. return pEnum->pE != NULL ;
  608. }
  609. //-------------------------------------------------------------------------//
  610. // Terminates an enumeration begun with EnumHead() or EnumTail().
  611. TPRIORITYLIST_TEMPLATE
  612. void TPRIORITYLIST::EndEnum( HANDLE hEnum ) const
  613. {
  614. if( hEnum ) delete (ENUM*)hEnum ;
  615. }
  616. //-------------------------------------------------------------------------//
  617. #ifdef _DEBUG
  618. TPRIORITYLIST_TEMPLATE
  619. void TPRIORITYLIST::Trace()
  620. {
  621. ELEMENT* pE ;
  622. int  i;
  623. for( i=0, pE = m_pHead; pE; pE = Next( pE ), i++ )
  624. {
  625. TRACE("Data[%d]: 0x%08lX, priority[%d]: %ldn",
  626.   i, *(ULONG*)&pE->data, i, pE->priority ) ;
  627. }
  628. }
  629. #endif _DEBUG
  630. //-------------------------------------------------------------------------//
  631. #ifdef WIN32_USERMODE
  632. # undef WIN32_USERMODE
  633. #endif
  634. #ifdef NT_KERNELMODE
  635. # undef NT_KERNELMODE
  636. #endif
  637. #endif __TPRIORITYLIST_H__