首页 / C++ / C++实现时间轮定时器
C++实现时间轮定时器
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C++实现时间轮定时器,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含6875字,纯文字阅读大概需要10分钟。
内容图文
![C++实现时间轮定时器](/upload/InfoBanner/zyjiaocheng/1162/5fced388d98a442d9867073eb109caac.jpg)
根据网上介绍了解原理后自己写的一个定时器,如有不足望指正
1 //TimeWheel.h 2 #pragma once 3 #include <iostream> 4 #include <windows.h> 5 #include <array> 6 #include <list> 7 #include <atomic> 8 #include <thread> 9 #include <mutex> 10 #include <assert.h> 11 #include <functional> 12usingnamespace std; 13 14#define _SYNCHRONIZE 1 //同步 15#define _ASYNCHRONOUS_SINGLE_THREAD 2 //异步单线程 16#define _ASYNCHRONOUS_MULTITHREADING 3 //异步多线程 17//模式(自由选择) 18#define _MODE _ASYNCHRONOUS_SINGLE_THREAD 19 20#define _MAX_LEVEL 4 //最大层级 21#define _LEVEL 4 //层级 22 23#if (_LEVEL <= _MAX_LEVEL) 24class TimeWheel final 25{ 26private: 27//事件信息 28 typedef struct _timerInfo 29 { 30 UINT level; //存在层级 31 UINT groove; //存在槽数 32bool once; //是否只执行一次 33 function<void()> func; //事件回调 34 array<UINT, _LEVEL> time; //事件层级(小到大) 35 }TIMEINFO, * TIMEINFO_PTR; 36 37static unique_ptr<TimeWheel> _me; //实例指针 38 mutex _lock; //线程锁 39 condition_variable _condition; //条件变量 40 array<USHORT, _LEVEL> _grooveNum; //层级槽数 41 array<USHORT, _LEVEL> _pointer{ 0 }; //层级指针 42 UINT _tick; //滴答(单位:毫秒) 43 list<_timerInfo>* _eventList[_LEVEL]; //事件列表 44 atomic<UINT> _taskNum{ 0 }; //当前任务数 45 atomic<bool> _isInit{ false }; //是否初始化 46 atomic<bool> _isRun{ true }; //是否正在运行 47protected: 48 TimeWheel() = default; 49 TimeWheel(CONST TimeWheel&) = delete; 50 TimeWheel& operator =(CONST TimeWheel&) = delete; 51public: 52 ~TimeWheel() { 53 _isRun = false; 54 }; 55//获取实例 56static TimeWheel& getInstance() { 57static once_flag _flag; 58 call_once(_flag, [&]() { 59 _me.reset(new TimeWheel); 60 }); 61return *_me; 62 } 63//销毁 64void destroy() { 65 _me.reset(nullptr); 66 } 67 68//初始化数据(tick: 滴答, grooveNum: 槽数) 69void init(UINT tick, array<USHORT, _LEVEL>& grooveNum); 70//添加定时事件(time: 秒) 71 template<typename Func, typename... Args> 72 auto addTimer(FLOAT time, BOOL loop, Func&& func, Args&& ... args); 73//清除定时事件 74void clearTimer(list<_timerInfo>::iterator timer); 75}; 76 77//添加定时事件 78 template<typename Func, typename... Args> 79 auto TimeWheel::addTimer(FLOAT time, BOOL loop, Func&& func, Args&& ... args) 80{ 81if (!_isInit) throw runtime_error("未初始化"); 82//毫秒数 83 UINT ms = 1000 * time; 84//最大时间单位 85char maxUnit = -1; 86 TIMEINFO timerEvent; 87//计算各层级时间 88for (int i = _LEVEL-1; i > -1; --i) 89 { 90//获取下一级时间单位 91 UINT timeUnit = _tick; 92for (int j = 0; j < i; timeUnit *= _grooveNum[j++]); 93//计算轮数 94 timerEvent.time[i] = ms / timeUnit; 95//更新剩余时间 96if (timerEvent.time[i] > 0) 97 { 98 ms -= timerEvent.time[i] * timeUnit; 99if (maxUnit == -1) 100 maxUnit = i; 101 } 102 } 103//设置事件数据104 assert(maxUnit != -1); 105 timerEvent.level = maxUnit; 106 timerEvent.func = bind(forward<Func>(func), forward<Args>(args)...); 107 timerEvent.once = loop; 108 { 109 lock_guard<mutex> lock{ _lock }; 110 timerEvent.groove = timerEvent.time[timerEvent.level] + _pointer[timerEvent.level]; 111//加入事件列表112 _eventList[timerEvent.level][timerEvent.groove].emplace_back(timerEvent); 113 } 114 ++_taskNum; 115//唤醒线程116 _condition.notify_one(); 117return --_eventList[timerEvent.level][timerEvent.groove].end(); 118} 119#endif
1 // TimeWheel.cpp 2 #include "TimeWheel.h" 3#if (_LEVEL <= _MAX_LEVEL) 4 unique_ptr<TimeWheel> TimeWheel::_me; 5 6//初始化数据(tick: 滴答, grooveNum: 槽数) 7void TimeWheel::init(UINT tick, array<USHORT, _LEVEL>& grooveNum) 8{ 9 _tick = tick; 10//初始化槽/各层级槽数 11for (int i = 0; i < _LEVEL; _eventList[i] = new list<_timerInfo>[grooveNum[i]], _grooveNum[i] = grooveNum[i], ++i); 12//启动时间轮 13 auto loop = new thread([this]() 14 { 15while (_isRun) 16 { 17 unique_lock<mutex> lock{ _lock }; 18do{ 19 _condition.wait(lock, [this] { return _taskNum.load() != 0; }); 20//二次检测 21 } while (_taskNum == 0); 22//滴答指针 23 this_thread::sleep_for(chrono::milliseconds(_tick)); 24//事件更新函数 25 auto runTask = [this](UINT __index) { 26//cout << "下标" << __index << " 指针:" << _pointer[__index] << endl; 27 auto& taskList = _eventList[__index][_pointer[__index]]; 28if (!taskList.empty()) 29 { 30for (list<_timerInfo>::iterator it = taskList.begin(); it != taskList.end();) 31 { 32//检测剩余时间 33 BOOL surplusTime = false; 34for (int i = __index - 1; i >= 0; --i) 35 { 36if (it->time[i] > 0) 37 { 38//更新事件时间及存在层级 39 surplusTime = true; 40 it->time[__index] = 0; 41 it->level = i; 42break; 43 } 44 } 45//存在剩余时间 46if (surplusTime) 47 { 48//加入事件列表 49 it->groove = it->time[it->level] + _pointer[it->level]; 50 _eventList[it->level][it->groove].push_back(*it); 51 it = taskList.erase(it); 52 } 53//无剩余时间 54else 55 { 56#if (_MODE == _ASYNCHRONOUS_MULTITHREADING) 57 auto task = new thread([&](function<void()>&& func) 58 { 59 cout << "执行函数" << endl; 60 func(); 61 }, it->func); 62#else 63 it->func(); 64#endif 65if (it->once) 66 { 67 cout << "删除迭代器" << endl; 68 it = taskList.erase(it); 69 --_taskNum; 70//如果没有任务 71if (_taskNum == 0) 72return; 73 } 74else 75 ++it; 76 } 77 } 78 } 79 }; 80//执行函数 81 auto runTaskFunc = [&](UINT _index) 82 { 83#if (_MODE == _ASYNCHRONOUS_SINGLE_THREAD || _MODE == _ASYNCHRONOUS_MULTITHREADING) 84 auto task = new thread([&](UINT&& ___index) 85 { 86 runTask(___index); 87 }, _index); 88#else 89 runTask(_index); 90#endif 91 }; 92//更新指针 93 UINT index = 0; 94 function<void(UINT&, bool)> upadtePointer; 95 upadtePointer = [&](UINT& __index, bool __runtasks) 96 { 97if (__index > _LEVEL) return; 98if (_pointer[__index] < _grooveNum[__index]) 99 { 100 ++_pointer[__index]; 101//上级指针更新102if (_pointer[__index] == _grooveNum[__index]) 103 { 104 _pointer[__index++] = 0; 105 runTaskFunc(__index); 106 upadtePointer(__index, false); 107return; 108 } 109if (__runtasks) 110 runTaskFunc(__index); 111 } 112 }; 113 upadtePointer(index, true); 114 } 115 }); 116 _isInit = true; 117} 118119//清除定时事件120void TimeWheel::clearTimer(list<_timerInfo>::iterator timer) 121{ 122if (!_isInit) throw runtime_error("未初始化"); 123 _eventList[timer->level][timer->groove].erase(timer); 124 --_taskNum; 125} 126#endif
1 // main.cpp 2 #include "TimeWheel.h" 3 4int main(int argc, TCHAR* argv[]) 5try{ 6//-------------------------------------初始化数据 7 auto&& timer = TimeWheel::getInstance(); 8 array<USHORT, 4> grooveNum{ 5,60,60,24 }; 9 timer.init(200, grooveNum); 10//当前时间11 OtherTools::getLocalTime(); 12 auto timer1 = timer.addTimer(5, true, [&]() { 13 printf("执行任务timer2\n"); 14 OtherTools::getLocalTime(); 15//timer.clearTimer(timer1);16 }); 17} 18catch (exception err) 19{ 20 cout <<"Main Error: exception type -> "<< err.what() << endl; 21 }
原文:https://www.cnblogs.com/muzzik/p/11441244.html
内容总结
以上是互联网集市为您收集整理的C++实现时间轮定时器全部内容,希望文章能够帮你解决C++实现时间轮定时器所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。