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.

234 lines
4.3 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. sleepn.cxx
  6. Abstract:
  7. Handles delayed callbacks. Delay must be < 49.7 days, and the
  8. callback must execute very quickly.
  9. Author:
  10. Albert Ting (AlbertT) 19-Dec-1994
  11. Revision History:
  12. --*/
  13. #include "spllibp.hxx"
  14. #pragma hdrstop
  15. TSleepNotify::
  16. TSleepNotify(
  17. VOID
  18. )
  19. /*++
  20. Routine Description:
  21. Single thread that servers as a timer.
  22. Arguments:
  23. Return Value:
  24. Notes:
  25. _hEvent is our validity variable.
  26. --*/
  27. {
  28. _hEvent = CreateEvent( NULL,
  29. FALSE,
  30. FALSE,
  31. NULL );
  32. if( !_hEvent ){
  33. return;
  34. }
  35. }
  36. #if 0
  37. TSleepNotify::
  38. ~TSleepNotify(
  39. VOID
  40. )
  41. /*++
  42. Routine Description:
  43. Destroys the SleepNotify. This should never be called since we
  44. never should destruct the object.
  45. Arguments:
  46. Return Value:
  47. --*/
  48. {
  49. if( _hEvent ){
  50. CloseHandle( _hEvent );
  51. }
  52. }
  53. #endif
  54. VOID
  55. TSleepNotify::
  56. vRun(
  57. VOID
  58. )
  59. /*++
  60. Routine Description:
  61. Main worker loop for callbacks. We will wait on an object
  62. to pickup new notifications, and when we time out, do the callback.
  63. Arguments:
  64. VOID
  65. Return Value:
  66. VOID: never returns.
  67. --*/
  68. {
  69. DWORD dwTimeout;
  70. DWORD dwResult;
  71. VSleepWorker* pSleepWorker;
  72. TCritSecLock CSL( _CritSec );
  73. while( TRUE ){
  74. pSleepWorker = SleepWorker_pHead();
  75. dwTimeout = pSleepWorker ?
  76. pSleepWorker->TickCountWake - GetTickCount() :
  77. INFINITE;
  78. {
  79. TCritSecUnlock CSU( _CritSec );
  80. dwResult = WaitForSingleObject( _hEvent, dwTimeout );
  81. }
  82. if( dwResult == WAIT_TIMEOUT ){
  83. //
  84. // We added a new item, so go back to sleep with the
  85. // new timeout value.
  86. //
  87. continue;
  88. }
  89. //
  90. // Traverse linked list for all items that must be callbacked.
  91. //
  92. PDLINK pdlink;
  93. TICKCOUNT TickCountNow = GetTickCount();
  94. for( pdlink = SleepWorker_pdlHead();
  95. SleepWorker_bValid( pdlink ); ){
  96. pSleepWorker = SleepWorker_pConvert( pdlink );
  97. pdlink = SleepWorker_pdlNext( pdlink );
  98. if( pSleepWorker->TickCountWake - TickCountNow < kTickCountMargin ){
  99. //
  100. // We should wake up this guy now.
  101. // There is a 1 hr margin since these call backs to
  102. // take time to execute, and we may miss one of them.
  103. //
  104. pSleepWorker->vCallback();
  105. //
  106. // Remove current item from linked list.
  107. //
  108. pSleepWorker->SleepWorker_vDelinkSelf();
  109. } else {
  110. //
  111. // This item still needs to sleep a little longer.
  112. // Since they are ordered by sleep time, we can
  113. // stop now.
  114. //
  115. break;
  116. }
  117. }
  118. }
  119. }
  120. VOID
  121. TSleepNotify::
  122. vAdd(
  123. VSleepWorker& SleepWorkerAdd,
  124. TICKCOUNT TickCountWake
  125. )
  126. /*++
  127. Routine Description:
  128. Insert a SleepWorker into the list of items sleeping based on
  129. when it wants to wake. The shortest sleepers are first on the list.
  130. Arguments:
  131. SleepWorkerAdd -- Item that wants to sleep a while.
  132. TickCountWake -- Tick count that we want to wake at.
  133. Return Value:
  134. --*/
  135. {
  136. TCritSecLock CSL( _CritSec );
  137. //
  138. // Traverse until we see someone that wants to sleep more than us.
  139. //
  140. PDLINK pdlink;
  141. VSleepWorker* pSleepWorker;
  142. TICKCOUNT TickCountNow = GetTickCount();
  143. TICKCOUNT TickCountSleep = TickCountWake - TickCountNow;
  144. for( pdlink = SleepWorker_pdlHead();
  145. SleepWorker_bValid( pdlink );
  146. pdlink = SleepWorker_pdlNext( pdlink ) ){
  147. pSleepWorker = SleepWorker_pConvert( pdlink );
  148. //
  149. // If the amount this item wants to sleep is greater than
  150. // the amount we want to sleep, then insert item here.
  151. //
  152. if( pSleepWorker->TickCountWake - TickCountNow > TickCountSleep ){
  153. SleepWorker_vInsertBefore( pdlink, &SleepWorkerAdd );
  154. return;
  155. }
  156. }
  157. //
  158. // No items or last item.
  159. // Add to end of list.
  160. //
  161. SleepWorker_vAppend( &SleepWorkerAdd );
  162. }