hthread.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #ifndef HW_THREAD_H_
  2. #define HW_THREAD_H_
  3. #include "hplatform.h"
  4. #include "hdef.h"
  5. #ifdef OS_WIN
  6. #define gettid GetCurrentThreadId
  7. #elif defined(OS_ANDROID)
  8. #define gettid gettid
  9. #elif defined(OS_LINUX)
  10. #include <sys/syscall.h>
  11. static inline int gettid() {
  12. return syscall(SYS_gettid);
  13. }
  14. #elif HAVE_PTHREAD_H
  15. #define gettid pthread_self
  16. #endif
  17. #ifdef OS_WIN
  18. typedef HANDLE hthread_t;
  19. typedef DWORD (WINAPI *hthread_routine)(void*);
  20. #define HTHREAD_ROUTINE(fname) DWORD WINAPI fname(void* userdata)
  21. static inline hthread_t hthread_create(hthread_routine fn, void* userdata) {
  22. return CreateThread(NULL, 0, fn, userdata, 0, NULL);
  23. }
  24. static inline int hthread_join(hthread_t th) {
  25. return WaitForSingleObject(th, INFINITE);
  26. }
  27. #else
  28. typedef pthread_t hthread_t;
  29. typedef void* (*hthread_routine)(void*);
  30. #define HTHREAD_ROUTINE(fname) void* fname(void* userdata)
  31. static inline hthread_t hthread_create(hthread_routine fn, void* userdata) {
  32. pthread_t th;
  33. pthread_create(&th, NULL, fn, userdata);
  34. return th;
  35. }
  36. static inline int hthread_join(hthread_t th) {
  37. return pthread_join(th, NULL);
  38. }
  39. #endif
  40. #ifdef __cplusplus
  41. /************************************************
  42. * HThread
  43. * Status: STOP,RUNNING,PAUSE
  44. * Control: start,stop,pause,resume
  45. * first-level virtual: doTask
  46. * second-level virtual: run
  47. ************************************************/
  48. #include <thread>
  49. #include <atomic>
  50. #include <chrono>
  51. class HThread {
  52. public:
  53. HThread() {
  54. status = STOP;
  55. status_switch = false;
  56. sleep_policy = YIELD;
  57. sleep_ms = 0;
  58. }
  59. virtual ~HThread() {}
  60. virtual int start() {
  61. if (status == STOP) {
  62. switchStatus(RUNNING);
  63. dotask_cnt = 0;
  64. thread = std::thread([this]{
  65. doPrepare();
  66. run();
  67. doFinish();
  68. });
  69. }
  70. return 0;
  71. }
  72. virtual int stop() {
  73. if (status != STOP) {
  74. switchStatus(STOP);
  75. thread.join(); // wait thread exit
  76. }
  77. return 0;
  78. }
  79. virtual int pause() {
  80. if (status == RUNNING) {
  81. switchStatus(PAUSE);
  82. }
  83. return 0;
  84. }
  85. virtual int resume() {
  86. if (status == PAUSE) {
  87. switchStatus(RUNNING);
  88. }
  89. return 0;
  90. }
  91. virtual void run() {
  92. while (status != STOP) {
  93. while (status == PAUSE) {
  94. std::this_thread::yield();
  95. }
  96. doTask();
  97. dotask_cnt++;
  98. sleep();
  99. }
  100. }
  101. virtual void doPrepare() {}
  102. virtual void doTask() {}
  103. virtual void doFinish() {}
  104. std::thread thread;
  105. enum Status {
  106. STOP,
  107. RUNNING,
  108. PAUSE,
  109. };
  110. std::atomic<Status> status;
  111. uint32_t dotask_cnt;
  112. enum SleepPolicy {
  113. YIELD,
  114. SLEEP_FOR,
  115. SLEEP_UNTIL,
  116. NO_SLEEP,
  117. };
  118. void setSleepPolicy(SleepPolicy policy, uint32_t ms = 0) {
  119. status_switch = true;
  120. sleep_policy = policy;
  121. sleep_ms = ms;
  122. }
  123. protected:
  124. void switchStatus(Status stat) {
  125. status_switch = true;
  126. status = stat;
  127. }
  128. void sleep() {
  129. switch (sleep_policy) {
  130. case YIELD:
  131. std::this_thread::yield();
  132. break;
  133. case SLEEP_FOR:
  134. std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms));
  135. break;
  136. case SLEEP_UNTIL: {
  137. if (status_switch) {
  138. status_switch = false;
  139. base_tp = std::chrono::system_clock::now();
  140. }
  141. base_tp += std::chrono::milliseconds(sleep_ms);
  142. std::this_thread::sleep_until(base_tp);
  143. }
  144. break;
  145. default: // donothing, go all out.
  146. break;
  147. }
  148. }
  149. std::atomic<bool> status_switch;
  150. SleepPolicy sleep_policy;
  151. std::chrono::system_clock::time_point base_tp; // for SLEEP_UNTIL
  152. uint32_t sleep_ms;
  153. };
  154. #endif
  155. #endif // HW_THREAD_H_