manabreak
manabreak

Reputation: 5597

C++11 Threads: sleep for a remaining time

I'm trying to implement an update thread for my small game with C++11 threads. I've got the update cycle going on "as fast as possible", but I'd like to limit it to say, 60 times per second. How do I get the remaining time left?

Core::Core()
{
    std::thread updateThread(update); // Start update thread
}

void Core::update()
{
    // TODO Get start time
    // Here happens the actual update stuff
    // TODO Get end time
    // double duration = ...; // Get the duration

    // Sleep if necessary
    if(duration < 1.0 / 60.0)
    {
        _sleep(1.0 / 60.0 - duration);
    }
}

Upvotes: 4

Views: 7389

Answers (4)

Howard Hinnant
Howard Hinnant

Reputation: 219395

Here is Pete's correct answer (which I up-voted) but with some code thrown in to show how much easier it is done than the other answers:

// desired frame rate
typedef std::chrono::duration<int, std::ratio<1, 60>> frame_duration;

void Core::update()
{
    // Get start time
    auto start_time = std::chrono::steady_clock::now();
    // Get end time
    auto end_time = start_time + frame_duration(1);
    // Here happens the actual update stuff

    // Sleep if necessary
    std::this_thread::sleep_until(end_time);
}

Any time you're using <chrono>, and you see you're manually converting units, you're opening yourself up to bugs, either immediately, or in future maintenance. Let <chrono> do the conversions for you.

Upvotes: 14

melak47
melak47

Reputation: 4850

Have a look at the functions and clocks provided in the chrono header.

For example:

using double_milliseconds = std::chrono::duration<double, std::chrono::milliseconds::period>;

auto t0 = std::chrono::high_resolution_clock::now();
/* do work here */
auto t1 = std::chrono::high_resolution_clock::now();

auto elapsed = std::chrono::duration_cast<double_milliseconds>(t1 - t0).count();

Upvotes: 4

Pete Becker
Pete Becker

Reputation: 76498

If you're using C++11 threads, you're not limited to whatever that _sleep function does. C++11 threads have sleep_for, which takes a duration (i.e., sleep for 10 seconds), and sleep_until, which takes a time point (i.e., sleep until next Thursday). For a thread that has to wake up at fixed intervals, sleep_until is the way to go. Just sleep until the next wakeup time.

Upvotes: 5

Raxvan
Raxvan

Reputation: 6515

The easiest way to limit the framerate is to keep track of how long it takes your entire update function. After that you need to sleep the remaining time:

In this example i used timeGetTime to measure time but you can use any other function that has high precision

void Core::Update()
{
    unsigned int start_time = timeGetTime();
    ActualUpdate();
    unsigned int end_time = timeGetTime();
    unsigned int frame_time = end_time - start_time;

    const unsigned int miliseconds_per_frame = 1000 / 60;
    if(frame_time < miliseconds_per_frame)
    {
        Sleep(miliseconds_per_frame - frame_time);
    }
}

Upvotes: 1

Related Questions