Source code of Windows XP (NT5)
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.

342 lines
7.4 KiB

  1. //
  2. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
  3. //
  4. #include <precomp.h>
  5. CTreeElement :: CTreeElement(LPCWSTR lpszHashedName, CRefCountedObject *pObject)
  6. {
  7. m_lpszHashedName = new WCHAR[wcslen(lpszHashedName) + 1];
  8. wcscpy(m_lpszHashedName, lpszHashedName);
  9. m_pObject = pObject;
  10. m_pObject->AddRef();
  11. m_pLeft = NULL;
  12. m_pRight = NULL;
  13. }
  14. CTreeElement :: ~CTreeElement()
  15. {
  16. delete [] m_lpszHashedName;
  17. m_pObject->Release();
  18. }
  19. LPCWSTR CTreeElement :: GetHashedName() const
  20. {
  21. return m_lpszHashedName;
  22. }
  23. CRefCountedObject *CTreeElement :: GetObject() const
  24. {
  25. m_pObject->AddRef();
  26. return m_pObject;
  27. }
  28. CTreeElement *CTreeElement :: GetRight() const
  29. {
  30. return m_pRight;
  31. }
  32. CTreeElement *CTreeElement :: GetLeft() const
  33. {
  34. return m_pLeft;
  35. }
  36. void CTreeElement :: SetRight(CTreeElement *pNext)
  37. {
  38. m_pRight = pNext;
  39. }
  40. void CTreeElement :: SetLeft(CTreeElement *pNext)
  41. {
  42. m_pLeft = pNext;
  43. }
  44. CObjectTree :: CObjectTree()
  45. {
  46. // Initialize the critical section
  47. InitializeCriticalSection(&m_ModificationSection);
  48. m_dwNumElements = 0;
  49. m_pHead = NULL;
  50. }
  51. CObjectTree :: ~CObjectTree()
  52. {
  53. // Destroy the data
  54. DeleteTree();
  55. // Destroy the critical section
  56. DeleteCriticalSection(&m_ModificationSection);
  57. }
  58. void CObjectTree :: DeleteTree()
  59. {
  60. EnterCriticalSection(&m_ModificationSection);
  61. if(m_pHead)
  62. DeleteSubTree(m_pHead);
  63. m_dwNumElements = 0;
  64. LeaveCriticalSection(&m_ModificationSection);
  65. }
  66. void CObjectTree :: DeleteSubTree(CTreeElement *pRoot)
  67. {
  68. if(pRoot->GetLeft())
  69. DeleteSubTree(pRoot->GetLeft());
  70. if(pRoot->GetRight())
  71. DeleteSubTree(pRoot->GetRight());
  72. delete pRoot;
  73. }
  74. BOOLEAN CObjectTree :: AddElement(LPCWSTR lpszHashedName, CRefCountedObject *pObject)
  75. {
  76. BOOLEAN retVal = TRUE;
  77. EnterCriticalSection(&m_ModificationSection);
  78. CTreeElement *pCurrent = m_pHead;
  79. CTreeElement *pParent = NULL;
  80. int iCompare;
  81. // Locate the position where the new element is to be inserted
  82. while(pCurrent)
  83. {
  84. iCompare = _wcsicmp(lpszHashedName, pCurrent->GetHashedName());
  85. if(iCompare == 0)
  86. {
  87. retVal = FALSE; // The element already exists
  88. break;
  89. }
  90. else if(iCompare > 0)
  91. {
  92. pParent = pCurrent;
  93. pCurrent = pCurrent->GetRight();
  94. }
  95. else
  96. {
  97. pParent = pCurrent;
  98. pCurrent = pCurrent->GetLeft();
  99. }
  100. }
  101. // Create the new element at the appropriate position
  102. if(retVal == TRUE && pParent)
  103. {
  104. iCompare = _wcsicmp(lpszHashedName, pParent->GetHashedName());
  105. if(iCompare == 0)
  106. retVal = FALSE;
  107. else if(iCompare > 0)
  108. {
  109. retVal = TRUE;
  110. pParent->SetRight(new CTreeElement(lpszHashedName, pObject));
  111. }
  112. else
  113. {
  114. retVal = TRUE;
  115. pParent->SetLeft(new CTreeElement(lpszHashedName, pObject));
  116. }
  117. }
  118. else if (retVal == TRUE)
  119. {
  120. m_pHead = new CTreeElement(lpszHashedName, pObject);
  121. retVal = TRUE;
  122. }
  123. // Increment the object count if the insertion was successful
  124. if(retVal)
  125. m_dwNumElements ++;
  126. LeaveCriticalSection(&m_ModificationSection);
  127. return retVal;
  128. }
  129. BOOLEAN CObjectTree :: DeleteElement(LPCWSTR lpszHashedName)
  130. {
  131. BOOLEAN retVal = FALSE;
  132. int iDirection = 0; // 0 indicates Unknown, 1 indicates LEFT and 2 indicates RIGHT
  133. EnterCriticalSection(&m_ModificationSection);
  134. if(m_pHead == NULL)
  135. retVal = FALSE;
  136. else
  137. {
  138. // Find the node to be deleted and its parent
  139. CTreeElement *pParent = NULL;
  140. CTreeElement *pCurrent = m_pHead;
  141. int iCompare;
  142. while(pCurrent)
  143. {
  144. iCompare = _wcsicmp(lpszHashedName, pCurrent->GetHashedName());
  145. if(iCompare == 0)
  146. break;
  147. else if(iCompare < 0)
  148. {
  149. iDirection = 1;
  150. pParent = pCurrent;
  151. pCurrent = pCurrent->GetLeft();
  152. }
  153. else
  154. {
  155. iDirection = 2;
  156. pParent = pCurrent;
  157. pCurrent = pCurrent->GetRight();
  158. }
  159. }
  160. if(!pCurrent)
  161. // The element was not found
  162. retVal = FALSE;
  163. else
  164. {
  165. CTreeElement *pCutPart = NULL;
  166. // If its left child is null, attach the right subtree to parent
  167. if(pCurrent->GetLeft() == NULL)
  168. pCutPart = pCurrent->GetRight();
  169. // If its right child is null, attach the left subtree to parent
  170. else if(pCurrent->GetRight() == NULL)
  171. pCutPart = pCurrent->GetLeft();
  172. else // We need to find the inorder successor
  173. {
  174. CTreeElement *pInorderSuccessor = pCurrent->GetRight();
  175. if(pInorderSuccessor->GetLeft() == NULL)
  176. {
  177. pInorderSuccessor->SetLeft(pCurrent->GetLeft());
  178. pCutPart = pInorderSuccessor;
  179. }
  180. else
  181. {
  182. CTreeElement *pPredecessor = pCurrent->GetRight();
  183. pInorderSuccessor = pPredecessor->GetLeft();
  184. while(pInorderSuccessor->GetLeft())
  185. {
  186. pPredecessor = pInorderSuccessor;
  187. pInorderSuccessor = pPredecessor->GetLeft();
  188. }
  189. pPredecessor->SetLeft(pInorderSuccessor->GetRight());
  190. pInorderSuccessor->SetLeft(pCurrent->GetLeft());
  191. pInorderSuccessor->SetRight(pCurrent->GetRight());
  192. pCutPart = pInorderSuccessor;
  193. }
  194. }
  195. if(iDirection == 0)
  196. m_pHead = pCutPart;
  197. else if (iDirection == 1)
  198. pParent->SetLeft(pCutPart);
  199. else
  200. pParent->SetRight(pCutPart);
  201. delete pCurrent;
  202. retVal = TRUE;
  203. }
  204. }
  205. // Decrement the count of items in the tree
  206. if(retVal)
  207. m_dwNumElements --;
  208. LeaveCriticalSection(&m_ModificationSection);
  209. return retVal;
  210. }
  211. CRefCountedObject * CObjectTree :: GetElement(LPCWSTR lpszHashedName)
  212. {
  213. EnterCriticalSection(&m_ModificationSection);
  214. CTreeElement *pCurrent = m_pHead;
  215. CRefCountedObject *pRetVal = NULL;
  216. int iCompare;
  217. while(pCurrent)
  218. {
  219. iCompare = _wcsicmp(lpszHashedName, pCurrent->GetHashedName());
  220. if(iCompare == 0)
  221. {
  222. pRetVal = pCurrent->GetObject();
  223. break;
  224. }
  225. else if (iCompare > 0)
  226. pCurrent = pCurrent->GetRight();
  227. else
  228. pCurrent = pCurrent->GetLeft();
  229. }
  230. LeaveCriticalSection(&m_ModificationSection);
  231. return pRetVal;
  232. }
  233. BOOLEAN CObjectTree :: DeleteLeastRecentlyAccessedElement()
  234. {
  235. BOOLEAN retVal = FALSE;
  236. EnterCriticalSection(&m_ModificationSection);
  237. if(m_pHead)
  238. {
  239. CRefCountedObject *pOldestElement = m_pHead->GetObject();
  240. CRefCountedObject *pLeftOldestElement = GetLeastRecentlyAccessedElementRecursive(m_pHead->GetLeft());
  241. CRefCountedObject *pRightOldestElement = GetLeastRecentlyAccessedElementRecursive(m_pHead->GetRight());
  242. if (pLeftOldestElement)
  243. {
  244. if(pLeftOldestElement->GetLastAccessTime() < pOldestElement->GetLastAccessTime())
  245. {
  246. pOldestElement->Release();
  247. pOldestElement = pLeftOldestElement;
  248. }
  249. else
  250. pLeftOldestElement->Release();
  251. }
  252. if (pRightOldestElement)
  253. {
  254. if(pRightOldestElement->GetLastAccessTime() < pOldestElement->GetLastAccessTime())
  255. {
  256. pOldestElement->Release();
  257. pOldestElement = pRightOldestElement;
  258. }
  259. else
  260. pRightOldestElement->Release();
  261. }
  262. retVal = DeleteElement(pOldestElement->GetName());
  263. pOldestElement->Release();
  264. }
  265. LeaveCriticalSection(&m_ModificationSection);
  266. return retVal;
  267. }
  268. CRefCountedObject * CObjectTree :: GetLeastRecentlyAccessedElementRecursive(CTreeElement *pElement)
  269. {
  270. CRefCountedObject *pObject = NULL;
  271. if(pElement)
  272. {
  273. pObject = pElement->GetObject();
  274. CRefCountedObject *pLeftObject = GetLeastRecentlyAccessedElementRecursive(pElement->GetLeft());
  275. if(pLeftObject)
  276. {
  277. if(pLeftObject->GetCreationTime() < pObject->GetCreationTime())
  278. {
  279. pObject->Release();
  280. pObject = pLeftObject;
  281. }
  282. else
  283. pLeftObject->Release();
  284. }
  285. CRefCountedObject *pRightObject = GetLeastRecentlyAccessedElementRecursive(pElement->GetRight());
  286. if(pRightObject)
  287. {
  288. if (pRightObject->GetCreationTime() < pObject->GetCreationTime())
  289. {
  290. pObject->Release();
  291. pObject = pRightObject;
  292. }
  293. else
  294. pRightObject->Release();
  295. }
  296. }
  297. return pObject;
  298. }