C++一个简单的定时器

0.前言

C++学习笔记。

该学习笔记练习使用了 std::function 函数对象,std::bind 函数适配器,std::priority_queue 创建最大堆,std::mutex 创建互斥锁,std::condition_variable 条件变量。

1.正文

C++实现一个简单的定时器任务,可以添加定时器。

cpp 复制代码
#include <iostream>
#include <string>
#include <chrono>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <queue>
#include <thread>
#include <functional>
#include <cstdint>


using SteadyClock = std::chrono::steady_clock;
using TimePoint = std::chrono::steady_clock::time_point;
using MillionSecond = std::chrono::milliseconds;

class TimerTask {
 public:
  using TimerFunc = std::function<void(const TimerTask & timer)>;

  enum {
    TIMER_TASK_PERIOD,
    TIMER_TASK_ONESHOT,
  };

  uint32_t id_;
  int type_;
  MillionSecond interval_;
  TimePoint trigger_point_;
  TimerFunc func_;
};

class TimerCompare {
 public:
  bool operator()(const TimerTask &a, const TimerTask &b) {
    return a.trigger_point_ > b.trigger_point_;
  }
};

class TimerTaskThread {
 public:
  int add(bool oneshot, int interval_ms, const TimerTask::TimerFunc &func) 
  {
    TimerTask timer;
    timer.type_ = oneshot ? TimerTask::TIMER_TASK_ONESHOT : TimerTask::TIMER_TASK_PERIOD;
    timer.interval_ = MillionSecond(interval_ms);
    timer.trigger_point_ = SteadyClock::now() + timer.interval_;
    timer.func_ = func;
   
    {
      std::unique_lock<std::mutex> lock;
      timer.id_ = id_pool_++;
      timer_queue_.push(timer);
      cv_notify_.notify_one();
    }

    return timer.id_ ;
  }

  int remove(int id) {
    std::unique_lock<std::mutex> lock;
    std::vector<TimerTask> temp;

    while(!timer_queue_.empty()) {
      auto timer = timer_queue_.top();
      timer_queue_.pop();

      if(timer.id_ == id) {
        continue;
      }

      temp.push_back(timer);
    }

    for(auto timer : temp) {
      timer_queue_.push(timer);
    }

    cv_notify_.notify_one();

    return 0;
  }

  TimePoint top(void) {
    if(timer_queue_.empty()) {
      return TimePoint::max();
    }

    return timer_queue_.top().trigger_point_;
  }

  TimePoint now(void) {
    return SteadyClock::now();
  }

  void start(void) {
    running_ = true;
    // std::thread([this](){
    //   run();
    // }).detach();

    std::thread(&TimerTaskThread::run, this).detach();

  }

  void process_timer(TimerTask &timer) {
    timer.func_(timer);

    if(timer.type_ == TimerTask::TIMER_TASK_PERIOD) {
      timer.trigger_point_ = SteadyClock::now() + timer.interval_;
      timer_queue_.push(timer);
    }
  }

  void run(void) {
    while(running_) {
      std::unique_lock<std::mutex> lock(mutex_);

      cv_notify_.wait_until(lock, top());
      
      while(!timer_queue_.empty() && now() >= top()) {
        if(!running_)
          break;
        
        auto timer = timer_queue_.top();
        timer_queue_.pop();
        process_timer(timer);
      }
    }
  }


 void dump()
 {
  std::cout << "timertaskthread dump" << std::endl;
 }

 private:
  using PriorityQueue = std::priority_queue<TimerTask, std::vector<TimerTask>, TimerCompare>;
  PriorityQueue timer_queue_;
  int running_;
  std::mutex mutex_;
  std::condition_variable cv_notify_;
  uint32_t id_pool_;
};


int main(int argc, char *argv[]) {
  TimerTaskThread timer_task;
  timer_task.start();

  std::cout << std::chrono::steady_clock::now().time_since_epoch().count() << std::endl;

  timer_task.add(false, 2000, [](const TimerTask & timer) {
    std::cout << std::chrono::steady_clock::now().time_since_epoch().count() << std::endl;
    std::cout << "timer task 1" << std::endl;
    });
  
  timer_task.add(false, 2000, [](const TimerTask & timer) {
    std::cout << std::chrono::steady_clock::now().time_since_epoch().count() << std::endl;
    std::cout << "timer task 1" << std::endl;
    });

  timer_task.add(false, 4000, [](const TimerTask & timer) {
    std::cout << std::chrono::steady_clock::now().time_since_epoch().count() << std::endl;
    std::cout << "timer task 2" << std::endl;
    });
  
  
  auto fun1 = std::bind(&TimerTaskThread::dump, &timer_task);
  int timer_id_1 = timer_task.add(false, 200, fun1);
  
  int count = 0;
  while(1) {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    count++;
    if(count == 2) {
      timer_task.remove(timer_id_1);
    }
  }


  return 0;
}

执行结果

相关推荐
youcans_4 小时前
【动手学STM32G4】(3)STM32G431之定时器
stm32·单片机·嵌入式硬件·定时器
一个平凡而乐于分享的小比特17 天前
时钟源与定时器:澄清概念
定时器·时钟源
特立独行的猫a18 天前
C++使用Boost的Asio库优雅实现定时器与线程池工具类
开发语言·c++·线程池·定时器·boost·asio
利刃大大22 天前
【JavaSE】十五、线程同步wait | notify && 单例模式 && 阻塞队列 && 线程池 && 定时器
java·单例模式·线程池·定时器·阻塞队列
YouEmbedded22 天前
解码信号与槽(含 QTimer 应用)
qt·定时器·信号与槽
故事不长丨1 个月前
C#定时器与延时操作的使用
开发语言·c#·.net·线程·定时器·winform
普中科技2 个月前
【普中DSP28335开发攻略】-- 第 16 章 定时器中断实验
单片机·嵌入式硬件·定时器·dsp28335·普中科技
Jie_jiejiayou2 个月前
定时器详解以及呼吸灯实现 — STM32(HAL库)
stm32·单片机·嵌入式硬件·定时器
安庆平.Я2 个月前
STM32——定时器
stm32·单片机·嵌入式硬件·定时器