jeudi 18 mai 2023

C++ callback timer with start/stop functions

I need to create a class to replicate the functionality of a callback timer from a library I no longer have access to.

Basically, spawn an asynchronous thread that executes some function after a timeout is reached. However, if some condition is met before the timeout, the function is not executed, and the timer is cancelled.

I am not sure how to "stop" the timer based on some condition.

This is what I have so far (based on the answer to this post C++ Non-blocking async timer by wally)

#include <iostream>
#include <chrono>
#include <thread>
#include <functional>
#include <mutex>
#include <condition_variable>

class Timer 
{
public:

   Timer(size_t time, const std::function<void(void)>& callback) : 
      time(std::chrono::milliseconds(time)),
      callback(callback) {}

   ~Timer() 
   { 
      if (started) 
      { 
         wait_thread.join(); 
         started = false; 
      } 
   }

   // TODO: Implement stop()
   void stop()
   {
      // ???
   }

   // TODO: Implement start()
   void start()
   {
      if (!started)
      {
         started = true;
         wait_thread = std::thread{ [this]() { wait_then_call(); } };
      }
      else
      {
         std::cout << "Thread " << wait_thread.get_id() << " already been started! " << std::endl;
      }
   }

private:

   void wait_then_call()
   {
      std::unique_lock<std::mutex> lck(mtx);
      for (int i = 10; i > 0; --i)
      {
         std::cout << "Thread " << wait_thread.get_id() << " countdown at: " << '\t' << i << std::endl;
         cv.wait_for(lck, time / 10);
      }
      callback();
   }

   std::mutex mtx;
   std::condition_variable cv{};
   std::chrono::milliseconds time;
   std::function <void(void)> callback;
   std::thread wait_thread;
   bool started = false;

};

Testing:

int main()
{
   auto f = []() {std::cout << "Executing Callback Function"; };

   Timer t1{ 3000, f };
   t1.start();

   Timer t2{ 10000, f };
   t2.start();

   // main thread is free to continue doing other things
}

Aucun commentaire:

Enregistrer un commentaire