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.

146 lines
3.5 KiB

  1. /*
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. */
  4. #include "stdafx.h"
  5. #include "atlconv.h"
  6. #include "termmgr.h"
  7. #include "timerq.h"
  8. DWORD
  9. CTimerQueue::GetTimeToTimeout(
  10. )
  11. {
  12. if ( IsEmpty() ) return INFINITE;
  13. CFilterInfo *FirstEntry = m_Head.m_pNext;
  14. DWORD FirstTimeout = FirstEntry->m_WaitTime;
  15. // get current time
  16. DWORD CurrentTime = timeGetTime();
  17. // get the minimum time difference between the two
  18. // this should get rid of the wrap problem
  19. BOOL bIsWrap;
  20. DWORD TimeDiff = GetMinDiff(CurrentTime, FirstTimeout, bIsWrap);
  21. // if this time diff value is > MAX_TIMEOUT, it has to be in the
  22. // past - schedule it now
  23. if (TimeDiff > MAX_TIMEOUT) return 0;
  24. // check if the timeout event is in the past - schedule it for now
  25. if ( bIsWrap )
  26. {
  27. // if there is a wrap around, the first timeout must be the
  28. // one causing it (the wrap around), otherwise its in the past
  29. if ( CurrentTime <= FirstTimeout ) return 0;
  30. }
  31. else
  32. {
  33. // no wrap around, so if we timeout is behind current time, its past
  34. if ( FirstTimeout <= CurrentTime ) return 0;
  35. }
  36. return TimeDiff;
  37. }
  38. DWORD
  39. CTimerQueue::GetMinDiff(
  40. IN DWORD Time1,
  41. IN DWORD Time2,
  42. OUT BOOL &bIsWrap
  43. )
  44. {
  45. DWORD NormalDiff;
  46. DWORD WrapDiff;
  47. if (Time1 < Time2)
  48. {
  49. NormalDiff = Time2 - Time1;
  50. WrapDiff = MAX_DWORD - NormalDiff;
  51. }
  52. else
  53. {
  54. NormalDiff = Time1 - Time2;
  55. WrapDiff = MAX_DWORD - NormalDiff;
  56. }
  57. if (NormalDiff < WrapDiff)
  58. {
  59. bIsWrap = FALSE;
  60. return NormalDiff;
  61. }
  62. else
  63. {
  64. bIsWrap = TRUE;
  65. return WrapDiff;
  66. }
  67. // should never reach this place
  68. TM_ASSERT(FALSE);
  69. return 0;
  70. }
  71. void
  72. CTimerQueue::Insert(
  73. IN CFilterInfo *pNewFilterInfo
  74. )
  75. {
  76. TM_ASSERT(NULL != pNewFilterInfo);
  77. TM_ASSERT(!pNewFilterInfo->InQueue());
  78. // walk through the queue until an entry with
  79. // an equal or greater wait time is found
  80. // need to account for the wrap
  81. DWORD NewTime = pNewFilterInfo->m_WaitTime;
  82. CFilterInfo *pCurrent = m_Head.m_pNext;
  83. while (!IsHead(pCurrent))
  84. {
  85. // get the minimum time difference between the two
  86. // this should get rid of the wrap problem
  87. BOOL IsWrap;
  88. DWORD TimeDiff = GetMinDiff(pCurrent->m_WaitTime, NewTime, IsWrap);
  89. // if there is a wrap around, and the pCurrent time causes it, the
  90. // current entry must be greater than the new time
  91. if ( IsWrap && (pCurrent->m_WaitTime <= NewTime) ) break;
  92. // if the current time is greater than the new time
  93. if ( !IsWrap && (NewTime <= pCurrent->m_WaitTime) ) break;
  94. pCurrent = pCurrent->m_pNext;
  95. }
  96. // insert before pCurrent
  97. pCurrent->m_pPrev->m_pNext = pNewFilterInfo;
  98. pNewFilterInfo->m_pPrev = pCurrent->m_pPrev;
  99. pCurrent->m_pPrev = pNewFilterInfo;
  100. pNewFilterInfo->m_pNext = pCurrent;
  101. }
  102. BOOL
  103. CTimerQueue::Remove(
  104. IN CFilterInfo *pFilterInfo
  105. )
  106. {
  107. TM_ASSERT(NULL != pFilterInfo);
  108. TM_ASSERT(!IsHead(pFilterInfo));
  109. // either both prev/next are null or both are not null
  110. TM_ASSERT((NULL == pFilterInfo->m_pPrev) == \
  111. (NULL == pFilterInfo->m_pNext));
  112. if ( (NULL == pFilterInfo->m_pNext) && (NULL == pFilterInfo->m_pPrev) )
  113. return FALSE;
  114. pFilterInfo->m_pPrev->m_pNext = pFilterInfo->m_pNext;
  115. pFilterInfo->m_pNext->m_pPrev = pFilterInfo->m_pPrev;
  116. pFilterInfo->m_pNext = pFilterInfo->m_pPrev = NULL;
  117. return TRUE;
  118. }