T.T.T.
T.T.T.

Reputation: 34513

What is the cleanest way to create a timeout for a while loop?

Windows API/C/C++

1. ....  
2. ....
3. ....    
4.    while (flag1 != flag2)
5.    {
6.      SleepEx(100,FALSE);   
        //waiting for flags to be equal (flags are set from another thread).
7.    }
8. .....
9. .....  

If the flags don't equal each other after 7 seconds, I would like to continue to line 8.

Any help is appreciated. Thanks.

Upvotes: 8

Views: 28283

Answers (7)

Byron Whitlock
Byron Whitlock

Reputation: 53850

Make sure you do a sleep() or yield() in there or you will eat up all the entire CPU (or core) waiting.

Upvotes: 2

Arlen Beiler
Arlen Beiler

Reputation: 15866

I would say "check the time and if nothing has happened in seven seconds later, then break the loop.

Upvotes: 0

struppi
struppi

Reputation: 595

If your application does some networking stuff, have a look at the POSIX select() call, especially the timeout functionality!

Upvotes: 1

Kornel Kisielewicz
Kornel Kisielewicz

Reputation: 57525

You can use QueryPerformanceCounter from WinAPI. Check it before while starts, and query if the amount of time has passed. However, this is a high resolution timer. For a lower resolution use GetTickCount (milliseconds).

All depends whether you are actively waiting (doing something) or passively waiting for an external process. If the latter, then the following code using Sleep will be a lot easier:

int count = 0;
while ( flag1 != flag2 && count < 700 )
{
   Sleep( 10 ); // wait 10ms
   ++count;
}

If you don't use Sleep (or Yield) and your app is constantly checking on a condition, then you'll bloat the CPU the app is running on.

If you use WinAPI extensively, you should try out a more native solution, read about WinAPI's Synchronization Functions.

Upvotes: 4

Pete Kirkham
Pete Kirkham

Reputation: 49311

You failed to mention what will happen if the flags are equal.

Also, if you just test them with no memory barriers then you cannot guarantee to see any writes made by the other thread.

Your best bet is to use an Event, and use the WaitForSingleObject function with a 7000 millisecond time out.

Upvotes: 3

Michael
Michael

Reputation: 55395

Do not poll for the flags to change. Even with a sleep or yield during the loop, this just wastes CPU cycles.

Instead, get the thread which sets the flags to signal you that they've been changed, probably using an event. Your wait on the event takes a timeout, which you can tweak to allow waiting of 7 seconds total.

For example:

Thread1:

 flag1 = foo;
 SetEvent(hEvent);


 Thread2:

 DWORD timeOutTotal = 7000;  // 7 second timeout to start.
 while (flag1 != flag2 && timeOutTotal > 0)
 {
     // Wait for flags to change
     DWORD start = GetTickCount();

     WaitForSingleObject(hEvent, timeOutTotal);

     DWORD end = GetTickCount();

    // Don't let timeOutTotal accidently dip below 0.
    if ((end - start) > timeOutTotal)
    {
        timeOutTotal = 0;
    }
    else
    {
       timeOutTotal -= (end - start);
    }

 }

Upvotes: 6

JaredPar
JaredPar

Reputation: 754505

If you are waiting for a particular flag to be set or a time to be reached, a much cleaner solution may be to use an auto / manual reset event. These are designed for signalling conditions between threads and have very rich APIs designed on top of them. For instance you could use the WaitForMultipleObjects API which takes an explicit timeout value.

Upvotes: 9

Related Questions