1 #pragma once 2 3 #include <pthread.h> 4 #include <unistd.h> 5 #include <time.h> 6 #include <limits.h> 7 #include <stdlib.h> 8 9 #include "../Common/Thread.h" 10 11 namespace MT 12 { 13 class _Fiber; 14 15 class Thread : public ThreadBase 16 { 17 pthread_t thread; 18 pthread_attr_t threadAttr; 19 20 void * stackBase; 21 size_t stackSize; 22 23 bool isStarted; 24 25 static void* ThreadFuncInternal(void *pThread) 26 { 27 Thread * self = (Thread *)pThread; 28 29 self->func(self->funcData); 30 31 pthread_exit(nullptr); 32 } 33 34 public: 35 36 Thread() 37 : stackBase(nullptr) 38 , stackSize(0) 39 , isStarted(false) 40 { 41 } 42 43 void* GetStackBase() 44 { 45 return stackBase; 46 } 47 48 size_t GetStackSize() 49 { 50 return stackSize; 51 } 52 53 54 void Start(size_t _stackSize, TThreadEntryPoint entryPoint, void *userData) 55 { 56 ASSERT(!isStarted, "Thread already stared"); 57 58 ASSERT(func == nullptr, "Thread already started"); 59 60 func = entryPoint; 61 funcData = userData; 62 63 stackSize = _stackSize; 64 65 ASSERT(stackSize >= PTHREAD_STACK_MIN, "Thread stack to small"); 66 67 stackBase = (void *)malloc(stackSize); 68 69 int err = pthread_attr_init(&threadAttr); 70 ASSERT(err == 0, "pthread_attr_init - error"); 71 72 err = pthread_attr_setstack(&threadAttr, stackBase, stackSize); 73 ASSERT(err == 0, "pthread_attr_setstack - error"); 74 75 err = pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_JOINABLE); 76 ASSERT(err == 0, "pthread_attr_setdetachstate - error"); 77 78 err = pthread_create(&thread, &threadAttr, ThreadFuncInternal, this); 79 ASSERT(err == 0, "pthread_create - error"); 80 81 isStarted = true; 82 } 83 84 void Stop() 85 { 86 ASSERT(isStarted, "Thread is not started"); 87 88 if (func == nullptr) 89 { 90 return; 91 } 92 93 void *threadStatus = nullptr; 94 int err = pthread_join(thread, &threadStatus); 95 ASSERT(err == 0, "pthread_join - error"); 96 97 err = pthread_attr_destroy(&threadAttr); 98 ASSERT(err == 0, "pthread_attr_destroy - error"); 99 100 func = nullptr; 101 funcData = nullptr; 102 103 if (stackBase) 104 { 105 free(stackBase); 106 stackBase = nullptr; 107 } 108 stackSize = 0; 109 110 isStarted = false; 111 } 112 113 bool IsCurrentThread() const 114 { 115 if(!isStarted) 116 { 117 return false; 118 } 119 120 pthread_t callThread = pthread_self(); 121 if (pthread_equal(callThread, thread)) 122 { 123 return true; 124 } 125 return false; 126 } 127 128 static int GetNumberOfHardwareThreads() 129 { 130 long numberOfProcessors = sysconf( _SC_NPROCESSORS_ONLN ); 131 return (int)numberOfProcessors; 132 } 133 134 static void Sleep(uint32 milliseconds) 135 { 136 struct timespec req = {0}; 137 time_t sec = (int)(milliseconds/1000); 138 milliseconds = milliseconds - (sec*1000); 139 req.tv_sec = sec; 140 req.tv_nsec = milliseconds * 1000000L; 141 while (nanosleep(&req,&req) == -1 ) 142 { 143 continue; 144 } 145 } 146 147 }; 148 149 150 } 151 152 153