7

I am relatively new to C++, so I don't have a huge amount of experience. I have learned Python, and I am trying to make an improved version of a Python code I wrote in C++. However, I want it to work in real time, so I need to set the speed of a While loop. I'm sure there is an answer, but I couldn't find it. I want a comparable code to this:

rate(timeModifier * (1/dt))

This was the code I used in Python. I can set a variable dt to make calculations more precise, and timeModifier to double or triple the speed (1 sets it to realtime). This means that the program will go through the loop 1/dt times per second. I understand I can include time.h at the header, but I guess I am too new to C++ to understand how to transfer this to my needs.

Asaaj
  • 272
  • 2
  • 3
  • 9
  • 1
    Use a sleep function to wait until you are ready for the next iteration – David Heffernan May 18 '12 at 13:37
  • 4
    Careful: depending on what you are doing (physics simulation, game loop) calling `sleep` is moderately horrible advice. Rather, you want [either framerate-dependent calculations or fixed time steps with which get called in variable intervals](http://gamedev.stackexchange.com/q/1589/4661). – Konrad Rudolph May 18 '12 at 14:04
  • 1
    While the meaning of the term "realtime" is more than a little nebulous, it probably doesn't mean what you think it means. – John Dibling May 18 '12 at 14:51

6 Answers6

7

You could write your own timer class:

#include <ctime>

class Timer {
    private:
        unsigned long startTime;
    public:
        void start() {
            startTime = clock();
        }

        unsigned long elapsedTime() {
            return ((unsigned long) clock() - startTime) / CLOCKS_PER_SEC;
        }

        bool isTimeout(unsigned long seconds) {
            return seconds >= elapsedTime();
        }
};


int main() 
{
    unsigned long dt = 10; //in seconds
    Timer t;
    t.start();

    while(true) 
    {
        if(t.elapsedTime() < dt) 
        {
            //do something to pass time as a busy-wait or sleep
        }
        else 
        {
            //do something else
                    t = Timer(); //reset the timer
        }
    }
}

Note that busy-waits are discouraged, since they will hog the CPU. If you don't need to do anything, use the sleep command(Windows) or usleep ( Linux). For more information on making timers in C++, see this link.

slybloty
  • 6,346
  • 6
  • 49
  • 70
4

You can't do it the same manner in C++. You need to manually call some kind of sleep function in calculation loop, Sleep on Windows or usleep on *NIX.

inkooboo
  • 2,904
  • 1
  • 19
  • 24
  • Yep that's all I needed. Sleep() works in the opposite way from the Python version, but it works for my needs. – Asaaj Jun 15 '12 at 05:42
  • I don't recommend using `Sleep()` functions since It'd block the whole application from running and gives inaccurate time, However, it's absolutely inappropriate for real-time things. – Beyondo Jan 29 '18 at 13:31
3

It's been a while since I've done something like this, but something like this will work:

#include <time.h>

time_t t2, t1 = time(NULL);

while(CONDITIONS)
{
    time_t t2 = time(NULL);
    if(difftime(t2, t1) > timeModifier)
    {
        //DO the stuff!
        t1 = time(NULL);
    }
}

I should note, however, that I'm not familiar with the precision of this method, I think it measures the difference in seconds.

If you need something more precise, use the clock() function which has the number of milliseconds since 12:00 AM beginning January 1, 1980, to the nearest 10 milliseconds. Perhaps something like this:

#include <time.h>

clock_t t2, t1 = clock();

while(CONDITIONS)
{
    t2 = clock();
    if((t2-t1) > someTimeElapsed*timeModifier)
    {
        //DO the stuff!
        t1 = clock());
    }
}

Update: You can even yield the CPU to other threads and processes by adding this after the end of the if statement:

else
{
    usleep(10000); //sleep for ten milliseconds (chosen because of precision on clock())
}
Bob2Chiv
  • 1,858
  • 2
  • 19
  • 29
  • you appear to read from t1 before assigning, and there should be an else containing a sleep before you get a +1 – Mooing Duck May 18 '12 at 14:14
  • @MooingDuck I added a note, but for me it depends on what the program is doing whether or not I would want it to sleep. – Bob2Chiv May 18 '12 at 14:35
0

Depending on the accuracy you need, and your platform, you could use usleep This allows you to set the pause time down to microseconds:

 #include <unistd.h>

 int usleep(useconds_t useconds);

Remember that your loop will always take longer than this because of the inherent processingtime of the rest of the loop but it's a start. For anything more accurate,you'd probably need to look at timer based callbacks.

Component 10
  • 10,247
  • 7
  • 47
  • 64
0

You should really create a new thread and have it do the timing so that it remains unaffected by the processing work done in the loop.

WARNING: Pseudo code... just to give you an idea of how to start.

Thread* tThread = CreateTimerThread(1000);
tThread->run();
while( conditionNotMet() )
{
    tThread->waitForTimer();
    doWork();
}

CreateTimerThread() should return the thread object you want, and run would be something like:

run()
{
    while( false == shutdownLatch() )
    {
        Sleep( timeout );
        pulseTimerEvent();
    }
}

waitForTimer()
{
    WaitForSingleObject( m_handle );
    return;
}
Dennis
  • 3,683
  • 1
  • 21
  • 43
  • Maybe, but it would remove the "worry" of keeping pegged times and calculating sleep loops. Nice into to multi-threading. Not that hard these days with the apache decaf, boost and Intel TBB libraries. Besides look at how clean the code becomes... :) – Dennis May 18 '12 at 15:14
0

Under Windows you can use QueryPerformanceCounter, while polling the time (e.g. within another while loop) call Sleep(0) to allow other threads to continue operation.

Remember Sleep is highly inaccurate. For full control just run a loop without operations, however you'll use 100% of the CPU. To relax the strain on the CPU you can call Sleep(10) etc.

demorge
  • 1,097
  • 1
  • 7
  • 17