tags:

views:

267

answers:

5

I have a while loop that runs in a do while loop. I need the while loop to run exactly every second no faster no slower. but i'm not sure how i would do that. this is the loop, off in its own function. I have heard of the sleep() function but I also have heard that it is not very accurate.

int min5()
{
    int second = 00;
    int minute = 0;
    const int ZERO = 00;

    do{
        while (second <= 59){
        if(minute == 5) break;
        second += 1;
        if(second == 60) minute += 1;
        if(second == 60) second = ZERO;
        if(second < 60) cout << "Current Time> "<< minute <<" : "<< second <<" \n";
        }
      } while (minute <= 5);
}
A: 
Sleep(1000);

http://msdn.microsoft.com/en-us/library/ms686298(VS.85).aspx

Andrey
If *dwMilliseconds* is less than the resolution of the system clock, the thread may sleep for less than the specified length of time.
Kevin Panko
How do you know that the OP is using Windows as a platform? BTW, other platforms have `Sleep` methods. The link may not help if the OP is using Linux or Mac or an embedded system.
Thomas Matthews
@Thomas Matthews i know that it is for windows and i was not sure that OP is using it. i decided to make a guess :)
Andrey
@Kevin if his system clock is slower than 1 Hz, I think he has bigger problems
Tyler McHenry
@Kevin Panko - On windows at least sleep tries not to sleep for less than the time you specify - it typically sleeps for longer.
Stewart
@Stewart agree, on Win you sleep longer, never shorter
Andrey
"If *dwMilliseconds* is greater than one tick but less than two, the wait can be anywhere between one and two ticks, and so on."
Kevin Panko
+4  A: 

The best accuracy you can achieve is by using Operating System (OS) functions. You need to find the API that also has a callback function. The callback function is a function you write that the OS will call when the timer has expired.

Be aware that the OS may lose timing precision due to other tasks and activities that are running while your program is executing.

Thomas Matthews
+1  A: 

In Windows for example, there is a possibility to create a waitable timer object.

If that's Your operating system check the documentation here for example Waitable Timer Objects.

From the code You presented it looks like what You are trying to do can be done much easier with sleep. It doesn't make sense to guarantee that Your loop body is executed exactly every 1 second. Instead make it execute 10 times a second and check if the time that elapsed form the last time, You took some action, is more than a second or not. If not, do nothing. If yes, take action (print Your message, increment variables etc), store the time of last action and loop again.

Maciej Hehl
+1  A: 

As someone else posted, your OS may provide some kind of alarm or timer functionality. You should try to use this kind of thing rather than coding your own polling loop. Polling the time means you need to be context switched in every second, which keeps your code running when the system could be doing other stuff. In this case you interrupt someone else 300 times just to say "are we done yet".

Also, you should never make assumptions about the duration of a sleep - even if you had a real time OS this would be unsafe - you should always ask the real time clock or tick counter how much time has elapsed each time because otherwise any errors accumulate so you will get less and less accurate over time. This is true even on a real time system because even if a real time system could sleep accurately for 1 second, it takes some time for your code to run so this timing error would accumulate on each pass through the loop.

Stewart
+3  A: 

If you want a portable solution, you shouldn't expect high-precision timing. Usually, you only get that with a platform-dependent solution.

A portable (albeit not very CPU-efficient, nor particularly elegant) solution might make use of a function similar to this:

#include <ctime>

void wait_until_next_second()
{
    time_t before = time(0);
    while (difftime(time(0), before) < 1);
}

You'd then use this in your function like this:

int min5()
{
    wait_until_next_second();  // synchronization (optional), so that the first
                               // subsequent call will not take less than 1 sec.
    ...
    do
    {
        wait_until_next_second();  // waits approx. one second
        while (...)
        {
            ...
        }
    } while (...)
}

Some further comments on your code:

  • Your code gets into an endless loop once minute reaches the value 5.

  • Are you aware that 00 denotes an octal (radix 8) number (due to the leading zero)? It doesn't matter in this case, but be careful with numbers such as 017. This is decimal 15, not 17!

  • You could incorporate the seconds++ right into the while loop's condition: while (seconds++ <= 59) ...

  • I think in this case, it would be better to insert endl into the cout stream, since that will flush it, while inserting "\n" won't flush the stream. It doesn't truly matter here, but your intent seems to be to always see the current time on cout; if you don't flush the stream, you're not actually guaranteed to see the time message immediately.

stakx
oh, i didn't know. up to this point i'm self taught, thats why my code looks ugly XD so until i get into college i've been learning mostly from mistakes such as this, so again thank you for helping (^_^)
itachisxeyes
@itachisxeyes: I didn't mean that your code is ugly. I saw that you tagged your question with `beginner`, so I thought I'd give you additional hints at some things you _could_ do with your code. I hope that didn't give you any offense; that certainly was not my intention.
stakx
@stakx: oh i did not take any offense, i'm just assuming that most everything i write is ugly and could probably be done better and more efficiently.and am thankful you when the extra mile with additional help.
itachisxeyes