开发者

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

开发者 https://www.devze.com 2022-12-17 07:40 出处:网络
Windows API/C/C++ 1. .... 2. .... 3. .... 4.while (flag1 != flag2) 5.{ 6.SleepEx(100,FALSE); //waiting for flags to be equal (flags are开发者_如何学C set from another thread).

Windows API/C/C++

1. ....  
2. ....
3. ....    
4.    while (flag1 != flag2)
5.    {
6.      SleepEx(100,FALSE);   
        //waiting for flags to be equal (flags are开发者_如何学C 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.


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.


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);
    }

 }


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.


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.


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


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


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

0

精彩评论

暂无评论...
验证码 换一张
取 消