hthread.h 4.3 KB

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