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.

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