hthread.h 4.5 KB

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