timer.h 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  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. if (_isRunning) {
  19. // Already running, ignore Start call
  20. return;
  21. }
  22. using namespace std::chrono;
  23. _isRunning = true;
  24. _beginTime = high_resolution_clock::now();
  25. if (_fps > 0) {
  26. auto task = [this, func = std::forward<Func>(func)]() mutable {
  27. while (_isRunning) {
  28. // 这里不能直接使用整数除法
  29. // 因为整数除法有截断,导致最终睡眠的时间少一些
  30. uint64_t goalTime = int((double(1000.0) / _fps * _tickCnt) + 0.5);
  31. ++_tickCnt;
  32. auto nowTime = high_resolution_clock::now();
  33. auto duration = duration_cast<milliseconds>(nowTime - _beginTime).count();
  34. int64_t sleepTime = goalTime - duration;
  35. if (sleepTime > 0) {
  36. SleepMs(sleepTime);
  37. }
  38. #ifdef __AVDEBUG
  39. // else if (sleepTime < 0) {
  40. // printf("Time out : %lld\n", -sleepTime);
  41. // }
  42. #endif
  43. _isOverload = -sleepTime > 1000; // 捕获的过载时间设置为 1s
  44. func();
  45. }
  46. };
  47. _thread = new std::thread(std::move(task));
  48. // timeBeginPeriod(1);
  49. return;
  50. }
  51. auto task = [this, func = std::forward<Func>(func)]() mutable {
  52. while (_isRunning) {
  53. func();
  54. }
  55. };
  56. _thread = new std::thread(std::move(task));
  57. }
  58. void Stop()
  59. {
  60. _isRunning = false;
  61. if (_thread == nullptr) {
  62. return;
  63. }
  64. // if (_fps > 0) {
  65. // timeEndPeriod(1);
  66. // }
  67. _thread->join();
  68. delete _thread;
  69. _thread = nullptr;
  70. }
  71. bool IsOverload() const { return _isOverload; }
  72. private:
  73. int _fps = 100;
  74. int _isRunning = false;
  75. int _isOverload = false;
  76. std::vector<int> vec;
  77. std::chrono::time_point<std::chrono::high_resolution_clock> _beginTime;
  78. std::thread* _thread = nullptr;
  79. uint64_t _tickCnt = 0;
  80. };
  81. #endif