1
0

hthread.h 4.6 KB

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