1
0

EventLoop.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #ifndef HV_EVENT_LOOP_HPP_
  2. #define HV_EVENT_LOOP_HPP_
  3. #include <functional>
  4. #include <queue>
  5. #include <map>
  6. #include <mutex>
  7. #include "hloop.h"
  8. #include "hthread.h"
  9. #include "Event.h"
  10. namespace hv {
  11. class EventLoop {
  12. public:
  13. typedef std::function<void()> Functor;
  14. EventLoop() {
  15. loop_ = hloop_new(HLOOP_FLAG_AUTO_FREE);
  16. assert(loop_ != NULL);
  17. hloop_set_userdata(loop_, this);
  18. }
  19. ~EventLoop() {
  20. stop();
  21. }
  22. void start() {
  23. if (loop_ == NULL) return;
  24. hloop_run(loop_);
  25. }
  26. void stop() {
  27. if (loop_ == NULL) return;
  28. hloop_stop(loop_);
  29. loop_ = NULL;
  30. }
  31. void pause() {
  32. if (loop_ == NULL) return;
  33. hloop_pause(loop_);
  34. }
  35. void resume() {
  36. if (loop_ == NULL) return;
  37. hloop_resume(loop_);
  38. }
  39. TimerID setTimer(int timeout_ms, TimerCallback cb, int repeat = INFINITE) {
  40. htimer_t* htimer = htimer_add(loop_, onTimer, timeout_ms, repeat);
  41. Timer timer(htimer, cb, repeat);
  42. hevent_set_userdata(htimer, &timer);
  43. TimerID timerID = hevent_id(htimer);
  44. mutex_.lock();
  45. timers[timerID] = timer;
  46. mutex_.unlock();
  47. return timerID;
  48. }
  49. // alias javascript setTimeout, setInterval
  50. TimerID setTimeout(int timeout_ms, TimerCallback cb) {
  51. return setTimer(timeout_ms, cb, 1);
  52. }
  53. TimerID setInterval(int interval_ms, TimerCallback cb) {
  54. return setTimer(interval_ms, cb, INFINITE);
  55. }
  56. void killTimer(TimerID timerID) {
  57. std::lock_guard<std::mutex> locker(mutex_);
  58. auto iter = timers.find(timerID);
  59. if (iter != timers.end()) {
  60. Timer& timer = iter->second;
  61. htimer_del(timer.timer);
  62. timers.erase(iter);
  63. }
  64. }
  65. void resetTimer(TimerID timerID) {
  66. std::lock_guard<std::mutex> locker(mutex_);
  67. auto iter = timers.find(timerID);
  68. if (iter != timers.end()) {
  69. Timer& timer = iter->second;
  70. htimer_reset(timer.timer);
  71. if (timer.repeat == 0) {
  72. timer.repeat = 1;
  73. }
  74. }
  75. }
  76. bool isInLoop() {
  77. return hv_gettid() == hloop_tid(loop_);
  78. }
  79. void assertInLoop() {
  80. assert(isInLoop());
  81. }
  82. void runInLoop(Functor fn) {
  83. if (isInLoop()) {
  84. if (fn) fn();
  85. } else {
  86. queueInLoop(fn);
  87. }
  88. }
  89. void queueInLoop(Functor fn) {
  90. postEvent([fn](Event* ev) {
  91. if (fn) fn();
  92. });
  93. }
  94. void postEvent(EventCallback cb) {
  95. if (loop_ == NULL) return;
  96. EventPtr ev(new Event(cb));
  97. ev->event.cb = onCustomEvent;
  98. mutex_.lock();
  99. customEvents.push(ev);
  100. mutex_.unlock();
  101. hloop_post_event(loop_, &ev->event);
  102. }
  103. private:
  104. static void onTimer(htimer_t* htimer) {
  105. hloop_t* hloop = (hloop_t*)hevent_loop(htimer);
  106. EventLoop* loop = (EventLoop*)hloop_userdata(hloop);
  107. TimerID timerID = hevent_id(htimer);
  108. TimerCallback cb = NULL;
  109. loop->mutex_.lock();
  110. auto iter = loop->timers.find(timerID);
  111. if (iter != loop->timers.end()) {
  112. Timer& timer = iter->second;
  113. cb = timer.cb;
  114. --timer.repeat;
  115. }
  116. loop->mutex_.unlock();
  117. if (cb) cb(timerID);
  118. // NOTE: refind iterator, because iterator may be invalid
  119. // if the timer-related interface is called in the callback function above.
  120. loop->mutex_.lock();
  121. iter = loop->timers.find(timerID);
  122. if (iter != loop->timers.end()) {
  123. Timer& timer = iter->second;
  124. if (timer.repeat == 0) {
  125. // htimer_t alloc and free by hloop, but timers[timerID] managed by EventLoop.
  126. loop->timers.erase(iter);
  127. }
  128. }
  129. loop->mutex_.unlock();
  130. }
  131. static void onCustomEvent(hevent_t* hev) {
  132. hloop_t* hloop = (hloop_t*)hevent_loop(hev);
  133. EventLoop* loop = (EventLoop*)hloop_userdata(hloop);
  134. loop->mutex_.lock();
  135. EventPtr ev = loop->customEvents.front();
  136. loop->customEvents.pop();
  137. loop->mutex_.unlock();
  138. if (ev && ev->cb) ev->cb(ev.get());
  139. }
  140. private:
  141. hloop_t* loop_;
  142. std::mutex mutex_;
  143. std::queue<EventPtr> customEvents; // GUAREDE_BY(mutex_)
  144. std::map<TimerID, Timer> timers; // GUAREDE_BY(mutex_)
  145. };
  146. }
  147. #endif // HV_EVENT_LOOP_HPP_