1 // ==============================================================
2 // This file is part of Glest Shared Library (www.glest.org)
3 //
4 // Copyright (C) 2009-2010 Titus Tscharntke (info@titusgames.de) and
5 // Mark Vejvoda (mark_vejvoda@hotmail.com)
6 //
7 // You can redistribute this code and/or modify it under
8 // the terms of the GNU General Public License as published
9 // by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version
11 // ==============================================================
12
13 #include "base_thread.h"
14 #include "platform_common.h"
15 #include "util.h"
16 #include "conversion.h"
17 #include "platform_util.h"
18 #include <time.h>
19
20 using namespace Shared::Util;
21
22 namespace Shared { namespace PlatformCommon {
23
24 Mutex BaseThread::mutexMasterThreadList;
25 std::map<void *,int> BaseThread::masterThreadList;
26
BaseThread()27 BaseThread::BaseThread() : Thread(),
28 mutexRunning(new Mutex(CODE_AT_LINE)),
29 mutexQuit(new Mutex(CODE_AT_LINE)),
30 mutexBeginExecution(new Mutex(CODE_AT_LINE)),
31 mutexDeleteSelfOnExecutionDone(new Mutex(CODE_AT_LINE)),
32 mutexThreadObjectAccessor(new Mutex(CODE_AT_LINE)),
33 mutexThreadOwnerValid(new Mutex(CODE_AT_LINE)),
34 mutexExecutingTask(new Mutex(CODE_AT_LINE)),
35 mutexStarted(new Mutex(CODE_AT_LINE)),
36 ptr(NULL), genericData(NULL) {
37
38 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
39
40 ptr = this;
41 MutexSafeWrapper safeMutexMasterList(&mutexMasterThreadList);
42 masterThreadList[ptr]++;
43 safeMutexMasterList.ReleaseLock();
44
45 uniqueID = "base_thread";
46
47 setQuitStatus(false);
48 setRunningStatus(false);
49 setStarted(false);
50 setHasBeginExecution(false);
51 setExecutingTask(false);
52 setDeleteSelfOnExecutionDone(false);
53 setThreadOwnerValid(true);
54
55 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
56 }
57
getMutexThreadObjectAccessor()58 Mutex * BaseThread::getMutexThreadObjectAccessor() {
59 return mutexThreadObjectAccessor;
60 }
61
~BaseThread()62 BaseThread::~BaseThread() {
63
64 //printf("In ~BaseThread Line: %d uniqueID [%s]\n",__LINE__,uniqueID.c_str());
65 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
66
67 //BaseThread *base_thread = dynamic_cast<BaseThread *>(this);
68 if(this->getStarted() == false) {
69 time_t elapsed = time(NULL);
70 for(;this->getStarted() == false &&
71 difftime((long int)time(NULL),elapsed) <= 3;) {
72 sleep(5);
73 }
74 }
75
76 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
77 bool ret = shutdownAndWait();
78 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s] ret [%d] END\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str(),ret);
79
80 //printf("In ~BaseThread Line: %d uniqueID [%s]\n",__LINE__,uniqueID.c_str());
81
82 MutexSafeWrapper safeMutexMasterList(&mutexMasterThreadList);
83
84 //printf("In ~BaseThread Line: %d uniqueID [%s]\n",__LINE__,uniqueID.c_str());
85
86 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s] ret [%d] END\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str(),ret);
87
88 //printf("In ~BaseThread Line: %d uniqueID [%s]\n",__LINE__,uniqueID.c_str());
89
90 if(masterThreadList.find(this) == masterThreadList.end()) {
91 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s] ret [%d] END\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str(),ret);
92
93 char szBuf[8096]="";
94 snprintf(szBuf,8096,"invalid thread delete for ptr: %p",this);
95 throw megaglest_runtime_error(szBuf);
96 }
97 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s] ret [%d] END\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str(),ret);
98
99 //printf("In ~BaseThread Line: %d uniqueID [%s]\n",__LINE__,uniqueID.c_str());
100
101 masterThreadList[this]--;
102 if(masterThreadList[this] <= 0) {
103 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s] ret [%d] END\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str(),ret);
104 masterThreadList.erase(this);
105 }
106
107 //printf("In ~BaseThread Line: %d uniqueID [%s]\n",__LINE__,uniqueID.c_str());
108
109 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s] ret [%d] END\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str(),ret);
110
111 safeMutexMasterList.ReleaseLock();
112
113 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s] ret [%d] END\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str(),ret);
114
115
116 delete mutexRunning;
117 mutexRunning = NULL;
118 delete mutexQuit;
119 mutexQuit = NULL;
120 delete mutexBeginExecution;
121 mutexBeginExecution = NULL;
122 delete mutexDeleteSelfOnExecutionDone;
123 mutexDeleteSelfOnExecutionDone = NULL;
124 delete mutexThreadObjectAccessor;
125 mutexThreadObjectAccessor = NULL;
126 delete mutexThreadOwnerValid;
127 mutexThreadOwnerValid = NULL;
128 delete mutexExecutingTask;
129 mutexExecutingTask = NULL;
130 delete mutexStarted;
131 mutexStarted = NULL;
132
133 //printf("In ~BaseThread Line: %d uniqueID [%s] [%p]\n",__LINE__,uniqueID.c_str(),this);
134 }
135
getStarted()136 bool BaseThread::getStarted() {
137 static string mutexOwnerId = CODE_AT_LINE;
138 MutexSafeWrapper safeMutex(mutexStarted,mutexOwnerId);
139 mutexStarted->setOwnerId(mutexOwnerId);
140 bool retval = started;
141 safeMutex.ReleaseLock();
142
143 return retval;
144 }
145
setStarted(bool value)146 void BaseThread::setStarted(bool value) {
147 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
148
149 static string mutexOwnerId = CODE_AT_LINE;
150 MutexSafeWrapper safeMutex(mutexStarted,mutexOwnerId);
151 mutexStarted->setOwnerId(mutexOwnerId);
152 started = value;
153 safeMutex.ReleaseLock();
154
155 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
156 }
157
isThreadDeleted(void * ptr)158 bool BaseThread::isThreadDeleted(void *ptr) {
159 bool result = false;
160 MutexSafeWrapper safeMutexMasterList(&mutexMasterThreadList);
161 if(masterThreadList.find(ptr) != masterThreadList.end()) {
162 result = (masterThreadList[ptr] <= 0);
163 }
164 safeMutexMasterList.ReleaseLock();
165 return result;
166 }
167
getMutexThreadOwnerValid()168 Mutex * BaseThread::getMutexThreadOwnerValid() {
169 if(getThreadOwnerValid() == true) {
170 return mutexThreadOwnerValid;
171 }
172 return NULL;
173 }
174
setThreadOwnerValid(bool value)175 void BaseThread::setThreadOwnerValid(bool value) {
176 static string mutexOwnerId = CODE_AT_LINE;
177 MutexSafeWrapper safeMutex(mutexThreadOwnerValid,mutexOwnerId);
178 mutexThreadOwnerValid->setOwnerId(mutexOwnerId);
179 threadOwnerValid = value;
180 safeMutex.ReleaseLock();
181 }
182
getThreadOwnerValid()183 bool BaseThread::getThreadOwnerValid() {
184 //bool ret = false;
185 static string mutexOwnerId = CODE_AT_LINE;
186 MutexSafeWrapper safeMutex(mutexThreadOwnerValid,mutexOwnerId);
187 //mutexThreadOwnerValid.setOwnerId(mutexOwnerId);
188 bool ret = threadOwnerValid;
189 safeMutex.ReleaseLock();
190
191 return ret;
192 }
193
signalQuit()194 void BaseThread::signalQuit() {
195 setQuitStatus(true);
196 }
197
setQuitStatus(bool value)198 void BaseThread::setQuitStatus(bool value) {
199 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
200
201 static string mutexOwnerId = CODE_AT_LINE;
202 MutexSafeWrapper safeMutex(mutexQuit,mutexOwnerId);
203 mutexQuit->setOwnerId(mutexOwnerId);
204 quit = value;
205 safeMutex.ReleaseLock();
206
207 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
208 }
209
getQuitStatus()210 bool BaseThread::getQuitStatus() {
211 //bool retval = false;
212 static string mutexOwnerId = CODE_AT_LINE;
213 MutexSafeWrapper safeMutex(mutexQuit,mutexOwnerId);
214 //mutexQuit.setOwnerId(mutexOwnerId);
215 bool retval = quit;
216 safeMutex.ReleaseLock();
217
218 return retval;
219 }
220
getHasBeginExecution()221 bool BaseThread::getHasBeginExecution() {
222 //bool retval = false;
223 static string mutexOwnerId = CODE_AT_LINE;
224 MutexSafeWrapper safeMutex(mutexBeginExecution,mutexOwnerId);
225 //mutexBeginExecution.setOwnerId(mutexOwnerId);
226 bool retval = hasBeginExecution;
227 safeMutex.ReleaseLock();
228
229 return retval;
230 }
231
setHasBeginExecution(bool value)232 void BaseThread::setHasBeginExecution(bool value) {
233 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
234
235 static string mutexOwnerId = CODE_AT_LINE;
236 MutexSafeWrapper safeMutex(mutexBeginExecution,mutexOwnerId);
237 mutexBeginExecution->setOwnerId(mutexOwnerId);
238 hasBeginExecution = value;
239 safeMutex.ReleaseLock();
240
241 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
242 }
243
getRunningStatus()244 bool BaseThread::getRunningStatus() {
245 //bool retval = false;
246
247 static string mutexOwnerId = CODE_AT_LINE;
248 MutexSafeWrapper safeMutex(mutexRunning,mutexOwnerId);
249 bool retval = running;
250 safeMutex.ReleaseLock();
251
252 if(retval == false) {
253 retval = !getHasBeginExecution();
254 }
255
256 return retval;
257 }
258
setRunningStatus(bool value)259 void BaseThread::setRunningStatus(bool value) {
260 static string mutexOwnerId = CODE_AT_LINE;
261 MutexSafeWrapper safeMutex(mutexRunning,mutexOwnerId);
262 mutexRunning->setOwnerId(mutexOwnerId);
263 running = value;
264 if(value == true) {
265 setHasBeginExecution(true);
266 }
267 safeMutex.ReleaseLock();
268 }
269
setExecutingTask(bool value)270 void BaseThread::setExecutingTask(bool value) {
271 static string mutexOwnerId = CODE_AT_LINE;
272 MutexSafeWrapper safeMutex(mutexExecutingTask,mutexOwnerId);
273 mutexExecutingTask->setOwnerId(mutexOwnerId);
274 executingTask = value;
275 safeMutex.ReleaseLock();
276 }
277
getExecutingTask()278 bool BaseThread::getExecutingTask() {
279 //bool retval = false;
280 static string mutexOwnerId = CODE_AT_LINE;
281 MutexSafeWrapper safeMutex(mutexExecutingTask,mutexOwnerId);
282 bool retval = executingTask;
283 safeMutex.ReleaseLock();
284
285 return retval;
286 }
287
getDeleteSelfOnExecutionDone()288 bool BaseThread::getDeleteSelfOnExecutionDone() {
289 //bool retval = false;
290 static string mutexOwnerId = CODE_AT_LINE;
291 MutexSafeWrapper safeMutex(mutexDeleteSelfOnExecutionDone,mutexOwnerId);
292 bool retval = deleteSelfOnExecutionDone;
293 safeMutex.ReleaseLock();
294
295 return retval;
296 }
297
setDeleteSelfOnExecutionDone(bool value)298 void BaseThread::setDeleteSelfOnExecutionDone(bool value) {
299 static string mutexOwnerId = CODE_AT_LINE;
300 MutexSafeWrapper safeMutex(mutexDeleteSelfOnExecutionDone,mutexOwnerId);
301 mutexDeleteSelfOnExecutionDone->setOwnerId(mutexOwnerId);
302 deleteSelfOnExecutionDone = value;
303 }
304
deleteSelfIfRequired()305 void BaseThread::deleteSelfIfRequired() {
306 if(getDeleteSelfOnExecutionDone() == true) {
307 if(isThreadDeleted(this->ptr) == false) {
308 this->setDeleteAfterExecute(true);
309 }
310 return;
311 }
312 }
313
canShutdown(bool deleteSelfIfShutdownDelayed)314 bool BaseThread::canShutdown(bool deleteSelfIfShutdownDelayed) {
315 return true;
316 }
317
shutdownAndWait(BaseThread * pThread)318 bool BaseThread::shutdownAndWait(BaseThread *pThread) {
319 bool ret = false;
320 if(pThread != NULL) {
321 ret = pThread->shutdownAndWait();
322 }
323
324 return ret;
325 }
326
shutdownAndWait()327 bool BaseThread::shutdownAndWait() {
328 bool ret = true;
329 BaseThread *pThread = this;
330 //string uniqueID = (pThread != NULL ? pThread->getUniqueID() : "?");
331 string uniqueID = pThread->getUniqueID();
332 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
333
334 //if(pThread != NULL) {
335 if(pThread->getRunningStatus() == true) {
336 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
337
338 pThread->signalQuit();
339 sleep(0);
340 ret = false;
341
342 int maxWaitSeconds = 5;
343 if(pThread->canShutdown() == false) {
344 maxWaitSeconds = 2;
345 }
346
347 for( time_t elapsed = time(NULL); difftime(time(NULL),elapsed) <= maxWaitSeconds; ) {
348 if(pThread->getRunningStatus() == false) {
349 ret = true;
350 break;
351 }
352
353 sleep(0);
354 }
355 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
356 sleep(0);
357 }
358 //}
359 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s] ret [%d] END\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str(),ret);
360 return ret;
361 }
362
363 }}//end namespace
364