Team Fortress 2 Source Code as on 22/4/2020
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.

888 lines
18 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Intrusive linked list templates, both for singly and doubly linked lists
  4. //
  5. // $Revision: $
  6. // $NoKeywords: $
  7. //===========================================================================//
  8. #ifndef UTILINTRUSIVELIST_H
  9. #define UTILINTRUSIVELIST_H
  10. #ifdef _WIN32
  11. #pragma once
  12. #endif
  13. #include "tier0/basetypes.h"
  14. #include "utlmemory.h"
  15. #include "tier0/dbg.h"
  16. //
  17. // These templates are used for intrusive linked list classes. Intrusive linked list templates
  18. // force the structs and classes contained within them to have their own m_pNext, (optionally),
  19. // m_pPrev, and other fields contained within. All memory management is up to the caller and their
  20. // classes. No data will ever be copied. Nodes can only exist on one list at a time, because of
  21. // only having on m_Next field, and manipulating the list while walking it requires that care on
  22. // the part of the caller. All accessing and searching functions work by passing and returning
  23. // pointers.
  24. //
  25. //
  26. //
  27. // naming and field conventions:
  28. // functions referring to a DList are for doubly linked lists. nodes must have m_pHead and
  29. // m_pPrev pointer fields.
  30. // Functions using Priority require an m_Priority field, which must be comparable.
  31. //
  32. // Some functions are mean for use with lists which maintain both a head and tail pointer
  33. // in order to support fast adding to the end.
  34. /// validates that the doubly linked list has the proper structure, pointer-wise
  35. namespace IntrusiveList
  36. {
  37. #ifdef SUPERSLOW_DEBUG_VERSION
  38. template<class T> inline void ValidateDList(T *head)
  39. {
  40. if (head)
  41. {
  42. Assert(head->m_pPrev==0);
  43. }
  44. while(head)
  45. {
  46. if (head->m_pNext)
  47. {
  48. Assert(head->m_pNext->m_pPrev==head);
  49. }
  50. if (head->m_pPrev)
  51. {
  52. Assert(head->m_pPrev->m_pNext==head);
  53. }
  54. head=head->m_pNext;
  55. }
  56. }
  57. #else
  58. template<class T> inline void ValidateDList(T * /*head*/)
  59. {
  60. }
  61. #endif
  62. // move a node in a doubly linked list backwards one step.
  63. template <class T> inline void MoveDNodeBackwards( T *which, T * &head)
  64. {
  65. if (which->m_pPrev)
  66. {
  67. T *p=which->m_pPrev;
  68. T *pp=p->m_pPrev;
  69. T *n=which->m_pNext;
  70. Assert(p->m_pNext == which);
  71. if (n)
  72. {
  73. Assert(n->m_pPrev==which);
  74. n->m_pPrev=p;
  75. }
  76. if (pp)
  77. {
  78. Assert(pp->m_pNext==p);
  79. pp->m_pNext=which;
  80. }
  81. else
  82. {
  83. head=which; // this node is the new root!
  84. }
  85. which->m_pNext=p;
  86. which->m_pPrev=pp;
  87. p->m_pNext=n;
  88. p->m_pPrev=which;
  89. }
  90. ValidateDList(head);
  91. }
  92. // removes node 'which' from doubly linked list with 'head'
  93. template<class T> inline void RemoveFromDList(T * &head, T *which)
  94. {
  95. if (which->m_pPrev)
  96. {
  97. Assert(which->m_pPrev->m_pNext==which);
  98. which->m_pPrev->m_pNext=which->m_pNext;
  99. if (which->m_pNext)
  100. {
  101. Assert(which->m_pNext->m_pPrev==which);
  102. which->m_pNext->m_pPrev=which->m_pPrev;
  103. }
  104. }
  105. else
  106. {
  107. if (head==which)
  108. {
  109. head=which->m_pNext;
  110. if (head)
  111. {
  112. Assert(head->m_pPrev==which);
  113. head->m_pPrev=0;
  114. }
  115. }
  116. }
  117. which->m_pNext=which->m_pPrev=0;
  118. ValidateDList(head);
  119. }
  120. //checks to see if node is in doubly linked list
  121. template<class T> bool OnDList(T const *head, T const *which)
  122. {
  123. return (head==which) || (which->m_pNext !=0) || (which->m_pPrev !=0);
  124. }
  125. // add a node to the end of a singly linked list
  126. template<class T> void AddToDTail(T * & head, T * node)
  127. {
  128. node->m_pNext=0;
  129. if (! head)
  130. {
  131. head=node;
  132. }
  133. else
  134. {
  135. T *ptr=head;
  136. while(ptr->m_pNext)
  137. {
  138. ptr=ptr->m_pNext;
  139. }
  140. ptr->m_pNext=node;
  141. node->m_pPrev=ptr; //
  142. }
  143. }
  144. // add a node to end of doubly linked list.
  145. template<class T> inline void AddToDHead(T * &head, T *which)
  146. {
  147. which->m_pNext=head;
  148. if (head)
  149. {
  150. head->m_pPrev=which;
  151. }
  152. which->m_pPrev=0;
  153. head=which;
  154. ValidateDList(head);
  155. }
  156. // add a node to front of doubly linked list which maintains a tail ptr
  157. template<class T> inline void AddToDHeadWithTailPtr(T * &head, T *which, T * &tailptr)
  158. {
  159. which->m_pNext=head;
  160. if (head)
  161. {
  162. head->m_pPrev=which;
  163. }
  164. else
  165. {
  166. tailptr=which;
  167. }
  168. which->m_pPrev=0;
  169. head=which;
  170. ValidateDList(head);
  171. }
  172. // add a node to end of doubly linked list which maintains a tail ptr
  173. template<class T> inline void AddToDTailWithTailPtr(T * &head, T *which, T * & tailptr)
  174. {
  175. if (! tailptr)
  176. {
  177. Assert(! head);
  178. which->m_pPrev=which->m_pNext=0;
  179. tailptr=head=which;
  180. }
  181. else
  182. {
  183. which->m_pNext=0;
  184. which->m_pPrev=tailptr;
  185. tailptr->m_pNext=which;
  186. tailptr=which;
  187. }
  188. ValidateDList( head );
  189. }
  190. // Remove a node from a dlist , maintaining the tail ptr. node is not 'delete' d
  191. template<class T> inline void RemoveFromDListWithTailPtr(T * &head, T *which, T * & tailptr)
  192. {
  193. if (which==tailptr)
  194. {
  195. tailptr=which->m_pPrev;
  196. }
  197. if (which->m_pPrev)
  198. {
  199. Assert(which->m_pPrev->m_pNext==which);
  200. which->m_pPrev->m_pNext=which->m_pNext;
  201. if (which->m_pNext)
  202. {
  203. Assert(which->m_pNext->m_pPrev==which);
  204. which->m_pNext->m_pPrev=which->m_pPrev;
  205. }
  206. }
  207. else
  208. {
  209. if (head==which)
  210. {
  211. head=which->m_pNext;
  212. if (head)
  213. {
  214. Assert(head->m_pPrev==which);
  215. head->m_pPrev=0;
  216. }
  217. }
  218. }
  219. which->m_pNext=which->m_pPrev=0;
  220. ValidateDList(head);
  221. }
  222. // this function removes a node, and delete's the node
  223. template<class T> inline void DeleteFromDListWithTailPtr(T * &head, T *which, T * & tailptr)
  224. {
  225. T *tmp=which;
  226. if (which==tailptr)
  227. {
  228. tailptr=which->m_pPrev;
  229. }
  230. if (which->m_pPrev)
  231. {
  232. Assert(which->m_pPrev->m_pNext==which);
  233. which->m_pPrev->m_pNext=which->m_pNext;
  234. if (which->m_pNext)
  235. {
  236. Assert(which->m_pNext->m_pPrev==which);
  237. which->m_pNext->m_pPrev=which->m_pPrev;
  238. }
  239. }
  240. else
  241. {
  242. if (head==which)
  243. {
  244. head=which->m_pNext;
  245. if (head)
  246. {
  247. Assert(head->m_pPrev==which);
  248. head->m_pPrev=0;
  249. }
  250. }
  251. }
  252. which->m_pNext=which->m_pPrev=0;
  253. delete tmp;
  254. ValidateDList(head);
  255. }
  256. // Add a node to a d-list, keeping the highest priority nodes first. This is a simple
  257. // linear search to insert, NOT a O(logn) heap.
  258. template<class T> inline void AddToDPriority(T * &head, T *which)
  259. {
  260. T* prevnode=0;
  261. for(T *curnode=head;curnode;curnode=curnode->m_pNext)
  262. {
  263. if (which->m_Priority>=curnode->m_Priority)
  264. break;
  265. prevnode=curnode;
  266. }
  267. // now, we have either run out of list, or we have found an
  268. // element to add this one before
  269. if (! prevnode)
  270. {
  271. AddToDHead(head,which);
  272. }
  273. else
  274. {
  275. which->m_pNext=prevnode->m_pNext;
  276. prevnode->m_pNext=which;
  277. which->m_pPrev=prevnode;
  278. if (which->m_pNext)
  279. which->m_pNext->m_pPrev=which;
  280. }
  281. }
  282. // same as AddToDPriority, except with reverse order
  283. template<class T> inline void AddToDPriorityLowestFirst(T * &head, T *which)
  284. {
  285. T* prevnode=0;
  286. for(T *curnode=head;curnode;curnode=curnode->m_pNext)
  287. {
  288. if (which->m_Priority<=curnode->m_Priority)
  289. break;
  290. prevnode=curnode;
  291. }
  292. // now, we have either run out of list, or we have found an
  293. // element to add this one before
  294. if (! prevnode)
  295. {
  296. AddToDHead(head,which);
  297. }
  298. else
  299. {
  300. which->m_pNext=prevnode->m_pNext;
  301. prevnode->m_pNext=which;
  302. which->m_pPrev=prevnode;
  303. if (which->m_pNext)
  304. which->m_pNext->m_pPrev=which;
  305. }
  306. }
  307. // return a pointer to the last node in a singly-linked (or doubly) list
  308. template<class T> T * LastNode(T * head)
  309. {
  310. if (head)
  311. {
  312. while(head->m_pNext)
  313. {
  314. head=head->m_pNext;
  315. }
  316. }
  317. return head;
  318. }
  319. // Remove from a singly linked list. no delete called.
  320. template<class T,class V> void RemoveFromList(T * & head, V *which)
  321. {
  322. if (head==which)
  323. {
  324. head=which->m_pNext;
  325. }
  326. else
  327. {
  328. for(T * i=head; i; i=i->m_pNext)
  329. {
  330. if (i->m_pNext==which)
  331. {
  332. i->m_pNext=which->m_pNext;
  333. return;
  334. }
  335. }
  336. }
  337. }
  338. // same as RemoveFromList, but 'delete' is called.
  339. template<class T,class V> void DeleteFromList(T * & head, V *which)
  340. {
  341. T *tmp;
  342. if (head==which)
  343. {
  344. tmp=which->m_pNext;
  345. delete(head);
  346. head=tmp;
  347. }
  348. else
  349. {
  350. for(T * i=head; i; i=i->m_pNext)
  351. {
  352. if (i->m_pNext==which)
  353. {
  354. tmp=which->m_pNext;
  355. delete(which);
  356. i->m_pNext=tmp;
  357. return;
  358. }
  359. }
  360. }
  361. }
  362. // find the position in a list of a node. -1 if not found. Linear search.
  363. // nodes must have comparison functions
  364. template<class T,class V> int PositionInList(T *head, V *node)
  365. {
  366. int pos=0;
  367. while(head)
  368. {
  369. if (head==node) return pos;
  370. head=head->m_pNext;
  371. pos++;
  372. }
  373. return -1;
  374. }
  375. // find the Nth node in a list. null if index too high.
  376. template<class T> T *NthNode(T * head, int idx)
  377. {
  378. while(idx && head)
  379. {
  380. idx--;
  381. head=head->m_pNext;
  382. }
  383. return head;
  384. }
  385. //Add a node to the head of a singly-linked
  386. // Note that the head var passed to this will be modified.
  387. template<class T,class V> static inline void AddToHead(T * & head, V * node)
  388. {
  389. node->m_pNext=head;
  390. head=node;
  391. }
  392. //Add a node to the tail of a singly-linked. Not fast
  393. // Note that the head var passed to this will be modified.
  394. template<class T,class V> static inline void AddToTail(T * & head, V * node)
  395. {
  396. node->m_pNext = NULL;
  397. if ( ! head )
  398. head = node;
  399. else
  400. {
  401. T *pLastNode = head;
  402. while( pLastNode->m_pNext )
  403. pLastNode = pLastNode->m_pNext;
  404. pLastNode->m_pNext = node;
  405. }
  406. }
  407. //Add a node to the head of a singly-linked list, maintaining a tail pointer
  408. template<class T,class V> static inline void AddToHead(T * & head, T * &tail,V * node)
  409. {
  410. if (! head)
  411. {
  412. tail=node;
  413. }
  414. node->m_pNext=head;
  415. head=node;
  416. }
  417. // return the node in head before in a singly linked list. returns null if head is empty, n is
  418. // null, or if n is the first node. not fast.
  419. template<class T> static inline T * PrevNode(T *head, T *node)
  420. {
  421. T *i;
  422. for(i=head;i;i=i->m_pNext)
  423. {
  424. if (i->m_pNext == node)
  425. break;
  426. }
  427. return i;
  428. }
  429. // add a node to the end of a singly linked list. Not fast.
  430. template<class T,class V> void AddToEnd(T * & head, V * node)
  431. {
  432. node->m_pNext=0;
  433. if (! head)
  434. {
  435. head=node;
  436. }
  437. else
  438. {
  439. T *ptr=head;
  440. while(ptr->m_pNext)
  441. {
  442. ptr=ptr->m_pNext;
  443. }
  444. ptr->m_pNext=node;
  445. }
  446. }
  447. // add a node to the end of a singly linked list, maintaining a tail pointer.
  448. // the head and tail pointer can be modified by this routine.
  449. template<class T,class V> void AddToEndWithTail(T * & head, T * & tail,V * node)
  450. {
  451. Assert((head && tail) || ((!head) && (!tail)));
  452. node->m_pNext=0;
  453. if (! head)
  454. {
  455. head=tail=node;
  456. }
  457. else
  458. {
  459. tail->m_pNext=node;
  460. tail=node;
  461. }
  462. }
  463. // Add a node to a singly linked list, sorting by the m_Name field
  464. template<class T> void AddSortedByName(T * & head, T * node)
  465. {
  466. if ( (! head) || // empty list?
  467. (stricmp(node->m_Name,head->m_Name)==-1)) // or we should be first?
  468. {
  469. node->m_pNext=head; // make us head
  470. head=node;
  471. }
  472. else
  473. {
  474. T *t;
  475. for(t=head;t->m_pNext;t=t->m_pNext) // find the node we should be before
  476. if (stricmp(t->m_pNext->m_Name,node->m_Name)>=0)
  477. break;
  478. node->m_pNext=t->m_pNext;
  479. t->m_pNext=node;
  480. }
  481. }
  482. // count # of elements in list
  483. template<class T> int ListLength(T *head)
  484. {
  485. int len=0;
  486. while(head)
  487. {
  488. len++;
  489. head=head->m_pNext;
  490. }
  491. return len;
  492. }
  493. // this will kill a list if the list is of objects which automatically
  494. // remove themselves from the list when delete is called
  495. template<class T> void KillList(T * & head)
  496. {
  497. while(head)
  498. {
  499. delete head;
  500. }
  501. }
  502. // this will kill all elements in a list if
  503. // the elements are of a type which does NOT remove itself from
  504. // the list when the destructor is called.
  505. template<class T> void DeleteList(T * & head)
  506. {
  507. while (head)
  508. {
  509. T* tmp=head->m_pNext;
  510. delete head;
  511. head=tmp;
  512. }
  513. }
  514. // find a named node in any list which has both a Next field and a Name field.
  515. template <class T> static inline T * FindNamedNode(T * head, char const *name)
  516. {
  517. for(;head && stricmp(head->m_Name,name); head=head->m_pNext)
  518. {
  519. }
  520. return head;
  521. }
  522. template <class T> static inline T * FindNamedNodeCaseSensitive(T * head, char const *name)
  523. {
  524. for(;head && strcmp(head->m_Name,name); head=head->m_pNext)
  525. {
  526. }
  527. return head;
  528. }
  529. // find data in a singly linked list, using equality match on any field
  530. // usage: FindNodeByField(listptr,data,&list::fieldname)
  531. template <class T, class U, class V> static inline T * FindNodeByField(T * head, U data, U V::*field)
  532. {
  533. while(head)
  534. {
  535. if (data==(*head).*field)
  536. return head;
  537. head=head->m_pNext;
  538. }
  539. return 0;
  540. }
  541. // find a node and its predecessor, matching on equality of a given field.
  542. // usage: FindNodeByFieldWithPrev(listptr,data,&list::fieldname, prevptr)
  543. template <class T, class U, class V> static inline T * FindNodeByFieldWithPrev(T * head, U data, U V::*field, T * & prev)
  544. {
  545. prev=0;
  546. for(T *i=head; i; i=i->m_pNext)
  547. {
  548. if(data==(*i).*field)
  549. return i;
  550. prev=i;
  551. }
  552. prev=0;
  553. return 0;
  554. }
  555. /// sort a list. comparefn should return 0 if the items are equal, 1 if A goes first, and -1 if A goes last.
  556. // NOT fast.
  557. template<class T> void SortList(T * &head, int (*comparefn)(T * a, T * b))
  558. {
  559. int didswap=1;
  560. while(didswap)
  561. {
  562. didswap=0;
  563. T *prev=0;
  564. for(T *i=head;i && i->m_pNext; i=i->m_pNext)
  565. {
  566. /// compare i and i+1
  567. int rslt=(*comparefn)(i,i->m_pNext);
  568. if (rslt==-1)
  569. {
  570. /// need to swap
  571. didswap=1;
  572. T *newfirst=i->m_pNext;
  573. if (prev)
  574. {
  575. prev->m_pNext=newfirst;
  576. i->m_pNext=newfirst->m_pNext;
  577. newfirst->m_pNext=i;
  578. }
  579. else
  580. {
  581. head=i->m_pNext;
  582. i->m_pNext=newfirst->m_pNext;
  583. newfirst->m_pNext=i;
  584. }
  585. i=newfirst;
  586. }
  587. prev=i;
  588. }
  589. }
  590. }
  591. // sort a doubly linked list. NOt fast.
  592. template <class T> void SortDList(T * & head, int (*comparefn)(T * a, T * b))
  593. {
  594. SortList(head,comparefn);
  595. /// now, regen prev ptrs
  596. T *prev=0;
  597. for(T *i=head;i;i=i->m_pNext)
  598. {
  599. i->m_pPrev=prev;
  600. prev=i;
  601. }
  602. }
  603. // reverse a singly linked list. not recommended for anything other than valve programming
  604. // interview :-)
  605. template <class T> T *ReversedList( T * head )
  606. {
  607. T * pNewHead=NULL;
  608. while( head )
  609. {
  610. T *pNext=head->m_pNext;
  611. #ifdef INTERVIEW_QUESTION
  612. head->m_pNext=pNewHead;
  613. pNewHead = head;
  614. #else
  615. AddToHead( pNewHead, head );
  616. #endif
  617. head = pNext;
  618. }
  619. return pNewHead;
  620. }
  621. };
  622. // singly linked list
  623. template<class T> class CUtlIntrusiveList
  624. {
  625. public:
  626. T *m_pHead;
  627. FORCEINLINE T *Head( void ) const
  628. {
  629. return m_pHead;
  630. }
  631. FORCEINLINE CUtlIntrusiveList(void)
  632. {
  633. m_pHead = NULL;
  634. }
  635. FORCEINLINE void RemoveAll( void )
  636. {
  637. // empty list. doesn't touch nodes at all
  638. m_pHead = NULL;
  639. }
  640. FORCEINLINE void AddToHead( T * node )
  641. {
  642. IntrusiveList::AddToHead( m_pHead, node );
  643. }
  644. FORCEINLINE void AddToTail( T * node )
  645. {
  646. IntrusiveList::AddToTail( m_pHead, node );
  647. }
  648. void RemoveNode(T *which)
  649. {
  650. IntrusiveList::RemoveFromList( m_pHead, which );
  651. }
  652. // this will kill a list if the list is of objects which automatically
  653. // remove themselves from the list when delete is called
  654. void KillList( void )
  655. {
  656. while(m_pHead)
  657. {
  658. delete m_pHead;
  659. }
  660. }
  661. // return the node in head before in a singly linked list. returns null if head is empty, n is
  662. // null, or if n is the first node. not fast. Fast for dlists
  663. T * PrevNode(T *node)
  664. {
  665. return IntrusiveList::PrevNode( m_pHead, node );
  666. }
  667. int NthNode( int n )
  668. {
  669. return NthNode( m_pHead, n );
  670. }
  671. // this will kill all elements in a list if
  672. // the elements are of a type which does NOT remove itself from
  673. // the list when the destructor is called.
  674. void Purge( void )
  675. {
  676. while (m_pHead)
  677. {
  678. T* tmp=m_pHead->m_pNext;
  679. delete m_pHead;
  680. m_pHead=tmp;
  681. }
  682. }
  683. int Count( void ) const
  684. {
  685. return IntrusiveList::ListLength( m_pHead );
  686. }
  687. FORCEINLINE T * FindNamedNodeCaseSensitive( char const *pName ) const
  688. {
  689. return IntrusiveList::FindNamedNodeCaseSensitive( m_pHead, pName );
  690. }
  691. T *RemoveHead( void )
  692. {
  693. if ( m_pHead )
  694. {
  695. T *pRet = m_pHead;
  696. m_pHead = pRet->m_pNext;
  697. return pRet;
  698. }
  699. else
  700. return NULL;
  701. }
  702. };
  703. // doubly linked list
  704. template<class T> class CUtlIntrusiveDList : public CUtlIntrusiveList<T>
  705. {
  706. public:
  707. FORCEINLINE void AddToHead( T * node )
  708. {
  709. IntrusiveList::AddToDHead( CUtlIntrusiveList<T>::m_pHead, node );
  710. }
  711. FORCEINLINE void AddToTail( T * node )
  712. {
  713. IntrusiveList::AddToDTail( CUtlIntrusiveList<T>::m_pHead, node );
  714. }
  715. void RemoveNode(T *which)
  716. {
  717. IntrusiveList::RemoveFromDList( CUtlIntrusiveList<T>::m_pHead, which );
  718. }
  719. T *RemoveHead( void )
  720. {
  721. if ( CUtlIntrusiveList<T>::m_pHead )
  722. {
  723. T *pRet = CUtlIntrusiveList<T>::m_pHead;
  724. CUtlIntrusiveList<T>::m_pHead = CUtlIntrusiveList<T>::m_pHead->m_pNext;
  725. if ( CUtlIntrusiveList<T>::m_pHead )
  726. CUtlIntrusiveList<T>::m_pHead->m_pPrev = NULL;
  727. return pRet;
  728. }
  729. else
  730. return NULL;
  731. }
  732. T * PrevNode(T *node)
  733. {
  734. return ( node )?node->m_Prev:NULL;
  735. }
  736. };
  737. template<class T> class CUtlIntrusiveDListWithTailPtr : public CUtlIntrusiveDList<T>
  738. {
  739. public:
  740. T *m_pTailPtr;
  741. FORCEINLINE CUtlIntrusiveDListWithTailPtr( void ) : CUtlIntrusiveDList<T>()
  742. {
  743. m_pTailPtr = NULL;
  744. }
  745. FORCEINLINE void AddToHead( T * node )
  746. {
  747. IntrusiveList::AddToDHeadWithTailPtr( CUtlIntrusiveList<T>::m_pHead, node, m_pTailPtr );
  748. }
  749. FORCEINLINE void AddToTail( T * node )
  750. {
  751. IntrusiveList::AddToDTailWithTailPtr( CUtlIntrusiveList<T>::m_pHead, node, m_pTailPtr );
  752. }
  753. void RemoveNode( T *pWhich )
  754. {
  755. IntrusiveList::RemoveFromDListWithTailPtr( CUtlIntrusiveList<T>::m_pHead, pWhich, m_pTailPtr );
  756. }
  757. void Purge( void )
  758. {
  759. CUtlIntrusiveList<T>::Purge();
  760. m_pTailPtr = NULL;
  761. }
  762. void Kill( void )
  763. {
  764. CUtlIntrusiveList<T>::Purge();
  765. m_pTailPtr = NULL;
  766. }
  767. T *RemoveHead( void )
  768. {
  769. if ( CUtlIntrusiveDList<T>::m_pHead )
  770. {
  771. T *pRet = CUtlIntrusiveDList<T>::m_pHead;
  772. CUtlIntrusiveDList<T>::m_pHead = CUtlIntrusiveDList<T>::m_pHead->m_pNext;
  773. if ( CUtlIntrusiveDList<T>::m_pHead )
  774. CUtlIntrusiveDList<T>::m_pHead->m_pPrev = NULL;
  775. if (! CUtlIntrusiveDList<T>::m_pHead )
  776. m_pTailPtr = NULL;
  777. ValidateDList( CUtlIntrusiveDList<T>::m_pHead );
  778. return pRet;
  779. }
  780. else
  781. return NULL;
  782. }
  783. T * PrevNode(T *node)
  784. {
  785. return ( node )?node->m_Prev:NULL;
  786. }
  787. };
  788. template<class T> void PrependDListWithTailToDList( CUtlIntrusiveDListWithTailPtr<T> &src,
  789. CUtlIntrusiveDList<T> &dest )
  790. {
  791. if ( src.m_pHead )
  792. {
  793. src.m_pTailPtr->m_pNext = dest.m_pHead;
  794. if ( dest.m_pHead )
  795. dest.m_pHead->m_pPrev = src.m_pTailPtr;
  796. dest.m_pHead = src.m_pHead;
  797. IntrusiveList::ValidateDList( dest.m_pHead );
  798. }
  799. }
  800. #endif