C++定時器CTimer的實現
有過使用Objective-C、Java等語言開發專案的同學會發現,網路或社群有存在眾多的開源庫或元件。個人在使用C++11進行專案開發時,想找一些比較完善、系統化的基本功能庫卻很少,比如定時器。
這裡,主要利用thread、mutex、condition_variable_any、function來實現定時器,可現實同步、非同步、單次、循序執行任務。程式碼中附帶了簡單的註釋,若有疑問或建議歡迎留言。
CTimer.hpp
//
// CTimer.hpp
//
// Created by lzj<lizhijian_21@163.com> on 2018/7/20.
// Copyright © 2018年 ZJ. All rights reserved.
//
#ifndef CTimer_hpp
#define CTimer_hpp
#include <stdio.h>
#include <functional>
#include <chrono>
#include <thread>
#include <atomic>
#include <mutex>
#include <string>
#include <condition_variable>
class CTimer
{
public:
CTimer(const std::string sTimerName = ""); //構造定時器,附帶名稱
~CTimer();
/**
開始執行定時器
@param msTime 延遲執行(單位ms)
@param task 任務函式介面
@param bLoop 是否迴圈(預設執行1次)
@param async 是否非同步(預設非同步)
@return true:已準備執行,否則失敗
*/
bool Start(unsigned int msTime, std::function<void()> task, bool bLoop = false, bool async = true);
/**
取消定時器,同步定時器無法取消(若任務程式碼已執行則取消無效)
*/
void Cancel();
/**
同步執行一次
#這個介面感覺作用不大,暫時現實在這裡
@param msTime 延遲時間(ms)
@param fun 函式介面或lambda程式碼塊
@param args 引數
@return true:已準備執行,否則失敗
*/
template<typename callable, typename... arguments>
bool SyncOnce(int msTime, callable&& fun, arguments&&... args) {
std::function<typename std::result_of<callable(arguments...)>::type()> task(std::bind(std::forward<callable>(fun), std::forward<arguments>(args)...)); //繫結任務函式或lambda成function
return Start(msTime, task, false, false);
}
/**
非同步執行一次任務
@param msTime 延遲及間隔時間
@param fun 函式介面或lambda程式碼塊
@param args 引數
@return true:已準備執行,否則失敗
*/
template<typename callable, typename... arguments>
bool AsyncOnce(int msTime, callable&& fun, arguments&&... args) {
std::function<typename std::result_of<callable(arguments...)>::type()> task(std::bind(std::forward<callable>(fun), std::forward<arguments>(args)...));
return Start(msTime, task, false);
}
/**
非同步執行一次任務(預設延遲1毫秒後執行)
@param fun 函式介面或lambda程式碼塊
@param args 引數
@return true:已準備執行,否則失敗
*/
template<typename callable, typename... arguments>
bool AsyncOnce(callable&& fun, arguments&&... args) {
std::function<typename std::result_of<callable(arguments...)>::type()> task(std::bind(std::forward<callable>(fun), std::forward<arguments>(args)...));
return Start(1, task, false);
}
/**
非同步迴圈執行任務
@param msTime 延遲及間隔時間
@param fun 函式介面或lambda程式碼塊
@param args 引數
@return true:已準備執行,否則失敗
*/
template<typename callable, typename... arguments>
bool AsyncLoop(int msTime, callable&& fun, arguments&&... args) {
std::function<typename std::result_of<callable(arguments...)>::type()> task(std::bind(std::forward<callable>(fun), std::forward<arguments>(args)...));
return Start(msTime, task, true);
}
private:
void DeleteThread(); //刪除任務執行緒
public:
int m_nCount = 0; //迴圈次數
private:
std::string m_sName; //定時器名稱
std::atomic_bool m_bExpired; //裝載的任務是否已經過期
std::atomic_bool m_bTryExpired; //裝備讓已裝載的任務過期(標記)
std::atomic_bool m_bLoop; //是否迴圈
std::thread *m_Thread = nullptr;
std::mutex m_ThreadLock;
std::condition_variable_any m_ThreadCon;
};
#endif /* CTimer_hpp */
CTimer.cpp
//
// CTimer.cpp
//
// Created by lzj<lizhijian_21@163.com> on 2018/7/20.
// Copyright © 2018年 ZJ. All rights reserved.
//
#include "CTimer.hpp"
#include <future>
#include "CPrintfLog.h"
CTimer::CTimer(const std::string sTimerName):m_bExpired(true), m_bTryExpired(false), m_bLoop(false)
{
m_sName = sTimerName;
}
CTimer::~CTimer()
{
m_bTryExpired = true; //嘗試使任務過期
DeleteThread();
}
bool CTimer::Start(unsigned int msTime, std::function<void()> task, bool bLoop, bool async)
{
if (!m_bExpired || m_bTryExpired) return false; //任務未過期(即內部仍在存在或正在執行任務)
m_bExpired = false;
m_bLoop = bLoop;
m_nCount = 0;
if (async) {
DeleteThread();
m_Thread = new std::thread([this, msTime, task]() {
if (!m_sName.empty()) {
#if (defined(__ANDROID__) || defined(ANDROID)) //相容Android
pthread_setname_np(pthread_self(), m_sName.c_str());
#elif defined(__APPLE__) //相容蘋果系統
pthread_setname_np(m_sName.c_str()); //設定執行緒(定時器)名稱
#endif
}
while (!m_bTryExpired) {
m_ThreadCon.wait_for(m_ThreadLock, std::chrono::milliseconds(msTime)); //休眠
if (!m_bTryExpired) {
task(); //執行任務
m_nCount ++;
if (!m_bLoop) {
break;
}
}
}
m_bExpired = true; //任務執行完成(表示已有任務已過期)
m_bTryExpired = false; //為了下次再次裝載任務
});
} else {
std::this_thread::sleep_for(std::chrono::milliseconds(msTime));
if (!m_bTryExpired) {
task();
}
m_bExpired = true;
m_bTryExpired = false;
}
return true;
}
void CTimer::Cancel()
{
if (m_bExpired || m_bTryExpired || !m_Thread) {
return;
}
m_bTryExpired = true;
}
void CTimer::DeleteThread()
{
if (m_Thread) {
m_ThreadCon.notify_all(); //休眠喚醒
m_Thread->join(); //等待執行緒退出
delete m_Thread;
m_Thread = nullptr;
}
}
用法1:
CTimer *pTimer = new CTimer("定時器1");
pTimer->AsyncOnce(10, [](void *userData) { //延遲10毫秒執行1次
JMCPCenterCtl *pCenterCtl = static_cast<JMCPCenterCtl*>(userData); //JMCPCenterCtl是當前類
if (pCenterCtl) {
CPrintf("這是一個定時器");
}
}, this);
用法2:
void JMCPCenterCtl::didHeartbeatThread(void *arg); //定時器任務函式
CTimer *pTimer = new CTimer("定時器2");
pTimer->AsyncLoop(10, didHeartbeatThread, this); //非同步迴圈執行,間隔時間10毫秒
用法3:
CTimer *pTimer = new CTimer("定時器3");
pTimer->AsyncLoop(10, [](JMCPCenterCtl *self) {
printf(“這是一個10毫秒觸發的定時器”);
}, this); //非同步迴圈執行,間隔時間10毫秒
用法4:
int a = 1;
int b = 2;
int sum = 0;
CTimer *pTimer = new CTimer("定時器4");
pTimer->AsyncLoop(1000, [](void *self, int a, int b, int *sum) {
*sum = a + b + *sum;
printf("累加 sum += a + b + *sum: %d\n", *sum);
}, this, a, b , &sum); //非同步迴圈執行,間隔時間1秒
列印:
累加 sum += a + b + *sum: 3
累加 sum += a + b + *sum: 6
累加 sum += a + b + *sum: 9
累加 sum += a + b + *sum: 12
相關文章
- 【JavaScript定時器小案例】常見的幾種定時器實現的案例JavaScript定時器
- Go定時器的三種實現方式Go定時器
- java springboot 實現定時器任務JavaSpring Boot定時器
- 【STM32F4】利用定時器實現最基本的定時功能(HAL)定時器
- Laravel 結合 Redis 實現 PHP 定時器LaravelRedisPHP定時器
- .NET中如何實現高精度定時器定時器
- Golang 定時器底層實現深度剖析Golang定時器
- js實現0ms延時定時器的幾種方式JS定時器
- netty系列之:HashedWheelTimer一種定時器的高效實現Netty定時器
- 深入 Java Timer 定時排程器實現原理Java
- Laravel + Workerman 實現多程式定時器任務Laravel定時器
- C++程式設計_簡易計時器(Timer)的控制檯實現C++程式設計
- 直播app原始碼,定時開關,實現計時器功能APP原始碼
- 如何實現定時推送?
- 定時器以及定時器的幾個案例定時器
- VUE簡單的定時器實時重新整理Vue定時器
- 深入 Java Timer 定時任務排程器實現原理Java
- SpringBoot使用Quartz定時器實現Email資訊轟炸Spring Bootquartz定時器AI
- 基於Python實現環形佇列高效定時器Python佇列定時器
- 利用定時器實現51微控制器返回上電執行時間功能定時器
- PHP定時執行任務的實現PHP
- [筆記]laravel定時任務的實現筆記Laravel
- C++實現簡易計算器C++
- Flutter倒數計時/計時器的實現Flutter
- 使用Quartz實現定時作業quartz
- Java如何實現定時任務?Java
- SpringBoot如何實現定時任務Spring Boot
- javascript實現時間器JavaScript
- LinkBlockedQueue的c++實現BloCC++
- Python實現定時任務的多種方式Python
- java設定熱鍵(C++實現dll匯入)JavaC++
- 系統梳理主流定時器演算法實現的差異以及應用定時器演算法
- 【STM32+HAL庫】使用通用定時器生成的PWM實現呼吸燈效果定時器
- Laravel5.6使用定時任務實現定時發郵件Laravel
- Laravel5.6 使用定時任務實現定時發郵件Laravel
- C++實現以秒為單位的計數器C++
- SpringBoot中併發定時任務的實現、動態定時任務的實現(看這一篇就夠了)Spring Boot
- GO的定時器Timer 和定時任務cronGo定時器