timer.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #ifndef _FY_TIMER_H_
  2. #define _FY_TIMER_H_
  3. #include <time.h>
  4. #include <map>
  5. #include <memory.h>
  6. #include <string.h>
  7. #include <asm-generic/siginfo.h>
  8. #include "utils/Log.h"
  9. #include "mutex.hpp"
  10. namespace base {
  11. /**
  12. * 计时timer
  13. */
  14. class timer {
  15. public:
  16. timer():add_up_time_(0), start_time_(this->uptime()) {
  17. }
  18. void reset() {
  19. start_time_ = this->uptime();
  20. add_up_time_ = 0;
  21. }
  22. int64_t elapsed() const {
  23. if (start_time_ < 0) {
  24. return add_up_time_;
  25. }
  26. return this->uptime() - start_time_ + add_up_time_;
  27. }
  28. void pause() {
  29. if (start_time_ >= 0) {
  30. add_up_time_ += (this->uptime() - start_time_);
  31. }
  32. start_time_ = -1;
  33. }
  34. void resume() {
  35. if (start_time_ < 0) {
  36. start_time_ = this->uptime();
  37. }
  38. }
  39. bool paused() const {
  40. return start_time_ < 0;
  41. }
  42. private:
  43. static int64_t uptime() {
  44. struct timespec ts;
  45. clock_gettime(CLOCK_BOOTTIME, &ts);
  46. return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
  47. }
  48. int64_t add_up_time_;
  49. int64_t start_time_;
  50. };
  51. /**
  52. * 日志输出时间间隔
  53. */
  54. class progress_timer : private base::timer {
  55. public:
  56. explicit progress_timer(const char* label):base::timer(),label_(label) {
  57. }
  58. ~progress_timer(){
  59. int64_t progress = elapsed();
  60. int64_t second = progress/1000;
  61. if (second > 0) {
  62. LOGD("%s took \033[1;32m%llds.%lldms\033[0m", label_.c_str(), progress/1000, progress%1000);
  63. } else {
  64. LOGD("%s took \033[1;32m%lldms\033[0m", label_.c_str(),progress%1000);
  65. }
  66. }
  67. private:
  68. std::string label_;
  69. };
  70. /**
  71. * 可能需要链接 -lrt
  72. */
  73. class posix_timer {
  74. public:
  75. typedef void (*posix_timer_callback)(int timer_id, void * user_data);
  76. private:
  77. struct description;
  78. public:
  79. virtual ~posix_timer() {
  80. std::map<int, description>::iterator des = all_timer_.begin();
  81. for (; des != all_timer_.end(); des++) {
  82. destroy(des->first);
  83. }
  84. }
  85. private:
  86. /**
  87. * return timer id
  88. */
  89. static int _create(bool oneshot, int period_millis, int delay_millis, posix_timer_callback on_timer, void* user_data) {
  90. fy::lock_guard<fy::mutex> lock(instance()->mutex_);
  91. instance()->sival_int_++;
  92. int ret;
  93. timer_t timer;
  94. struct sigevent evp;
  95. struct timespec spec;
  96. struct itimerspec time_value;
  97. memset((void*)&evp, 0, sizeof(sigevent));
  98. evp.sigev_value.sival_int = instance()->sival_int_;
  99. /* 子线程运行 */
  100. evp.sigev_notify = SIGEV_THREAD;
  101. evp.sigev_notify_function = posix_timer::timer_thread_callback_wrapper;
  102. ret = timer_create(CLOCK_MONOTONIC, &evp, &timer);
  103. if (-1 == ret) {
  104. //LOGE("timer_create Failed");
  105. return -1;
  106. }
  107. time_value.it_interval.tv_sec = period_millis / 1000; /*n秒触发一次*/
  108. time_value.it_interval.tv_nsec = period_millis % 1000 * 1000 * 1000;
  109. clock_gettime(CLOCK_MONOTONIC, &spec);
  110. time_value.it_value.tv_sec = spec.tv_sec + delay_millis / 1000; /*n秒后启动*/
  111. time_value.it_value.tv_nsec = spec.tv_nsec + delay_millis % 1000 * 1000 * 1000;
  112. struct description des = {
  113. oneshot,
  114. period_millis,
  115. timer,
  116. instance()->sival_int_,
  117. user_data,
  118. on_timer
  119. };
  120. instance()->all_timer_[instance()->sival_int_] = des;
  121. //启动
  122. ret = timer_settime(timer, CLOCK_MONOTONIC, &time_value, NULL);
  123. if(-1 == ret) {
  124. //LOGE("timer_settime Failed");
  125. timer_delete(timer);
  126. instance()->all_timer_.erase(instance()->all_timer_.find(instance()->sival_int_));
  127. return -2;
  128. }
  129. //LOGD("start timer");
  130. return instance()->sival_int_;
  131. }
  132. public:
  133. static void destroy(int timer_id) {
  134. fy::lock_guard<fy::mutex> lock(instance()->mutex_);
  135. std::map<int, description>::iterator it = instance()->all_timer_.find(timer_id);
  136. if (it == instance()->all_timer_.end()) {
  137. return;
  138. }
  139. timer_delete(it->second.timer);
  140. instance()->all_timer_.erase(it);
  141. }
  142. static int oneshot(time_t delay_millis, posix_timer_callback on_timer, void* user_data) {
  143. return instance()->_create(true, 0, delay_millis, on_timer, user_data);
  144. }
  145. /**
  146. * 每次回调都会创建一个新线程,并且,回调的执行时间不影响定时器下一次的触发时间;
  147. * 这意味着,如果回调中耗时长于period_millis,会同时存在多个回调。
  148. */
  149. static int create(int period_millis, int delay_millis, posix_timer_callback on_timer, void* user_data) {
  150. return instance()->_create(false, period_millis, delay_millis, on_timer, user_data);
  151. }
  152. private:
  153. posix_timer() {
  154. sival_int_ = 0;
  155. }
  156. static posix_timer* instance() {
  157. static posix_timer singleton;
  158. return &singleton;
  159. }
  160. static void timer_thread_callback_wrapper(union sigval v) {
  161. instance()->timer_thread_callback(v);
  162. }
  163. void timer_thread_callback(union sigval v) {
  164. description des;
  165. { // scope lock
  166. fy::lock_guard<fy::mutex> lock(mutex_);
  167. std::map<int, description>::iterator it = all_timer_.find(v.sival_int);
  168. if (it == all_timer_.end()) {
  169. return;
  170. }
  171. des = it->second;
  172. if (des.is_oneshot) {
  173. timer_delete(it->second.timer);
  174. instance()->all_timer_.erase(it);
  175. }
  176. }
  177. des.callback(des.sival_int, des.user_data);
  178. }
  179. struct description {
  180. bool is_oneshot;
  181. time_t interval;
  182. timer_t timer;
  183. int sival_int;
  184. void* user_data;
  185. posix_timer_callback callback;
  186. };
  187. private:
  188. int sival_int_;
  189. fy::mutex mutex_;
  190. std::map<int, description> all_timer_;
  191. };
  192. } /* namespace fy */
  193. #endif /* JNI_FY_TIMER_H_ */