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