#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 #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 #include #include 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; 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::steady_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 status_changed; std::chrono::steady_clock::time_point base_tp; }; #endif #endif // HV_THREAD_H_