基于C++ Coroutines提案 ‘Stackless Resumable Functions’编写的协程库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

timer.cpp 2.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #include "librf/librf.h"
  2. namespace librf
  3. {
  4. LIBRF_API timer_manager::timer_manager()
  5. {
  6. _added_timers.reserve(128);
  7. }
  8. LIBRF_API timer_manager::~timer_manager()
  9. {
  10. clear();
  11. }
  12. LIBRF_API void timer_manager::call_target_(const timer_target_ptr & sptr, bool canceld)
  13. {
  14. auto cb = std::move(sptr->cb);
  15. sptr->st = timer_target::State::Invalid;
  16. #if _DEBUG
  17. sptr->_manager = nullptr;
  18. #endif
  19. if(cb) cb(canceld);
  20. }
  21. LIBRF_API void timer_manager::clear()
  22. {
  23. #if !RESUMEF_DISABLE_MULT_THREAD
  24. std::unique_lock<spinlock> __lock(_added_mtx);
  25. #endif
  26. auto _atimer = std::move(_added_timers);
  27. #if !RESUMEF_DISABLE_MULT_THREAD
  28. __lock.unlock();
  29. #endif
  30. for (auto& sptr : _atimer)
  31. call_target_(sptr, true);
  32. auto _rtimer = std::move(_runing_timers);
  33. for (auto & kv : _rtimer)
  34. call_target_(kv.second, true);
  35. }
  36. LIBRF_API detail::timer_target_ptr timer_manager::add_(const timer_target_ptr & sptr)
  37. {
  38. assert(sptr);
  39. assert(sptr->st == timer_target::State::Invalid);
  40. #if !RESUMEF_DISABLE_MULT_THREAD
  41. scoped_lock<spinlock> __lock(_added_mtx);
  42. #endif
  43. #if _DEBUG
  44. assert(sptr->_manager == nullptr);
  45. sptr->_manager = this;
  46. #endif
  47. sptr->st = timer_target::State::Added;
  48. _added_timers.push_back(sptr);
  49. return sptr;
  50. }
  51. LIBRF_API bool timer_manager::stop(const timer_target_ptr & sptr)
  52. {
  53. if (!sptr || sptr->st == timer_target::State::Invalid)
  54. return false;
  55. #if _DEBUG
  56. assert(sptr->_manager == this);
  57. #endif
  58. sptr->st = timer_target::State::Invalid;
  59. return true;
  60. }
  61. LIBRF_API void timer_manager::update()
  62. {
  63. {
  64. #if !RESUMEF_DISABLE_MULT_THREAD
  65. std::unique_lock<spinlock> __lock(_added_mtx);
  66. #endif
  67. if (unlikely(_added_timers.size() > 0))
  68. {
  69. auto _atimer = std::move(_added_timers);
  70. _added_timers.reserve(128);
  71. #if !RESUMEF_DISABLE_MULT_THREAD
  72. __lock.unlock();
  73. #endif
  74. for (auto& sptr : _atimer)
  75. {
  76. if (sptr->st == timer_target::State::Added)
  77. {
  78. sptr->st = timer_target::State::Runing;
  79. _runing_timers.insert({ sptr->tp, sptr });
  80. }
  81. else
  82. {
  83. assert(sptr->st == timer_target::State::Invalid);
  84. call_target_(sptr, true);
  85. }
  86. }
  87. }
  88. }
  89. if (unlikely(_runing_timers.size() > 0))
  90. {
  91. auto now_ = clock_type::now();
  92. auto iter = _runing_timers.begin();
  93. for (; iter != _runing_timers.end(); ++iter)
  94. {
  95. auto & kv = *iter;
  96. if (kv.first > now_)
  97. break;
  98. call_target_(kv.second, kv.second->st == timer_target::State::Invalid);
  99. }
  100. _runing_timers.erase(_runing_timers.begin(), iter);
  101. }
  102. }
  103. }