views:

231

answers:

7

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.

+1  A: 

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.

Kornel Kisielewicz
You are forgetting to increment count inside the loop XD
Wallacoloo
@wallacoloo, thanks, it's late here ;>
Kornel Kisielewicz
Note that your solution is not that precise. Specifying a Sleep of 10ms means that the sleep may be about 10ms. It depends on the underlying timer resolution. Also, if there are other busy higher priority threads active, you may have to wait even longer, so you can't rely on a sleep of 10ms actually being 10ms.
zdan
@zdan - I doubt that the OP wanted a precise solution. He can use QPC with if he really want's to be precise -- and without at least Sleep(1) he'll be eating up resources.
Kornel Kisielewicz
+1  A: 

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

Byron Whitlock
+10  A: 

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.

JaredPar
+1 Yes. Much cleaner.
Byron Whitlock
+5  A: 

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

 }
Michael
+3  A: 

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.

Pete Kirkham
A: 

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

struppi
+1  A: 

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

Arlen Beiler