Creating a Pure C++11 Generic Timer Class

One thing I noticed while searching for a simple, generic and pure C++ Timer class online, was the huge amount of answers that were floating around and none of them fit the exact description I was looking for. As a Qt Framework user I wanted to have something as close to QTimer as possible, or maybe even something like Timer class in .NET Framework and C# language. Well, I ended up writing one myself using what I could gather and this post is the summary of it all.



Following code snippet is the contents of timer.hpp file. Obviously, it can still be improved by adding a number of different constructors for convenience and even query methods, but the idea is to to have an interval in milliseconds, a task that is run at every interval and finally a simple flag to decide whether it should repeat or not.

#ifndef TIMER_H
#define TIMER_H

#include <chrono>
#include <functional>
#include <atomic>
#include <thread>
#include <condition_variable>

class Timer
{

public:
    Timer(const std::chrono::milliseconds &interval,
          const std::function<void ()> &task,
          bool singleShot);
    ~Timer();

    void Start();
    void Stop();
    void SetSingleShot(bool enabled = true);
    bool IsRunning() const;

private:
    std::chrono::milliseconds mInterval;
    std::function<void ()> mTask;
    std::atomic_bool mSingleShot;
    std::atomic_bool mRunning;
    std::condition_variable mRunCondition;
    std::mutex mRunCondMutex;
    std::thread mThread;
    std::mutex mStopMutex;

};

#endif // TIMER_H


And the following is the contents of timer.cpp file. Notice how a std::condition_variable is used for a flexible wait, rather than just sleeping the thread unconditionally. Checking if the thread can be joined is another important thing to note. The rest should be self-explanatory but if you still have any questions you can use the comments section down below.

#include "timer.hpp"

Timer::Timer(const std::chrono::milliseconds &interval,
             const std::function<void ()> &task,
             bool singleShot)
    : mInterval(interval),
      mTask(task),
      mSingleShot(singleShot),
      mRunning(false)
{
}

Timer::~Timer()
{
    Stop();
}

bool Timer::IsRunning() const
{
    return mRunning;
}

void Timer::Start()
{
    Stop();

    mRunning = true;
    mThread = std::thread([this]
    {
        while (mRunning)
        {
            std::unique_lock<std::mutex> lock(mRunCondMutex);
            auto waitResult = mRunCondition.wait_for(lock, mInterval, [this]{ return !mRunning; });
            if (mRunning && !waitResult)
                mTask();

            if(mSingleShot)
                mRunning = false;
        }
    });
}

void Timer::SetSingleShot(bool enabled)
{
    mSingleShot = enabled;
}

void Timer::Stop()
{
    std::unique_lock<std::mutex> lock(mStopMutex);
    mRunning = false;
    mRunCondition.notify_all();
    if(mThread.joinable())
        mThread.join();
}


Finally, here is an example code that demonstrates how this class is actually used, which is quite similar to how QTimer class and other similar generic Timer classes are used:

auto task = []()
{
   // Do something
};
mTimer = std::make_shared<Timer>(std::chrono::seconds(1), task, true);
mTimer->Start();


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.