timer.h 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #ifndef __TIMER_H__
  2. #define __TIMER_H__
  3. #include "basic/basic.h"
  4. #include <functional>
  5. class Timer
  6. {
  7. public:
  8. ~Timer() { Stop(); }
  9. // interval 为 0 表示时刻执行
  10. template<typename Func>
  11. void Start(int fps, Func&& func)
  12. {
  13. static_assert(std::is_convertible_v<Func, std::function<void()>>,
  14. "func need to be std::function<void()>");
  15. _fps = fps;
  16. _tickCnt = 0;
  17. _isOverload = false;
  18. __CheckNo(!_isRunning);
  19. using namespace std::chrono;
  20. _isRunning = true;
  21. _beginTime = high_resolution_clock::now();
  22. if (_fps > 0) {
  23. auto task = [this, func = std::forward<Func>(func)]() mutable {
  24. while (_isRunning) {
  25. // 这里不能直接使用整数除法
  26. // 因为整数除法有截断,导致最终睡眠的时间少一些
  27. uint64_t goalTime = int((double(1000.0) / _fps * _tickCnt) + 0.5);
  28. ++_tickCnt;
  29. auto nowTime = high_resolution_clock::now();
  30. auto duration = duration_cast<milliseconds>(nowTime - _beginTime).count();
  31. int64_t sleepTime = goalTime - duration;
  32. if (sleepTime > 0) {
  33. SleepMs(sleepTime);
  34. }
  35. #ifdef __AVDEBUG
  36. // else if (sleepTime < 0) {
  37. // printf("Time out : %lld\n", -sleepTime);
  38. // }
  39. #endif
  40. _isOverload = -sleepTime > 1000; // 捕获的过载时间设置为 1s
  41. func();
  42. }
  43. };
  44. _thread = new std::thread(std::move(task));
  45. // timeBeginPeriod(1);
  46. return;
  47. }
  48. auto task = [this, func = std::forward<Func>(func)]() mutable {
  49. while (_isRunning) {
  50. func();
  51. }
  52. };
  53. _thread = new std::thread(std::move(task));
  54. }
  55. void Stop()
  56. {
  57. _isRunning = false;
  58. if (_thread == nullptr) {
  59. return;
  60. }
  61. // if (_fps > 0) {
  62. // timeEndPeriod(1);
  63. // }
  64. _thread->join();
  65. delete _thread;
  66. _thread = nullptr;
  67. }
  68. bool IsOverload() const { return _isOverload; }
  69. private:
  70. int _fps = 100;
  71. int _isRunning = false;
  72. int _isOverload = false;
  73. std::vector<int> vec;
  74. std::chrono::time_point<std::chrono::high_resolution_clock> _beginTime;
  75. std::thread* _thread = nullptr;
  76. uint64_t _tickCnt = 0;
  77. };
  78. #endif