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.

300 lines
7.6 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. GetAtomName (idToPush, szNameToPush, countof (szNameToPush));
  133. #endif
  134. /*
  135. * if we have tasks in the queue, look for one we can merge with
  136. */
  137. if (!m_queue.empty())
  138. {
  139. Queue::iterator it = m_queue.begin();
  140. Queue::iterator itEnd = m_queue.end();
  141. while ( (!sc.IsError()) &&
  142. (it = FindTaskByID(it, itEnd, idToPush)) != itEnd)
  143. {
  144. #ifdef DBG
  145. ATOM idMergeTarget;
  146. it->GetTask()->ScGetTaskID(&idMergeTarget);
  147. TCHAR szMergeTargetName[64];
  148. GetAtomName (idMergeTarget, szMergeTargetName, countof (szMergeTargetName));
  149. Trace (tagIdle, _T("%s (0x%08x) %smerged with %s (0x%08x) (%d idle tasks)"),
  150. szNameToPush,
  151. pitToPush,
  152. (sc) ? _T("not ") : _T(""),
  153. szMergeTargetName,
  154. it->GetTask(),
  155. m_queue.size());
  156. #endif
  157. sc = it->GetTask()->ScMerge(pitToPush);
  158. if(sc==S_OK) // successfully merged? just return
  159. {
  160. delete pitToPush;
  161. sc = S_FALSE;
  162. goto Cleanup;
  163. }
  164. // bump past the task we didn't merge with
  165. ++it;
  166. }
  167. }
  168. m_queue.push (CIdleQueueEntry (pitToPush, ePriority));
  169. #ifdef DBG
  170. Trace (tagIdle, _T("%s (0x%08x) pushed, priority %d (%d idle tasks)"),
  171. szNameToPush,
  172. pitToPush,
  173. ePriority,
  174. m_queue.size());
  175. #endif
  176. Cleanup:
  177. return sc;
  178. Error:
  179. TraceError(TEXT("CIdleTaskQueue::ScPushTask"), sc);
  180. goto Cleanup;
  181. }
  182. /*+-------------------------------------------------------------------------*
  183. * CIdleTaskQueue::ScPerformNextTask
  184. *
  185. *
  186. * Performs the next task, if any.
  187. * Removes the highest priority idle task from the task list, and calls ScDoWork() on it.
  188. *
  189. *--------------------------------------------------------------------------*/
  190. SC
  191. CIdleTaskQueue::ScPerformNextTask ()
  192. {
  193. DECLARE_SC (sc, _T("CIdleTaskQueue::ScPerformNextTask"));
  194. if (m_queue.empty())
  195. return (sc);
  196. CAutoPtr<CIdleTask> spIdleTask (m_queue.top().GetTask());
  197. if (spIdleTask == NULL)
  198. return (sc = E_UNEXPECTED);
  199. m_queue.pop();
  200. #ifdef DBG
  201. ATOM idTask;
  202. spIdleTask->ScGetTaskID(&idTask);
  203. TCHAR szTaskName[64];
  204. GetAtomName (idTask, szTaskName, countof (szTaskName));
  205. Trace (tagIdle, _T("Performing %s (0x%08x) (%d idle tasks remaining)"),
  206. szTaskName,
  207. (CIdleTask*) spIdleTask,
  208. m_queue.size());
  209. #endif
  210. sc = spIdleTask->ScDoWork();
  211. if (sc)
  212. return (sc);
  213. return (sc);
  214. }
  215. /*+-------------------------------------------------------------------------*
  216. * CIdleTaskQueue::ScGetTaskCount
  217. *
  218. * Returns the number of tasks in the idle list.
  219. *--------------------------------------------------------------------------*/
  220. SC CIdleTaskQueue::ScGetTaskCount (LONG_PTR* plCount)
  221. {
  222. SC sc;
  223. if (IsBadWritePtr (plCount, sizeof (*plCount)))
  224. {
  225. sc = E_POINTER;
  226. goto Error;
  227. }
  228. *plCount = m_queue.size();
  229. Cleanup:
  230. return sc;
  231. Error:
  232. TraceError(TEXT("CIdleTaskQueue::ScGetTaskCount"), sc);
  233. goto Cleanup;
  234. }
  235. /*+-------------------------------------------------------------------------*
  236. * CIdleTaskQueue::FindTaskByID
  237. *
  238. *
  239. *--------------------------------------------------------------------------*/
  240. CIdleTaskQueue::Queue::iterator CIdleTaskQueue::FindTaskByID (
  241. CIdleTaskQueue::Queue::iterator itFirst,
  242. CIdleTaskQueue::Queue::iterator itLast,
  243. ATOM idToFind)
  244. {
  245. return (std::find_if (itFirst, itLast,
  246. std::bind2nd (EqualTaskID(), idToFind)));
  247. }