Home > Software design >  Incorrect Interval Timer for a CallBack function in C
Incorrect Interval Timer for a CallBack function in C

Time:12-19

I find on the web this class to implement a callback function that asynchronously do some work while I'm on the Main thread. This is the class:

#include "callbacktimer.h"

    CallBackTimer::CallBackTimer()
    :_execute(false)
    {}

    CallBackTimer::~CallBackTimer() {
        if( _execute.load(std::memory_order_acquire) ) {
            stop();
        };
    }

    void CallBackTimer::stop()
    {
        _execute.store(false, std::memory_order_release);
        if( _thd.joinable() )
            _thd.join();
    }

    void CallBackTimer::start(int interval, std::function<void(void)> func)
    {
        if( _execute.load(std::memory_order_acquire) ) {
            stop();
        };
        _execute.store(true, std::memory_order_release);
        _thd = std::thread([this, interval, func]()
        {
            while (_execute.load(std::memory_order_acquire)) {
                func();
                std::this_thread::sleep_for(
                    std::chrono::milliseconds(interval)
                );
            }
        });
    }

    bool CallBackTimer::is_running() const noexcept {
        return ( _execute.load(std::memory_order_acquire) &&
                 _thd.joinable() );
    }

The problem here is that if I put a job to be done every millisecond I don't know why but it is repeated every 64 milliseconds and not every 1 millisecond, this snippet get an idea:

#include "callbacktimer.h"

int main()
{
    CallBackTimer cBT;

    int i = 0;
    cBT.start(1, [&]()-> void {

        i  ;

    });


    while(true)
    {
            std::cout << i << std::endl;
            Sleep(1000);
    }

    return 0;
}

Here I should see on the Standard Output: 1000, 2000, 3000, and so on. But it doesn't...

CodePudding user response:

It's quite hard to do something on a PC in a 1ms interval. Thread scheduling happens at 1/64s, which is ~16ms.

When you try to sleep for 1 ms, it will likely sleep for 1/64s instead, given that no other thread is scheduled to run. As your main thread sleeps for one second, your callback timer may run up to 64 times during that interval.

See also How often per second does Windows do a thread switch?

You can try multimedia timers which may go down to 1 millisecond.

I'm trying to implement a chronometer in qt which should show also the microsecondo

Well, you can show microseconds, I guess. But your function won't run every microsecond.

  • Related