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.

608 lines
17 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. fusiondeque.h
  5. Abstract:
  6. Author:
  7. Revision History:
  8. --*/
  9. #pragma once
  10. #include "fusiontrace.h"
  11. #include "fusiondequelinkage.h"
  12. class CDequeBase
  13. {
  14. protected:
  15. inline CDequeBase() : m_EntryCount(0) { m_Head.InitializeHead(this); }
  16. inline ~CDequeBase()
  17. {
  18. // Derived class should have cleaned up
  19. ASSERT_NTC(m_EntryCount == 0);
  20. }
  21. inline VOID VerifyLinkageFromThisDeque(const CDequeLinkage &r)
  22. {
  23. ASSERT_NTC(r.GetDequeBase() == this);
  24. }
  25. #if DBG
  26. inline bool Valid() const { return (m_Head.GetFlink() != NULL) && (m_Head.GetBlink() != NULL); }
  27. #endif // DBG
  28. void ResetHead() { FN_TRACE(); m_Head.InitializeHead(this); }
  29. inline VOID InsertAfter(CDequeLinkage *pExistingLinkage, CDequeLinkage *pNewLinkage, bool fUpdateEntryCount = true)
  30. {
  31. ASSERT_NTC(this->Valid());
  32. this->VerifyLinkageFromThisDeque(m_Head);
  33. pNewLinkage->SetFlink(pExistingLinkage->GetFlink());
  34. pNewLinkage->SetBlink(pExistingLinkage);
  35. pExistingLinkage->GetFlink()->SetBlink(pNewLinkage);
  36. pExistingLinkage->SetFlink(pNewLinkage);
  37. pNewLinkage->SetDeque(this);
  38. if (fUpdateEntryCount)
  39. m_EntryCount++;
  40. }
  41. VOID InsertBefore(CDequeLinkage *pExistingLinkage, CDequeLinkage *pNewLinkage, bool fUpdateEntryCount = true)
  42. {
  43. ASSERT_NTC(this->Valid());
  44. this->VerifyLinkageFromThisDeque(m_Head);
  45. pNewLinkage->SetBlink(pExistingLinkage->GetBlink());
  46. pNewLinkage->SetFlink(pExistingLinkage);
  47. pExistingLinkage->GetBlink()->SetFlink(pNewLinkage);
  48. pExistingLinkage->SetBlink(pNewLinkage);
  49. pNewLinkage->SetDeque(this);
  50. if (fUpdateEntryCount)
  51. m_EntryCount++;
  52. }
  53. VOID Remove(CDequeLinkage *pLinkage, bool fUpdateEntryCount = true)
  54. {
  55. ASSERT_NTC(this->Valid());
  56. this->VerifyLinkageFromThisDeque(m_Head);
  57. // You can't remove the head...
  58. ASSERT_NTC(pLinkage->GetDequeBase() == this);
  59. ASSERT_NTC(pLinkage != &m_Head);
  60. ASSERT_NTC(pLinkage->m_ulLockCount == 0);
  61. if ((pLinkage != NULL) &&
  62. (pLinkage->GetDequeBase() == this) &&
  63. (pLinkage != &m_Head))
  64. {
  65. pLinkage->GetBlink()->SetFlink(pLinkage->GetFlink());
  66. pLinkage->GetFlink()->SetBlink(pLinkage->GetBlink());
  67. if (fUpdateEntryCount)
  68. m_EntryCount--;
  69. }
  70. }
  71. VOID SetDeque(CDequeLinkage *pLinkage) { pLinkage->SetDeque(this); }
  72. static CDequeLinkage *GetFlink(const CDequeLinkage *pLinkage) { return pLinkage->GetFlink(); }
  73. static CDequeLinkage *GetFlink(const CDequeLinkage &rLinkage) { return rLinkage.GetFlink(); }
  74. static CDequeLinkage *GetBlink(const CDequeLinkage *pLinkage) { return pLinkage->GetBlink(); }
  75. static CDequeLinkage *GetBlink(const CDequeLinkage &rLinkage) { return rLinkage.GetBlink(); }
  76. static VOID SetFlink(CDequeLinkage *pLinkage, CDequeLinkage *pFlink) { pLinkage->SetFlink(pFlink); }
  77. static VOID SetFlink(CDequeLinkage &rLinkage, CDequeLinkage *pFlink) { rLinkage.SetFlink(pFlink); }
  78. static VOID SetBlink(CDequeLinkage *pLinkage, CDequeLinkage *pBlink) { pLinkage->SetBlink(pBlink); }
  79. static VOID SetBlink(CDequeLinkage &rLinkage, CDequeLinkage *pBlink) { rLinkage.SetBlink(pBlink); }
  80. CDequeLinkage m_Head;
  81. SIZE_T m_EntryCount;
  82. private:
  83. CDequeBase(const CDequeBase &r); // intentionally not implemented
  84. void operator =(const CDequeBase &r); // intentionally not implemented
  85. };
  86. template <typename TEntry, size_t LinkageMemberOffset> class CConstDequeIterator;
  87. template <typename TEntry, size_t LinkageMemberOffset> class CDeque : protected CDequeBase
  88. {
  89. friend CConstDequeIterator<TEntry, LinkageMemberOffset>;
  90. public:
  91. // NTRAID#NTBUG9 - 590101 - 2002/03/29 - mgrier - Should C_ASSERT that the linkage fits in TEntry
  92. CDeque() { }
  93. ~CDeque()
  94. {
  95. CSxsPreserveLastError ple;
  96. ASSERT_NTC(this->Valid());
  97. this->VerifyLinkageFromThisDeque(m_Head);
  98. // You should have cleaned up this deque beforehand...
  99. ASSERT_NTC(m_EntryCount == 0);
  100. m_EntryCount = 0;
  101. ple.Restore();
  102. }
  103. VOID TakeValue(CDeque &rThat)
  104. {
  105. FN_TRACE();
  106. ASSERT(this->Valid());
  107. // Since we don't manage the storage of the entries, "this" deque
  108. // must be empty.
  109. ASSERT(m_EntryCount == 0);
  110. // with regards to linkages, we only need to change the pseudo-head flink
  111. // and blink, the actual head blink and the actual tail flink. However,
  112. // for debugging purposes, we keep the identity of the deque that contains
  113. // the linkage in the linkage, so we also have to fix those.
  114. ASSERT(rThat.Valid());
  115. CDequeLinkage *pLinkage = rThat.GetFlink(rThat.m_Head);
  116. if (pLinkage != NULL)
  117. {
  118. while (pLinkage != &rThat.m_Head)
  119. {
  120. ASSERT(pLinkage->IsNotLocked());
  121. this->SetDeque(pLinkage);
  122. pLinkage = rThat.GetFlink(pLinkage);
  123. }
  124. }
  125. // Now munge the pointers...
  126. this->SetFlink(m_Head, rThat.GetFlink(rThat.m_Head));
  127. this->SetBlink(m_Head, rThat.GetBlink(rThat.m_Head));
  128. this->SetBlink(rThat.GetFlink(rThat.m_Head), &m_Head);
  129. this->SetFlink(rThat.GetBlink(rThat.m_Head), &m_Head);
  130. rThat.SetFlink(rThat.m_Head, &rThat.m_Head);
  131. rThat.SetBlink(rThat.m_Head, &rThat.m_Head);
  132. m_EntryCount = rThat.m_EntryCount;
  133. rThat.m_EntryCount = 0;
  134. }
  135. VOID AddToHead(TEntry *pEntry)
  136. {
  137. FN_TRACE();
  138. ASSERT(this->Valid());
  139. this->InsertAfter(&m_Head, this->MapEntryToLinkage(pEntry), true);
  140. }
  141. VOID AddToTail(TEntry *pEntry)
  142. {
  143. FN_TRACE();
  144. ASSERT(this->Valid());
  145. this->InsertBefore(&m_Head, this->MapEntryToLinkage(pEntry), true);
  146. }
  147. VOID Add(TEntry *pEntry)
  148. {
  149. FN_TRACE();
  150. ASSERT(this->Valid());
  151. AddToTail(pEntry);
  152. }
  153. TEntry *RemoveHead()
  154. {
  155. FN_TRACE();
  156. ASSERT(this->Valid());
  157. TEntry *pEntry = NULL;
  158. if (this->GetFlink(m_Head) != &m_Head)
  159. {
  160. CDequeLinkage *pLinkage = this->GetFlink(m_Head);
  161. this->Remove(pLinkage, true);
  162. pEntry = this->MapLinkageToEntry(pLinkage);
  163. }
  164. return pEntry;
  165. }
  166. TEntry *RemoveTail()
  167. {
  168. FN_TRACE();
  169. ASSERT(this->Valid());
  170. TEntry *pEntry = NULL;
  171. if (this->GetBlink(m_Head) != &m_Head)
  172. {
  173. pEntry = this->GetBlink(m_Head);
  174. this->Remove(pEntry, true);
  175. }
  176. return pEntry;
  177. }
  178. bool IsHead(CDequeLinkage *pLinkage) const { return pLinkage == &m_Head; }
  179. VOID Remove(TEntry *pEntry)
  180. {
  181. FN_TRACE();
  182. ASSERT(this->Valid());
  183. this->Remove(this->MapEntryToLinkage(pEntry), true);
  184. }
  185. template <typename T> VOID ForEach(T *pt, VOID (T::*pmfn)(TEntry *p))
  186. {
  187. FN_TRACE();
  188. ASSERT(this->Valid());
  189. CDequeLinkage *pLinkage = this->GetFlink(m_Head);
  190. if (pLinkage != NULL)
  191. {
  192. while (pLinkage != &m_Head)
  193. {
  194. // You can't remove the element that you're on during a ForEach() call.
  195. pLinkage->Lock();
  196. (pt->*pmfn)(this->MapLinkageToEntry(pLinkage));
  197. pLinkage->Unlock();
  198. pLinkage = this->GetFlink(pLinkage);
  199. }
  200. }
  201. }
  202. template <typename T> VOID ForEach(const T *pt, VOID (T::*pmfn)(TEntry *p) const)
  203. {
  204. FN_TRACE();
  205. ASSERT(this->Valid());
  206. CDequeLinkage *pLinkage = this->GetFlink(m_Head);
  207. if (pLinkage != NULL)
  208. {
  209. while (pLinkage != &m_Head)
  210. {
  211. pLinkage->Lock();
  212. (pt->*pmfn)(this->MapLinkageToEntry(pLinkage));
  213. pLinkage->Unlock();
  214. pLinkage = this->GetFlink(pLinkage);
  215. }
  216. }
  217. }
  218. template <typename T> VOID Clear(T *pt, VOID (T::*pmfn)(TEntry *p))
  219. {
  220. FN_TRACE();
  221. ASSERT(this->Valid());
  222. CDequeLinkage *pLinkage = this->GetFlink(m_Head);
  223. // NTRAID#NTBUG9 - 590101 - 2002/03/29 - mgrier - We should verify that the total iteration
  224. // count (including if pLinkage == NULL!) is equal to m_ElementCount.
  225. if (pLinkage != NULL)
  226. {
  227. while (pLinkage != &m_Head)
  228. {
  229. CDequeLinkage *pLinkage_Next = this->GetFlink(pLinkage);
  230. ASSERT(pLinkage->IsNotLocked());
  231. (pt->*pmfn)(this->MapLinkageToEntry(pLinkage));
  232. pLinkage = pLinkage_Next;
  233. }
  234. }
  235. this->ResetHead();
  236. m_EntryCount = 0;
  237. }
  238. template <typename T> VOID Clear(const T *pt, VOID (T::*pmfn)(TEntry *p) const)
  239. {
  240. FN_TRACE();
  241. ASSERT(this->Valid());
  242. CDequeLinkage *pLinkage = this->GetFlink(m_Head);
  243. if (pLinkage != NULL)
  244. {
  245. while (pLinkage != &m_Head)
  246. {
  247. CDequeLinkage *pLinkage_Next = this->GetFlink(pLinkage);
  248. ASSERT(pLinkage->IsNotLocked());
  249. (pt->*pmfn)(this->MapLinkageToEntry(pLinkage));
  250. pLinkage = pLinkage_Next;
  251. }
  252. }
  253. this->ResetHead();
  254. m_EntryCount = 0;
  255. }
  256. VOID Clear(VOID (TEntry::*pmfn)())
  257. {
  258. FN_TRACE();
  259. ASSERT(this->Valid());
  260. CDequeLinkage *pLinkage = this->GetFlink(m_Head);
  261. if (pLinkage != NULL)
  262. {
  263. while (pLinkage != &m_Head)
  264. {
  265. CDequeLinkage *pLinkage_Next = this->GetFlink(pLinkage);
  266. ASSERT(pLinkage->IsNotLocked());
  267. TEntry* pEntry = this->MapLinkageToEntry(pLinkage);
  268. (pEntry->*pmfn)();
  269. pLinkage = pLinkage_Next;
  270. }
  271. }
  272. this->ResetHead();
  273. m_EntryCount = 0;
  274. }
  275. VOID ClearAndDeleteAll()
  276. {
  277. FN_TRACE();
  278. ASSERT(this->Valid());
  279. CDequeLinkage *pLinkage = this->GetFlink(m_Head);
  280. if (pLinkage != NULL)
  281. {
  282. while (pLinkage != &m_Head)
  283. {
  284. CDequeLinkage *pLinkage_Next = this->GetFlink(pLinkage);
  285. ASSERT(pLinkage->IsNotLocked());
  286. TEntry* pEntry = this->MapLinkageToEntry(pLinkage);
  287. FUSION_DELETE_SINGLETON(pEntry);
  288. pLinkage = pLinkage_Next;
  289. }
  290. }
  291. this->ResetHead();
  292. m_EntryCount = 0;
  293. }
  294. void ClearNoCallback()
  295. {
  296. FN_TRACE();
  297. ASSERT(this->Valid());
  298. this->ResetHead();
  299. m_EntryCount = 0;
  300. }
  301. SIZE_T GetEntryCount() const { return m_EntryCount; }
  302. bool IsEmpty() const { return m_EntryCount == 0; }
  303. protected:
  304. using CDequeBase::Remove;
  305. TEntry *MapLinkageToEntry(CDequeLinkage *pLinkage) const
  306. {
  307. ASSERT_NTC(pLinkage != &m_Head);
  308. if (pLinkage == &m_Head)
  309. return NULL;
  310. return (TEntry *) (((LONG_PTR) pLinkage) - LinkageMemberOffset);
  311. }
  312. CDequeLinkage *MapEntryToLinkage(TEntry *pEntry) const
  313. {
  314. ASSERT_NTC(pEntry != NULL);
  315. return (CDequeLinkage *) (((LONG_PTR) pEntry) + LinkageMemberOffset);
  316. }
  317. private:
  318. CDeque(const CDeque &r); // intentionally not implemented
  319. void operator =(const CDeque &r); // intentionally not implemented
  320. };
  321. enum DequeIteratorMovementDirection
  322. {
  323. eDequeIteratorMoveForward,
  324. eDequeIteratorMoveBackward
  325. };
  326. template <typename TEntry, size_t LinkageMemberOffset> class CConstDequeIterator
  327. {
  328. public:
  329. CConstDequeIterator(const CDeque<TEntry, LinkageMemberOffset> *Deque = NULL) : m_Deque(Deque), m_pCurrent(NULL) { }
  330. ~CConstDequeIterator()
  331. {
  332. if (m_pCurrent != NULL)
  333. {
  334. m_pCurrent->Unlock();
  335. m_pCurrent = NULL;
  336. }
  337. }
  338. VOID Rebind(const CDeque<TEntry, LinkageMemberOffset> *NewDeque)
  339. {
  340. FN_TRACE();
  341. if (m_pCurrent != NULL)
  342. {
  343. m_pCurrent->Unlock();
  344. m_pCurrent = NULL;
  345. }
  346. m_Deque = NewDeque;
  347. if (NewDeque != NULL)
  348. {
  349. m_pCurrent = this->GetFirstLinkage();
  350. m_pCurrent->Lock();
  351. }
  352. }
  353. bool IsBound() const { return (m_Deque != NULL); }
  354. VOID Unbind()
  355. {
  356. FN_TRACE();
  357. if (m_Deque != NULL)
  358. {
  359. if (m_pCurrent != NULL)
  360. {
  361. m_pCurrent->Unlock();
  362. m_pCurrent = NULL;
  363. }
  364. m_Deque = NULL;
  365. }
  366. }
  367. // You can't remove an element that the iterator is sitting on; usually you just
  368. // save the current element and move to the next one, but if you found the exact
  369. // element you wanted and don't want to use the iterator any more, you can Close()
  370. // it to release the lock.
  371. VOID Close()
  372. {
  373. FN_TRACE();
  374. if (m_pCurrent != NULL)
  375. {
  376. m_pCurrent->Unlock();
  377. m_pCurrent = NULL;
  378. }
  379. }
  380. inline VOID Reset()
  381. {
  382. if (m_pCurrent != NULL)
  383. {
  384. m_pCurrent->Unlock();
  385. m_pCurrent = NULL;
  386. }
  387. m_pCurrent = this->GetFirstLinkage();
  388. m_pCurrent->Lock();
  389. }
  390. inline VOID Move(DequeIteratorMovementDirection eDirection)
  391. {
  392. ASSERT_NTC(m_pCurrent != NULL);
  393. ASSERT_NTC((eDirection == eDequeIteratorMoveForward) ||
  394. (eDirection == eDequeIteratorMoveBackward));
  395. m_pCurrent->Unlock();
  396. if (eDirection == eDequeIteratorMoveForward)
  397. m_pCurrent = m_Deque->GetFlink(m_pCurrent);
  398. else if (eDirection == eDequeIteratorMoveBackward)
  399. m_pCurrent = m_Deque->GetBlink(m_pCurrent);
  400. m_pCurrent->Lock();
  401. }
  402. VOID Next() { this->Move(eDequeIteratorMoveForward); }
  403. VOID Previous() { this->Move(eDequeIteratorMoveBackward); }
  404. bool More() const { return (m_pCurrent != NULL) && (m_pCurrent != &m_Deque->m_Head); }
  405. TEntry *operator ->() const { ASSERT_NTC(m_pCurrent != NULL); return this->MapLinkageToEntry(m_pCurrent); }
  406. operator TEntry *() const { ASSERT_NTC(m_pCurrent != NULL); return this->MapLinkageToEntry(m_pCurrent); }
  407. TEntry *Current() const { ASSERT_NTC(m_pCurrent != NULL); return this->MapLinkageToEntry(m_pCurrent); }
  408. protected:
  409. CDequeLinkage *GetFirstLinkage() const { return m_Deque->GetFlink(m_Deque->m_Head); }
  410. CDequeLinkage *GetLastLinkage() const { return m_Deque->GetBlink(m_Deque->m_Head); }
  411. TEntry *MapLinkageToEntry(CDequeLinkage *pLinkage) const { return m_Deque->MapLinkageToEntry(pLinkage); }
  412. const CDeque<TEntry, LinkageMemberOffset> *m_Deque;
  413. CDequeLinkage *m_pCurrent;
  414. };
  415. template <typename TEntry, size_t LinkageMemberOffset> class CDequeIterator : public CConstDequeIterator<TEntry, LinkageMemberOffset>
  416. {
  417. typedef CConstDequeIterator<TEntry, LinkageMemberOffset> Base;
  418. public:
  419. CDequeIterator(CDeque<TEntry, LinkageMemberOffset> *Deque = NULL) : Base(Deque) { }
  420. ~CDequeIterator() { }
  421. VOID Rebind(CDeque<TEntry, LinkageMemberOffset> *NewDeque)
  422. {
  423. FN_TRACE();
  424. if (m_pCurrent != NULL)
  425. {
  426. m_pCurrent->Unlock();
  427. m_pCurrent = NULL;
  428. }
  429. m_Deque = NewDeque;
  430. if (NewDeque != NULL)
  431. {
  432. m_pCurrent = this->GetFirstLinkage();
  433. m_pCurrent->Lock();
  434. }
  435. }
  436. TEntry *RemoveCurrent(DequeIteratorMovementDirection eDirection)
  437. {
  438. FN_TRACE();
  439. TEntry *Result = NULL;
  440. ASSERT(m_pCurrent != NULL);
  441. ASSERT(!m_Deque->IsHead(m_pCurrent));
  442. if ((m_pCurrent != NULL) && (!m_Deque->IsHead(m_pCurrent)))
  443. {
  444. Result = this->MapLinkageToEntry(m_pCurrent);
  445. this->Move(eDirection);
  446. const_cast<CDeque<TEntry, LinkageMemberOffset> *>(m_Deque)->Remove(Result);
  447. }
  448. return Result;
  449. }
  450. void DeleteCurrent(DequeIteratorMovementDirection eDirection)
  451. {
  452. FN_TRACE();
  453. TEntry *Result = this->RemoveCurrent(eDirection);
  454. if (Result != NULL)
  455. FUSION_DELETE_SINGLETON(Result);
  456. }
  457. protected:
  458. // All member data is in the parent...
  459. };
  460. #ifdef FN_TRACE_SHOULD_POP
  461. #pragma pop_macro("FN_TRACE")
  462. #undef FN_TRACE_SHOULD_POP
  463. #elif defined(FN_TRACE_SHOULD_DESTROY)
  464. #undef FN_TRACE
  465. #endif
  466. #ifdef FN_TRACE_CONSTRUCTOR_SHOULD_POP
  467. #pragma pop_macro("FN_TRACE_CONSTRUCTOR")
  468. #undef FN_TRACE_CONSTRUCTOR_SHOULD_POP
  469. #elif defined(FN_TRACE_CONSTRUCTOR_SHOULD_DESTROY)
  470. #undef FN_TRACE_CONSTRUCTOR
  471. #endif
  472. #ifdef FN_TRACE_DESTRUCTOR_SHOULD_POP
  473. #pragma pop_macro("FN_TRACE_DESTRUCTOR")
  474. #undef FN_TRACE_DESTRUCTOR_SHOULD_POP
  475. #elif defined(FN_TRACE_DESTRUCTOR_SHOULD_DESTROY)
  476. #undef FN_TRACE_DESTRUCTOR
  477. #endif