hloop.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #include "hloop.h"
  2. #include "hio.h"
  3. #include "io_watcher.h"
  4. #include "hdef.h"
  5. #include "htime.h"
  6. static void hloop_update_time(hloop_t* loop) {
  7. loop->cur_time = gethrtime();
  8. }
  9. int hloop_init(hloop_t* loop) {
  10. loop->status = HLOOP_STATUS_STOP;
  11. loop->event_counter = 0;
  12. loop->timer_counter = 0;
  13. loop->idle_counter = 0;
  14. loop->min_timer_timeout = INFINITE;
  15. loop->iowatcher = NULL;
  16. //hloop_iowatcher_init(loop);
  17. return 0;
  18. }
  19. void hloop_cleanup(hloop_t* loop) {
  20. for (auto& pair : loop->timers) {
  21. SAFE_FREE(pair.second);
  22. }
  23. loop->timers.clear();
  24. for (auto& pair : loop->idles) {
  25. SAFE_FREE(pair.second);
  26. }
  27. loop->idles.clear();
  28. for (auto& pair : loop->ios) {
  29. hio_t* io = pair.second;
  30. hio_del(io);
  31. SAFE_FREE(io);
  32. }
  33. loop->ios.clear();
  34. hloop_iowatcher_cleanup(loop);
  35. }
  36. int hloop_handle_timers(hloop_t* loop) {
  37. int ntimer = 0;
  38. auto iter = loop->timers.begin();
  39. while (iter != loop->timers.end()) {
  40. htimer_t* timer = iter->second;
  41. if (timer->destroy) goto destroy;
  42. if (!timer->active) goto next;
  43. if (timer->repeat == 0) goto destroy;
  44. if (timer->next_timeout < loop->cur_time) {
  45. ++ntimer;
  46. if (timer->cb) {
  47. timer->cb(timer, timer->userdata);
  48. }
  49. timer->next_timeout += timer->timeout*1000;
  50. if (timer->repeat != INFINITE) {
  51. --timer->repeat;
  52. }
  53. }
  54. next:
  55. ++iter;
  56. continue;
  57. destroy:
  58. free(timer);
  59. iter = loop->timers.erase(iter);
  60. }
  61. return ntimer;
  62. }
  63. int hloop_handle_idles(hloop_t* loop) {
  64. int nidle = 0;
  65. auto iter = loop->idles.begin();
  66. while (iter != loop->idles.end()) {
  67. hidle_t* idle = iter->second;
  68. if (idle->destroy) goto destroy;
  69. if (!idle->active) goto next;
  70. if (idle->repeat == 0) goto destroy;
  71. ++nidle;
  72. if (idle->cb) {
  73. idle->cb(idle, idle->userdata);
  74. }
  75. if (idle->repeat != INFINITE) {
  76. --idle->repeat;
  77. }
  78. next:
  79. ++iter;
  80. continue;
  81. destroy:
  82. free(idle);
  83. iter = loop->idles.erase(iter);
  84. }
  85. return nidle;
  86. }
  87. #define PAUSE_SLEEP_TIME 10 // ms
  88. #define MIN_POLL_TIMEOUT 1 // ms
  89. #define MAX_POLL_TIMEOUT 1000 // ms
  90. int hloop_run(hloop_t* loop) {
  91. int ntimer, nio, nidle;
  92. int poll_timeout;
  93. loop->start_time = gethrtime();
  94. loop->status = HLOOP_STATUS_RUNNING;
  95. loop->loop_cnt = 0;
  96. while (loop->status != HLOOP_STATUS_STOP) {
  97. hloop_update_time(loop);
  98. if (loop->status == HLOOP_STATUS_PAUSE) {
  99. msleep(PAUSE_SLEEP_TIME);
  100. continue;
  101. }
  102. ++loop->loop_cnt;
  103. // timers -> events -> idles
  104. ntimer = nio = nidle = 0;
  105. poll_timeout = INFINITE;
  106. if (loop->timers.size() != 0) {
  107. ntimer = hloop_handle_timers(loop);
  108. poll_timeout = MAX(MIN_POLL_TIMEOUT, loop->min_timer_timeout/10);
  109. }
  110. if (loop->ios.size() == 0 || loop->idles.size() != 0) {
  111. poll_timeout = MIN(poll_timeout, MAX_POLL_TIMEOUT);
  112. }
  113. if (loop->ios.size() != 0) {
  114. nio = hloop_handle_ios(loop, poll_timeout);
  115. }
  116. else {
  117. msleep(poll_timeout);
  118. }
  119. if (ntimer == 0 && nio == 0 && loop->idles.size() != 0) {
  120. nidle = hloop_handle_idles(loop);
  121. }
  122. //printf("loop_cnt=%lu ntimer=%d nio=%d nidle=%d\n", loop->loop_cnt, ntimer, nio, nidle);
  123. }
  124. loop->status = HLOOP_STATUS_STOP;
  125. loop->end_time = gethrtime();
  126. hloop_cleanup(loop);
  127. return 0;
  128. }
  129. int hloop_stop(hloop_t* loop) {
  130. loop->status = HLOOP_STATUS_STOP;
  131. return 0;
  132. }
  133. int hloop_pause(hloop_t* loop) {
  134. if (loop->status == HLOOP_STATUS_RUNNING) {
  135. loop->status = HLOOP_STATUS_PAUSE;
  136. }
  137. return 0;
  138. }
  139. int hloop_resume(hloop_t* loop) {
  140. if (loop->status == HLOOP_STATUS_PAUSE) {
  141. loop->status = HLOOP_STATUS_RUNNING;
  142. }
  143. return 0;
  144. }
  145. htimer_t* htimer_add(hloop_t* loop, htimer_cb cb, void* userdata, uint64_t timeout, uint32_t repeat) {
  146. htimer_t* timer = (htimer_t*)malloc(sizeof(htimer_t));
  147. memset(timer, 0, sizeof(htimer_t));
  148. timer->event_type = HEVENT_TYPE_TIMER;
  149. timer->event_id = ++loop->event_counter;
  150. timer->loop = loop;
  151. timer->timer_id = ++loop->timer_counter;
  152. timer->cb = cb;
  153. timer->userdata = userdata;
  154. timer->timeout = timeout;
  155. timer->repeat = repeat;
  156. timer->next_timeout = gethrtime() + timeout*1000;
  157. timer->active = 1;
  158. loop->timers[timer->timer_id] = timer;
  159. loop->min_timer_timeout = MIN(timeout, loop->min_timer_timeout);
  160. return timer;
  161. }
  162. void htimer_del(htimer_t* timer) {
  163. timer->active = 0;
  164. timer->destroy = 1;
  165. }
  166. void htimer_del(hloop_t* loop, uint32_t timer_id) {
  167. auto iter = loop->timers.find(timer_id);
  168. if (iter != loop->timers.end()) {
  169. htimer_t* timer = iter->second;
  170. htimer_del(timer);
  171. }
  172. }
  173. hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, void* userdata, uint32_t repeat) {
  174. hidle_t* idle = (hidle_t*)malloc(sizeof(hidle_t));
  175. memset(idle, 0, sizeof(hidle_t));
  176. idle->event_type = HEVENT_TYPE_IDLE;
  177. idle->event_id = ++loop->event_counter;
  178. idle->loop = loop;
  179. idle->idle_id = ++loop->idle_counter;
  180. idle->cb = cb;
  181. idle->userdata = userdata;
  182. idle->repeat = repeat;
  183. idle->active = 1;
  184. loop->idles[idle->idle_id] = idle;
  185. return idle;
  186. }
  187. void hidle_del(hidle_t* idle) {
  188. idle->active = 0;
  189. idle->destroy = 1;
  190. }
  191. void hidle_del(hloop_t* loop, uint32_t idle_id) {
  192. auto iter = loop->idles.find(idle_id);
  193. if (iter != loop->idles.end()) {
  194. hidle_t* idle = iter->second;
  195. hidle_del(idle);
  196. }
  197. }