Leaked source code of windows server 2003
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.

780 lines
17 KiB

  1. #ifdef __COLLMGR_HPP__
  2. /*++
  3. Copyright (C) 2000 Microsoft Corporation
  4. All rights reserved.
  5. Module Name:
  6. collmgr.cxx
  7. Abstract:
  8. This file contains the declaration of a generic
  9. linked list which could encapsulate any data type
  10. even if complex ones. The list is defined as a
  11. manager and a node. The manager manages the given
  12. nodes of that type.
  13. Author:
  14. Khaled Sedky (khaleds) 21-Jun-2000
  15. Revision History:
  16. --*/
  17. /**********************************/
  18. /* List Manager Implementation */
  19. /**********************************/
  20. template <class E,class C>
  21. TLstMgr<E,C> ::
  22. TLstMgr(
  23. IN EEntriesType ThisListEntriesType,
  24. IN EListType ThisListType,
  25. IN OUT HRESULT *hRes
  26. ) :
  27. m_pHead(NULL),
  28. m_pTail(NULL),
  29. m_cNumOfNodes(0),
  30. m_bUnique(ThisListEntriesType==TLstMgr<E,C>::KUniqueEntries ? TRUE : FALSE),
  31. TClassID("TLstMgr")
  32. {
  33. HRESULT hLocalRes = S_OK;
  34. __try
  35. {
  36. if(m_pLockSem = new CRITICAL_SECTION)
  37. {
  38. //
  39. // Do we need an exception handler here
  40. //
  41. ::InitializeCriticalSection(m_pLockSem);
  42. ::SetLastError(ERROR_SUCCESS);
  43. }
  44. else
  45. {
  46. hLocalRes = GetLastErrorAsHRESULT();
  47. }
  48. }
  49. __except(1)
  50. {
  51. hLocalRes = GetLastErrorAsHRESULT(TranslateExceptionCode(::GetExceptionCode()));
  52. }
  53. if(hRes)
  54. {
  55. *hRes = hLocalRes;
  56. }
  57. }
  58. template <class E,class C>
  59. TLstMgr<E,C> ::
  60. ~TLstMgr(
  61. VOID
  62. )
  63. {
  64. EnterCriticalSection(m_pLockSem);
  65. {
  66. DestructList();
  67. m_cNumOfNodes = 0;
  68. m_pHead = m_pTail = NULL;
  69. LeaveCriticalSection(m_pLockSem);
  70. }
  71. DeleteCriticalSection(m_pLockSem);
  72. delete m_pLockSem;
  73. }
  74. template <class E,class C>
  75. HRESULT
  76. TLstMgr<E,C> ::
  77. DestructList(
  78. VOID
  79. )
  80. {
  81. TLstNd<E,C> *pNode;
  82. for(pNode=m_pHead;
  83. pNode;
  84. pNode = m_pHead)
  85. {
  86. SPLASSERT(pNode);
  87. m_pHead = pNode->m_pNext;
  88. delete pNode;
  89. }
  90. return S_OK;
  91. }
  92. template <class E,class C>
  93. E&
  94. TLstMgr<E,C> ::
  95. operator[](
  96. IN DWORD Index
  97. ) const
  98. {
  99. TLstNd<E,C> *pNode;
  100. E *ClonedElement;
  101. //
  102. // In case the element is not found
  103. //
  104. ClonedElement = NULL;
  105. EnterCriticalSection(m_pLockSem);
  106. {
  107. if(m_cNumOfNodes &&
  108. Index >= 0 &&
  109. Index <= (m_cNumOfNodes-1))
  110. {
  111. DWORD InternalIndex = 0;
  112. for(pNode = m_pHead;
  113. (pNode &&
  114. (InternalIndex <= Index));
  115. pNode = pNode->m_pNext,
  116. InternalIndex ++)
  117. {
  118. ClonedElement = *pNode;
  119. }
  120. }
  121. }
  122. LeaveCriticalSection(m_pLockSem);
  123. return *ClonedElement;
  124. }
  125. template <class E,class C>
  126. TLstNd<E,C> *
  127. TLstMgr<E,C> ::
  128. ElementInList(
  129. const C &ToCompare
  130. ) const
  131. {
  132. TLstNd<E,C> *pNode = NULL;
  133. EnterCriticalSection(m_pLockSem);
  134. {
  135. if(m_cNumOfNodes)
  136. {
  137. for(pNode = m_pHead;
  138. (pNode && !(*(*(pNode)) == ToCompare));
  139. pNode = pNode->m_pNext)
  140. {
  141. //
  142. // There is really nothing to do, just
  143. // return the Node
  144. //
  145. }
  146. }
  147. }
  148. LeaveCriticalSection(m_pLockSem);
  149. return pNode;
  150. }
  151. template <class E,class C>
  152. TLstNd<E,C>*
  153. TLstMgr<E,C> ::
  154. AppendListByElem(
  155. IN const E &Element
  156. )
  157. {
  158. TLstNd<E,C> *pNode = new TLstNd<E,C>(Element);
  159. EnterCriticalSection(m_pLockSem);
  160. {
  161. if(pNode)
  162. {
  163. if(!m_cNumOfNodes)
  164. {
  165. //
  166. // The list is empty
  167. //
  168. m_pHead = m_pTail = pNode;
  169. m_pHead->m_pNext = NULL;
  170. m_pTail->m_pPrev = NULL;
  171. }
  172. else
  173. {
  174. //
  175. // The list has one or more Elements
  176. //
  177. m_pTail->m_pNext = pNode;
  178. pNode->m_pPrev = m_pTail;
  179. m_pTail = pNode;
  180. }
  181. m_cNumOfNodes ++;
  182. }
  183. }
  184. LeaveCriticalSection(m_pLockSem);
  185. return pNode;
  186. }
  187. template <class E,class C>
  188. TLstNd<E,C>*
  189. TLstMgr<E,C> ::
  190. AppendListByElem(
  191. IN E *Element
  192. )
  193. {
  194. TLstNd<E,C> *pNode = new TLstNd<E,C>(Element);
  195. EnterCriticalSection(m_pLockSem);
  196. {
  197. if(pNode)
  198. {
  199. if(!m_cNumOfNodes)
  200. {
  201. //
  202. // The list is empty
  203. //
  204. m_pHead = m_pTail = pNode;
  205. m_pHead->m_pNext = NULL;
  206. m_pTail->m_pPrev = NULL;
  207. }
  208. else
  209. {
  210. //
  211. // The list has one or more Elements
  212. //
  213. m_pTail->m_pNext = pNode;
  214. pNode->m_pPrev = m_pTail;
  215. m_pTail = pNode;
  216. }
  217. m_cNumOfNodes ++;
  218. }
  219. if(pNode)
  220. (*(*(pNode))).AddRef();
  221. }
  222. LeaveCriticalSection(m_pLockSem);
  223. return pNode;
  224. }
  225. template <class E,class C>
  226. TLstNd<E,C>*
  227. TLstMgr<E,C> ::
  228. AppendListByElem(
  229. IN const C &ElementMember
  230. )
  231. {
  232. TLstNd<E,C> *pNode;
  233. SetLastError(ERROR_SUCCESS);
  234. EnterCriticalSection(m_pLockSem);
  235. {
  236. if(!m_bUnique ||
  237. !(pNode = ElementInList(ElementMember)))
  238. {
  239. pNode = new TLstNd<E,C>(ElementMember);
  240. if(pNode)
  241. {
  242. if(!m_cNumOfNodes)
  243. {
  244. //
  245. // The list is empty
  246. //
  247. m_pHead = m_pTail = pNode;
  248. m_pHead->m_pNext = NULL;
  249. m_pTail->m_pPrev = NULL;
  250. }
  251. else
  252. {
  253. //
  254. // The list has one or more Elements
  255. //
  256. m_pTail->m_pNext = pNode;
  257. pNode->m_pPrev = m_pTail;
  258. m_pTail = pNode;
  259. }
  260. m_cNumOfNodes ++;
  261. }
  262. }
  263. if(pNode)
  264. (*(*(pNode))).AddRef();
  265. }
  266. LeaveCriticalSection(m_pLockSem);
  267. return pNode;
  268. }
  269. template<class E,class C>
  270. HRESULT
  271. TLstMgr<E,C> ::
  272. RmvElemFromList(
  273. IN const E &Element
  274. )
  275. {
  276. HRESULT hRes;
  277. TLstNd<E,C> *pNode = NULL;
  278. EnterCriticalSection(m_pLockSem);
  279. {
  280. if(m_cNumOfNodes)
  281. {
  282. //
  283. // Is this the last element in the List
  284. //
  285. if(m_pTail && *m_pTail == Element)
  286. {
  287. pNode = m_pTail;
  288. m_pTail = m_pTail->m_pPrev;
  289. if(m_pTail)
  290. {
  291. m_pTail->m_pNext = NULL;
  292. }
  293. }
  294. else if(m_pHead && *m_pHead == Element)
  295. {
  296. pNode = m_pHead;
  297. m_pHead = m_pHead->m_pNext;
  298. if(m_pHead)
  299. {
  300. m_pHead->m_pPrev = NULL;
  301. }
  302. }
  303. else
  304. {
  305. for(pNode = m_pHead->m_pNext;
  306. (pNode &&
  307. !(*pNode == Element));
  308. pNode = pNode->m_pNext)
  309. {
  310. //
  311. // Nothing , we just want to find the
  312. // target node.
  313. //
  314. }
  315. if(pNode)
  316. {
  317. pNode->m_pPrev->m_pNext = pNode->m_pNext;
  318. pNode->m_pNext->m_pPrev = pNode->m_pPrev;
  319. }
  320. }
  321. }
  322. if(pNode)
  323. {
  324. if(!--m_cNumOfNodes)
  325. {
  326. m_pHead = m_pTail = NULL;
  327. }
  328. delete pNode;
  329. hRes = S_OK;
  330. }
  331. else
  332. {
  333. //
  334. // If we reach this stage then the element
  335. // in the list { May be a better error code
  336. // should be returned TBD}
  337. //
  338. hRes = E_INVALIDARG;
  339. }
  340. }
  341. LeaveCriticalSection(m_pLockSem);
  342. return hRes;
  343. }
  344. template<class E,class C>
  345. HRESULT
  346. TLstMgr<E,C> ::
  347. RmvElemFromList(
  348. IN const C &ElementMember
  349. )
  350. {
  351. HRESULT hRes;
  352. if(!m_bUnique)
  353. {
  354. //
  355. // In case of nonunique entries, we cann't really
  356. // perform the operation.
  357. // Are we going to DecRef only... I guess the way
  358. // it is now is better.
  359. //
  360. hRes = E_NOINTERFACE;
  361. }
  362. else
  363. {
  364. TLstNd<E,C> *pNode = NULL;
  365. EnterCriticalSection(m_pLockSem);
  366. {
  367. if(m_cNumOfNodes)
  368. {
  369. //
  370. // Is this the last element in the List
  371. //
  372. if(m_pTail && *m_pTail == ElementMember)
  373. {
  374. pNode = m_pTail;
  375. }
  376. else if(m_pHead && *m_pHead == ElementMember)
  377. {
  378. pNode = m_pHead;
  379. }
  380. else
  381. {
  382. for(pNode = m_pHead->m_pNext;
  383. (pNode &&
  384. !(*pNode == ElementMember));
  385. pNode = pNode->m_pNext)
  386. {
  387. //
  388. // Nothing except detecting the
  389. // required node
  390. //
  391. }
  392. }
  393. }
  394. if(pNode)
  395. {
  396. if(!(*(*pNode)).Release())
  397. {
  398. //
  399. // We have to do this in order to prevent deleting the
  400. // data if it was already deleted in the release;
  401. //
  402. pNode->SetNodeData(static_cast<E*>(NULL));
  403. if(pNode == m_pTail)
  404. {
  405. m_pTail = m_pTail->m_pPrev;
  406. if(m_pTail)
  407. {
  408. m_pTail->m_pNext = NULL;
  409. }
  410. }
  411. else if(m_pHead == pNode)
  412. {
  413. m_pHead = m_pHead->m_pNext;
  414. if(m_pHead)
  415. {
  416. m_pHead->m_pPrev = NULL;
  417. }
  418. }
  419. else
  420. {
  421. pNode->m_pPrev->m_pNext = pNode->m_pNext;
  422. pNode->m_pNext->m_pPrev = pNode->m_pPrev;
  423. }
  424. delete pNode;
  425. if(!--m_cNumOfNodes)
  426. {
  427. m_pHead = m_pTail = NULL;
  428. }
  429. hRes = S_OK;
  430. }
  431. }
  432. else
  433. {
  434. //
  435. // If we reach this stage then the element
  436. // in the list { May be a better error code
  437. // should be returned TBD}
  438. //
  439. hRes = E_INVALIDARG;
  440. }
  441. }
  442. LeaveCriticalSection(m_pLockSem);
  443. }
  444. return hRes;
  445. }
  446. template <class E,class C>
  447. HRESULT
  448. TLstMgr<E,C> ::
  449. RmvElemAtPosFromList(
  450. IN DWORD Index
  451. )
  452. {
  453. TLstNd<E,C> *pNode = NULL;
  454. HRESULT hRes;
  455. EnterCriticalSection(m_pLockSem);
  456. {
  457. if(m_cNumOfNodes &&
  458. Index >= 0 &&
  459. Index <= (m_cNumOfNodes-1))
  460. {
  461. //
  462. // Is this the last element in the List
  463. //
  464. if(Index == 0)
  465. {
  466. pNode = m_pTail;
  467. m_pTail = m_pTail->m_pPrev;
  468. if(m_pTail)
  469. {
  470. m_pTail->m_pNext = NULL;
  471. }
  472. }
  473. else if(Index == (m_cNumOfNodes-1))
  474. {
  475. pNode = m_pHead;
  476. m_pHead = m_pHead->m_pNext;
  477. if(m_pHead)
  478. {
  479. m_pHead->m_pPrev = NULL;
  480. }
  481. }
  482. else
  483. {
  484. DWORD InternalIndex = 1;
  485. for(pNode = m_pHead->m_pNext;
  486. (pNode &&
  487. (InternalIndex < Index));
  488. pNode = pNode->m_pNext,
  489. InternalIndex ++)
  490. {
  491. //
  492. // Nothing but detect the node
  493. //
  494. }
  495. if(pNode)
  496. {
  497. Temp->m_pPrev->m_pNext = pNode->m_pNext;
  498. Temp->m_pNext->m_pPrev = pNode->m_pPrev;
  499. }
  500. }
  501. }
  502. if(pNode)
  503. {
  504. if(!--m_cNumOfNodes)
  505. {
  506. m_pHead = m_pTail = NULL;
  507. }
  508. delete pNode;
  509. hRes = S_OK;
  510. }
  511. else
  512. {
  513. //
  514. // If we reach this stage then the element
  515. // is not in the list { May be a better
  516. // error code should be returned TBD}
  517. //
  518. hRes = E_INVALIDARG;
  519. }
  520. }
  521. LeaveCriticalSection(m_pLockSem);
  522. return hRes;
  523. }
  524. template <class E,class C>
  525. HRESULT
  526. TLstMgr<E,C> ::
  527. RmvHead(
  528. VOID
  529. )
  530. {
  531. return RmvElemAtPosFromList(0);
  532. }
  533. template <class E,class C>
  534. HRESULT
  535. TLstMgr<E,C> ::
  536. RmvTail(
  537. VOID
  538. )
  539. {
  540. return RmvElemAtPosFromList((m_cNumOfNodes-1));
  541. }
  542. template <class E,class C>
  543. BOOL
  544. TLstMgr<E,C> ::
  545. HaveElements(
  546. VOID
  547. ) const
  548. {
  549. return !!m_cNumOfNodes;
  550. }
  551. template <class E,class C>
  552. DWORD
  553. TLstMgr<E,C> ::
  554. GetNumOfListNodes(
  555. VOID
  556. ) const
  557. {
  558. return m_cNumOfNodes;
  559. }
  560. /********************************/
  561. /* List Node Implementation */
  562. /********************************/
  563. template <class E,class C>
  564. TLstNd<E,C> ::
  565. TLstNd() :
  566. m_pPrev(NULL) ,
  567. m_pNext(NULL)
  568. {
  569. m_pD = new E;
  570. }
  571. template <class E,class C>
  572. TLstNd<E,C> ::
  573. TLstNd(
  574. IN const TLstNd<E,C> &N
  575. ) :
  576. m_pPrev(N.m_pPrev),
  577. m_pNext(N.m_pNext)
  578. {
  579. m_pD = new E(N.D);
  580. }
  581. template <class E,class C>
  582. TLstNd<E,C> ::
  583. TLstNd(
  584. IN const E &Element
  585. ) :
  586. m_pPrev(NULL),
  587. m_pNext(NULL)
  588. {
  589. m_pD = new E(Element);
  590. }
  591. template <class E,class C>
  592. TLstNd<E,C> ::
  593. TLstNd(
  594. IN E *Element
  595. ) :
  596. m_pPrev(NULL),
  597. m_pNext(NULL)
  598. {
  599. m_pD = Element;
  600. }
  601. template <class E,class C>
  602. TLstNd<E,C> ::
  603. TLstNd(
  604. IN const C &ElementMember
  605. ) :
  606. m_pPrev(NULL),
  607. m_pNext(NULL)
  608. {
  609. m_pD = new E(ElementMember);
  610. }
  611. template <class E,class C>
  612. TLstNd<E,C> ::
  613. ~TLstNd()
  614. {
  615. //
  616. // Implicitly the destructor for
  617. // the maintained element would be
  618. // called
  619. //
  620. if(m_pD)
  621. {
  622. delete m_pD;
  623. }
  624. }
  625. template <class E,class C>
  626. const E&
  627. TLstNd<E,C> ::
  628. operator=(
  629. IN const E &Element
  630. )
  631. {
  632. if(this->m_pD != &Element)
  633. {
  634. *m_pD = Element;
  635. }
  636. return *(this->m_pD);
  637. }
  638. template <class E,class C>
  639. BOOL
  640. TLstNd<E,C> ::
  641. operator==(
  642. IN const E &Element
  643. ) const
  644. {
  645. return *m_pD == Element;
  646. }
  647. template <class E,class C>
  648. BOOL
  649. TLstNd<E,C> ::
  650. operator==(
  651. const C &ToCompare
  652. ) const
  653. {
  654. return *m_pD == ToCompare;
  655. }
  656. template <class E,class C>
  657. E&
  658. TLstNd<E,C> ::
  659. operator*()
  660. {
  661. return *m_pD;
  662. }
  663. template <class E,class C>
  664. E*
  665. TLstNd<E,C> ::
  666. SetNodeData(
  667. IN E *pNewD
  668. )
  669. {
  670. //
  671. // In some cases where the data is ref counted
  672. // it might be a good idea to Nullify this pointer
  673. // once the data ref reaches 0 (as this implies)
  674. // that it was deleted. No need to delete it once
  675. // more. We also return a pointer to the old node
  676. // data
  677. //
  678. E *pOldD = m_pD;
  679. m_pD = pNewD;
  680. return pOldD;
  681. }
  682. #endif //__COLLMGR_HPP__