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.

309 lines
8.1 KiB

  1. /*--------------------------------------------------------------------------*
  2. *
  3. * Microsoft Windows
  4. * Copyright (C) Microsoft Corporation, 1992 - 1999
  5. *
  6. * File: idle.cpp
  7. *
  8. * Contents: Implementation file for CIdleTaskQueue
  9. *
  10. * History: 13-Apr-99 jeffro Created
  11. *
  12. *--------------------------------------------------------------------------*/
  13. #include "stdafx.h"
  14. //############################################################################
  15. //############################################################################
  16. //
  17. // Traces
  18. //
  19. //############################################################################
  20. //############################################################################
  21. #ifdef DBG
  22. CTraceTag tagIdle(TEXT("IdleTaskQueue"), TEXT("IdleTaskQueue"));
  23. #endif //DBG
  24. //############################################################################
  25. //############################################################################
  26. //
  27. // Implementation of CIdleTask
  28. //
  29. //############################################################################
  30. //############################################################################
  31. DEBUG_DECLARE_INSTANCE_COUNTER(CIdleTask);
  32. CIdleTask::CIdleTask()
  33. {
  34. DEBUG_INCREMENT_INSTANCE_COUNTER(CIdleTask);
  35. }
  36. CIdleTask::~CIdleTask()
  37. {
  38. DEBUG_DECREMENT_INSTANCE_COUNTER(CIdleTask);
  39. }
  40. CIdleTask::CIdleTask(const CIdleTask &rhs)
  41. {
  42. DEBUG_INCREMENT_INSTANCE_COUNTER(CIdleTask);
  43. *this = rhs;
  44. }
  45. CIdleTask&
  46. CIdleTask::operator= (const CIdleTask& rhs)
  47. {
  48. return *this;
  49. }
  50. //############################################################################
  51. //############################################################################
  52. //
  53. // Implementation of CIdleQueueEntry
  54. //
  55. //############################################################################
  56. //############################################################################
  57. DEBUG_DECLARE_INSTANCE_COUNTER(CIdleQueueEntry);
  58. CIdleQueueEntry::CIdleQueueEntry(const CIdleQueueEntry &rhs)
  59. {
  60. DEBUG_INCREMENT_INSTANCE_COUNTER(CIdleQueueEntry);
  61. *this = rhs;
  62. }
  63. CIdleQueueEntry&
  64. CIdleQueueEntry::operator= (const CIdleQueueEntry& rhs)
  65. {
  66. m_pTask = rhs.m_pTask;
  67. m_ePriority = rhs.m_ePriority;
  68. return (*this);
  69. }
  70. //############################################################################
  71. //############################################################################
  72. //
  73. // Implementation of CIdleTaskQueue
  74. //
  75. //############################################################################
  76. //############################################################################
  77. DEBUG_DECLARE_INSTANCE_COUNTER(CIdleTaskQueue);
  78. CIdleTaskQueue::CIdleTaskQueue()
  79. {
  80. DEBUG_INCREMENT_INSTANCE_COUNTER(CIdleTaskQueue);
  81. }
  82. CIdleTaskQueue::~CIdleTaskQueue()
  83. {
  84. DEBUG_DECREMENT_INSTANCE_COUNTER(CIdleTaskQueue);
  85. while(!m_queue.empty())
  86. {
  87. CIdleTask *pIdleTask = m_queue.top().GetTask();
  88. m_queue.pop();
  89. ASSERT(pIdleTask != NULL);
  90. if(pIdleTask!=NULL)
  91. {
  92. delete pIdleTask;
  93. }
  94. }
  95. }
  96. /*+-------------------------------------------------------------------------*
  97. * CIdleTaskQueue::ScPushTask
  98. *
  99. *
  100. * Adds the given task the list of tasks to execute at idle time.
  101. *
  102. * S_OK the task was added to the list.
  103. * S_FALSE the task was merged with an existing task.
  104. * other the task was not added to the list
  105. *
  106. *--------------------------------------------------------------------------*/
  107. SC CIdleTaskQueue::ScPushTask (
  108. CIdleTask* pitToPush,
  109. IdleTaskPriority ePriority)
  110. {
  111. SC sc;
  112. ATOM idToPush;
  113. /*
  114. * validate the parameters
  115. */
  116. if (IsBadWritePtr (pitToPush, sizeof (*pitToPush)))
  117. {
  118. sc = E_POINTER;
  119. goto Error;
  120. }
  121. if ((ePriority < ePriority_Low) || (ePriority > ePriority_High))
  122. {
  123. ASSERT (false && "Invalid idle task priority");
  124. sc = E_INVALIDARG;
  125. goto Error;
  126. }
  127. sc = pitToPush->ScGetTaskID (&idToPush);
  128. if(sc)
  129. goto Error;
  130. #ifdef DBG
  131. TCHAR szNameToPush[64];
  132. if (0 == GetAtomName (idToPush, szNameToPush, countof (szNameToPush)))
  133. {
  134. sc.FromLastError();
  135. goto Error;
  136. }
  137. #endif
  138. /*
  139. * if we have tasks in the queue, look for one we can merge with
  140. */
  141. if (!m_queue.empty())
  142. {
  143. Queue::iterator it = m_queue.begin();
  144. Queue::iterator itEnd = m_queue.end();
  145. while ( (!sc.IsError()) &&
  146. (it = FindTaskByID(it, itEnd, idToPush)) != itEnd)
  147. {
  148. #ifdef DBG
  149. ATOM idMergeTarget;
  150. it->GetTask()->ScGetTaskID(&idMergeTarget);
  151. TCHAR szMergeTargetName[64];
  152. if (0 == GetAtomName (idMergeTarget, szMergeTargetName, countof (szMergeTargetName)))
  153. {
  154. sc.FromLastError();
  155. goto Error;
  156. }
  157. Trace (tagIdle, _T("%s (0x%08x) %smerged with %s (0x%08x) (%d idle tasks)"),
  158. szNameToPush,
  159. pitToPush,
  160. (sc) ? _T("not ") : _T(""),
  161. szMergeTargetName,
  162. it->GetTask(),
  163. m_queue.size());
  164. #endif
  165. sc = it->GetTask()->ScMerge(pitToPush);
  166. if(sc==S_OK) // successfully merged? just return
  167. {
  168. delete pitToPush;
  169. sc = S_FALSE;
  170. goto Cleanup;
  171. }
  172. // bump past the task we didn't merge with
  173. ++it;
  174. }
  175. }
  176. m_queue.push (CIdleQueueEntry (pitToPush, ePriority));
  177. #ifdef DBG
  178. Trace (tagIdle, _T("%s (0x%08x) pushed, priority %d (%d idle tasks)"),
  179. szNameToPush,
  180. pitToPush,
  181. ePriority,
  182. m_queue.size());
  183. #endif
  184. Cleanup:
  185. return sc;
  186. Error:
  187. TraceError(TEXT("CIdleTaskQueue::ScPushTask"), sc);
  188. goto Cleanup;
  189. }
  190. /*+-------------------------------------------------------------------------*
  191. * CIdleTaskQueue::ScPerformNextTask
  192. *
  193. *
  194. * Performs the next task, if any.
  195. * Removes the highest priority idle task from the task list, and calls ScDoWork() on it.
  196. *
  197. *--------------------------------------------------------------------------*/
  198. SC
  199. CIdleTaskQueue::ScPerformNextTask ()
  200. {
  201. DECLARE_SC (sc, _T("CIdleTaskQueue::ScPerformNextTask"));
  202. if (m_queue.empty())
  203. return (sc);
  204. CAutoPtr<CIdleTask> spIdleTask (m_queue.top().GetTask());
  205. if (spIdleTask == NULL)
  206. return (sc = E_UNEXPECTED);
  207. m_queue.pop();
  208. #ifdef DBG
  209. ATOM idTask;
  210. spIdleTask->ScGetTaskID(&idTask);
  211. TCHAR szTaskName[64];
  212. if (0 == GetAtomName (idTask, szTaskName, countof (szTaskName)))
  213. return (sc.FromLastError());
  214. Trace (tagIdle, _T("Performing %s (0x%08x) (%d idle tasks remaining)"),
  215. szTaskName,
  216. (CIdleTask*) spIdleTask,
  217. m_queue.size());
  218. #endif
  219. sc = spIdleTask->ScDoWork();
  220. if (sc)
  221. return (sc);
  222. return (sc);
  223. }
  224. /*+-------------------------------------------------------------------------*
  225. * CIdleTaskQueue::ScGetTaskCount
  226. *
  227. * Returns the number of tasks in the idle list.
  228. *--------------------------------------------------------------------------*/
  229. SC CIdleTaskQueue::ScGetTaskCount (LONG_PTR* plCount)
  230. {
  231. SC sc;
  232. if (IsBadWritePtr (plCount, sizeof (*plCount)))
  233. {
  234. sc = E_POINTER;
  235. goto Error;
  236. }
  237. *plCount = m_queue.size();
  238. Cleanup:
  239. return sc;
  240. Error:
  241. TraceError(TEXT("CIdleTaskQueue::ScGetTaskCount"), sc);
  242. goto Cleanup;
  243. }
  244. /*+-------------------------------------------------------------------------*
  245. * CIdleTaskQueue::FindTaskByID
  246. *
  247. *
  248. *--------------------------------------------------------------------------*/
  249. CIdleTaskQueue::Queue::iterator CIdleTaskQueue::FindTaskByID (
  250. CIdleTaskQueue::Queue::iterator itFirst,
  251. CIdleTaskQueue::Queue::iterator itLast,
  252. ATOM idToFind)
  253. {
  254. return (std::find_if (itFirst, itLast,
  255. std::bind2nd (EqualTaskID(), idToFind)));
  256. }