3
\$\begingroup\$

This is code which must run on XP, so no GetTickCount64, and which should correctly handle the value wrapping around after 49 days. Can it be improved?

// DWORD timeoutMs is a given parameter.
DWORD beginMs = (timeoutMs == INFINITE ? 0 : ::GetTickCount());
DWORD endMs = beginMs + timeoutMs; // unsigned arithmethic is Mod(MAX+1)
DWORD currentMs;
// Create Process, omitted for brevity
while ((waitResult = ::WaitForSingleObject(pi.hProcess, DEFAULT_WAIT_MS)) == WAIT_TIMEOUT)
{
 if (timeoutMs != INFINITE)
 {
 bool timeoutReached = false;
 currentMs = ::GetTickCount();
 if (beginMs <= endMs) // normal case
 {
 if (currentMs > endMs)
 {
 timeoutReached = true;
 }
 }
 else // special case: tick count wrapped around after 49 days uptime
 {
 if (currentMs < beginMs && currentMs > endMs)
 {
 timeoutReached = true;
 }
 }
 if (timeoutReached)
 {
 ::TerminateProcess(pi.hProcess, 0);
 break;
 }
 }
}
asked May 20, 2016 at 17:52
\$\endgroup\$
4
  • 1
    \$\begingroup\$ Why not just have waitResult = ::WaitForSingleObject(pi.hProcess, timeoutMs);? Why use ::GetTickCount() at all? \$\endgroup\$ Commented May 20, 2016 at 22:34
  • \$\begingroup\$ What about the QueryPerformanceCounter functions? Are they also unavailable on XP? \$\endgroup\$ Commented May 21, 2016 at 3:43
  • \$\begingroup\$ @ncalmbeblpaicr0011 to be able to call a callback function in the loop and do other things like copy the standard output stream while the program is running. \$\endgroup\$ Commented May 23, 2016 at 19:45
  • \$\begingroup\$ @glampert They are available, that would be another option. \$\endgroup\$ Commented May 30, 2016 at 23:05

1 Answer 1

1
\$\begingroup\$

Unsigned subtraction (and automatic mod 2^32) will always give currentMs - beginMs == elapsedMs, even when beginMs > currentMs, and as long as the actual elapsed time doesn't overflow the tick count (it isn't greater than 49 days).

So you could replace the original with the following code:

DWORD beginMs = GetTickCount();
// Create Process, omitted for brevity
while ((waitResult = WaitForSingleObject(pi.hProcess, DEFAULT_WAIT_MS)) == WAIT_TIMEOUT) {
 if (timeoutMs != INFINITE) {
 DWORD currentMs = GetTickCount();
 bool timeoutReached = currentMs - beginMs > timeoutMs;
 if (timeoutReached) {
 TerminateProcess(pi.hProcess, 0);
 break;
 }
 }
}

And you could even go a step further and eliminate the variables currentMs and timeoutReached: if (GetTickCount() - beginMs > timeoutMs) {...

answered May 30, 2016 at 11:02
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.