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.

135 lines
4.3 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. str.cpp
  5. Abstract:
  6. Author:
  7. Vlad Sadovsky (vlads) 26-Jan-1997
  8. Revision History:
  9. 26-Jan-1997 VladS added to Sti
  10. --*/
  11. #include "cplusinc.h"
  12. #include "sticomm.h"
  13. /* FlushInputQueue is a private routine to collect and dispatch all
  14. * messages in the input queue. It returns TRUE if a WM_QUIT message
  15. * was detected in the queue, FALSE otherwise.
  16. */
  17. BOOL FlushInputQueue(volatile DWORD *pidOtherThread)
  18. {
  19. MSG msgTemp;
  20. while (PeekMessage(&msgTemp, NULL, 0, 0, PM_REMOVE)) {
  21. DispatchMessage(&msgTemp);
  22. // If we see a WM_QUIT in the queue, we need to do the same
  23. // sort of thing that a modal dialog does: break out of our
  24. // waiting, and repost the WM_QUIT to the queue so that the
  25. // next message loop up in the app will also see it. We also
  26. // post the message to the server thread's queue so that any
  27. // dialog stack displayed there will be destroyed as well.
  28. if (msgTemp.message == WM_QUIT) {
  29. if (pidOtherThread != NULL && *pidOtherThread != NULL) {
  30. PostThreadMessage(*pidOtherThread, msgTemp.message, msgTemp.wParam, msgTemp.lParam);
  31. }
  32. PostQuitMessage((int)msgTemp.wParam);
  33. return TRUE;
  34. }
  35. }
  36. return FALSE;
  37. }
  38. /* WaitAndYield() waits for the specified object using
  39. * MsgWaitForMultipleObjects. If messages are received,
  40. * they are dispatched and waiting continues. The return
  41. * value is the same as from MsgWaitForMultipleObjects.
  42. */
  43. DWORD WaitAndYield(HANDLE hObject, DWORD dwTimeout, volatile DWORD *pidOtherThread /* = NULL */)
  44. {
  45. DWORD dwTickCount, dwWakeReason, dwTemp;
  46. do {
  47. /* Flush any messages before we wait. This is because
  48. * MsgWaitForMultipleObjects will only return when NEW
  49. * messages are put in the queue.
  50. */
  51. if (FlushInputQueue(pidOtherThread)) {
  52. dwWakeReason = WAIT_TIMEOUT;
  53. break;
  54. }
  55. // in case we handle messages, we want close to a true timeout
  56. if ((dwTimeout != 0) &&
  57. (dwTimeout != (DWORD)-1)) {
  58. // if we can timeout, store the current tick count
  59. // every time through
  60. dwTickCount = GetTickCount();
  61. }
  62. dwWakeReason = MsgWaitForMultipleObjects(1,
  63. &hObject,
  64. FALSE,
  65. dwTimeout,
  66. QS_ALLINPUT);
  67. // if we got a message, dispatch it, then try again
  68. if (dwWakeReason == 1) {
  69. // if we can timeout, see if we did before processing the message
  70. // that way, if we haven't timed out yet, we'll get at least one
  71. // more shot at the event
  72. if ((dwTimeout != 0) &&
  73. (dwTimeout != (DWORD)-1)) {
  74. if ((dwTemp = (GetTickCount()-dwTickCount)) >= dwTimeout) {
  75. // if we timed out, make us drop through
  76. dwWakeReason = WAIT_TIMEOUT;
  77. } else {
  78. // subtract elapsed time from timeout and continue
  79. // (we don't count time spent dispatching message)
  80. dwTimeout -= dwTemp;
  81. }
  82. }
  83. if (FlushInputQueue(pidOtherThread)) {
  84. dwWakeReason = WAIT_TIMEOUT;
  85. break;
  86. }
  87. }
  88. } while (dwWakeReason == 1);
  89. return dwWakeReason;
  90. }
  91. /* WaitAndProcessSends is similar to WaitAndYield, but it only processes
  92. * SendMessage messages, not input messages.
  93. */
  94. DWORD WaitAndProcessSends(HANDLE hObject, DWORD dwTimeout)
  95. {
  96. DWORD dwWakeReason;
  97. do {
  98. dwWakeReason = MsgWaitForMultipleObjects(1,
  99. &hObject,
  100. FALSE,
  101. dwTimeout,
  102. QS_SENDMESSAGE);
  103. // if we got a message, yield, then try again
  104. if (dwWakeReason == 1) {
  105. MSG msgTemp;
  106. PeekMessage(&msgTemp, NULL, 0, 0, PM_NOREMOVE | PM_NOYIELD);
  107. }
  108. } while (dwWakeReason == 1);
  109. return dwWakeReason;
  110. }