hthread.h 4.5 KB

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