| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- #ifndef HV_THREAD_H_
- #define HV_THREAD_H_
- #include "hplatform.h"
- #ifdef OS_WIN
- #define hv_getpid (long)GetCurrentProcessId
- #else
- #define hv_getpid (long)getpid
- #endif
- #ifdef OS_WIN
- #define hv_gettid (long)GetCurrentThreadId
- #elif HAVE_GETTID || defined(OS_ANDROID)
- #define hv_gettid (long)gettid
- #elif defined(OS_LINUX)
- #include <sys/syscall.h>
- #define hv_gettid() (long)syscall(SYS_gettid)
- #elif defined(OS_DARWIN)
- static inline long hv_gettid() {
- uint64_t tid = 0;
- pthread_threadid_np(NULL, &tid);
- return tid;
- }
- #elif HAVE_PTHREAD_H
- #define hv_gettid (long)pthread_self
- #else
- #define hv_gettid hv_getpid
- #endif
- /*
- #include "hthread.h"
- HTHREAD_ROUTINE(thread_demo) {
- printf("thread[%ld] start\n", hv_gettid());
- hv_delay(3000);
- printf("thread[%ld] end\n", hv_gettid());
- return 0;
- }
- int main() {
- hthread_t th = hthread_create(thread_demo, NULL);
- hthread_join(th);
- return 0;
- }
- */
- #ifdef OS_WIN
- typedef HANDLE hthread_t;
- typedef DWORD (WINAPI *hthread_routine)(void*);
- #define HTHREAD_RETTYPE DWORD
- #define HTHREAD_ROUTINE(fname) DWORD WINAPI fname(void* userdata)
- static inline hthread_t hthread_create(hthread_routine fn, void* userdata) {
- return CreateThread(NULL, 0, fn, userdata, 0, NULL);
- }
- static inline int hthread_join(hthread_t th) {
- WaitForSingleObject(th, INFINITE);
- CloseHandle(th);
- return 0;
- }
- #else
- typedef pthread_t hthread_t;
- typedef void* (*hthread_routine)(void*);
- #define HTHREAD_RETTYPE void*
- #define HTHREAD_ROUTINE(fname) void* fname(void* userdata)
- static inline hthread_t hthread_create(hthread_routine fn, void* userdata) {
- pthread_t th;
- pthread_create(&th, NULL, fn, userdata);
- return th;
- }
- static inline int hthread_join(hthread_t th) {
- return pthread_join(th, NULL);
- }
- #endif
- #ifdef __cplusplus
- /************************************************
- * HThread
- * Status: STOP,RUNNING,PAUSE
- * Control: start,stop,pause,resume
- * first-level virtual: doTask
- * second-level virtual: run
- ************************************************/
- #include <thread>
- #include <atomic>
- #include <chrono>
- class HThread {
- public:
- enum Status {
- STOP,
- RUNNING,
- PAUSE,
- };
- enum SleepPolicy {
- YIELD,
- SLEEP_FOR,
- SLEEP_UNTIL,
- NO_SLEEP,
- };
- HThread() {
- status = STOP;
- status_changed = false;
- dotask_cnt = 0;
- sleep_policy = YIELD;
- sleep_ms = 0;
- }
- virtual ~HThread() {}
- void setStatus(Status stat) {
- status_changed = true;
- status = stat;
- }
- void setSleepPolicy(SleepPolicy policy, uint32_t ms = 0) {
- sleep_policy = policy;
- sleep_ms = ms;
- setStatus(status);
- }
- virtual int start() {
- if (status == STOP) {
- thread = std::thread([this] {
- if (!doPrepare()) return;
- setStatus(RUNNING);
- run();
- setStatus(STOP);
- if (!doFinish()) return;
- });
- }
- return 0;
- }
- virtual int stop() {
- if (status != STOP) {
- setStatus(STOP);
- }
- if (thread.joinable()) {
- thread.join(); // wait thread exit
- }
- return 0;
- }
- virtual int pause() {
- if (status == RUNNING) {
- setStatus(PAUSE);
- }
- return 0;
- }
- virtual int resume() {
- if (status == PAUSE) {
- setStatus(RUNNING);
- }
- return 0;
- }
- virtual void run() {
- while (status != STOP) {
- while (status == PAUSE) {
- std::this_thread::yield();
- }
- doTask();
- ++dotask_cnt;
- HThread::sleep();
- }
- }
- virtual bool doPrepare() {return true;}
- virtual void doTask() {}
- virtual bool doFinish() {return true;}
- std::thread thread;
- std::atomic<Status> status;
- uint32_t dotask_cnt;
- protected:
- void sleep() {
- switch (sleep_policy) {
- case YIELD:
- std::this_thread::yield();
- break;
- case SLEEP_FOR:
- std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms));
- break;
- case SLEEP_UNTIL: {
- if (status_changed) {
- status_changed = false;
- base_tp = std::chrono::system_clock::now();
- }
- base_tp += std::chrono::milliseconds(sleep_ms);
- std::this_thread::sleep_until(base_tp);
- }
- break;
- default: // donothing, go all out.
- break;
- }
- }
- SleepPolicy sleep_policy;
- uint32_t sleep_ms;
- // for SLEEP_UNTIL
- std::atomic<bool> status_changed;
- std::chrono::system_clock::time_point base_tp;
- };
- #endif
- #endif // HV_THREAD_H_
|