- attempt to add crude thread state tracking in thread class and force thread to die if it appears to be stuck (and output to console)

This commit is contained in:
SoftCoder 2013-12-30 21:23:49 -08:00
parent e0aa65402d
commit b109b26664
2 changed files with 67 additions and 5 deletions

View File

@ -46,6 +46,17 @@ namespace Shared { namespace Platform {
class Mutex; class Mutex;
//class uint32; //class uint32;
enum ThreadState {
thrsNew,
thrsStarting,
thrsExecuteStart,
thrsExecuting,
thrsExecuted,
thrsExecuteAutoClean,
thrsExecuteComplete
};
class Thread { class Thread {
public: public:
enum Priority { enum Priority {
@ -60,6 +71,7 @@ private:
SDL_Thread* thread; SDL_Thread* thread;
//std::auto_ptr<Mutex> mutexthreadAccessor; //std::auto_ptr<Mutex> mutexthreadAccessor;
Mutex *mutexthreadAccessor; Mutex *mutexthreadAccessor;
ThreadState currentState;
bool threadObjectValid(); bool threadObjectValid();
bool deleteAfterExecute; bool deleteAfterExecute;
@ -71,6 +83,7 @@ protected:
void addThreadToList(); void addThreadToList();
void removeThreadFromList(); void removeThreadFromList();
void queueAutoCleanThread(); void queueAutoCleanThread();
bool isThreadExecuteCompleteStatus();
public: public:
Thread(); Thread();

View File

@ -128,7 +128,9 @@ public:
// ===================================== // =====================================
// Threads // Threads
// ===================================== // =====================================
Thread::Thread() : thread(NULL), mutexthreadAccessor(new Mutex(CODE_AT_LINE)), deleteAfterExecute(false) { Thread::Thread() : thread(NULL),
mutexthreadAccessor(new Mutex(CODE_AT_LINE)),
deleteAfterExecute(false), currentState(thrsNew) {
addThreadToList(); addThreadToList();
} }
@ -184,15 +186,43 @@ void Thread::shutdownThreads() {
} }
} }
bool Thread::isThreadExecuteCompleteStatus() {
MutexSafeWrapper safeMutex(mutexthreadAccessor);
return (currentState == thrsExecuteComplete);
}
Thread::~Thread() { Thread::~Thread() {
if(Thread::getEnableVerboseMode()) printf("In ~Thread Line: %d [%p] thread = %p\n",__LINE__,this,thread); if(Thread::getEnableVerboseMode()) printf("In ~Thread Line: %d [%p] thread = %p\n",__LINE__,this,thread);
MutexSafeWrapper safeMutex(mutexthreadAccessor); MutexSafeWrapper safeMutex(mutexthreadAccessor);
if(thread != NULL) { if(thread != NULL) {
SDL_WaitThread(thread, NULL);
safeMutex.ReleaseLock();
if(isThreadExecuteCompleteStatus() == false) {
printf("**WARNING** thread destructor delayed, trying to exit...\n");
time_t elapsed = time(NULL);
for(;difftime((long int)time(NULL),elapsed) <= 5;) {
sleep(0);
if(isThreadExecuteCompleteStatus() == true) {
break;
}
}
}
if(isThreadExecuteCompleteStatus() == false) {
printf("**WARNING** thread destructor will KILL thread [%p]...\n",thread);
SDL_KillThread(thread);
}
else {
SDL_WaitThread(thread, NULL);
}
thread = NULL; thread = NULL;
} }
safeMutex.ReleaseLock(); else {
safeMutex.ReleaseLock();
}
if(Thread::getEnableVerboseMode()) printf("In ~Thread Line: %d [%p] thread = %p\n",__LINE__,this,thread); if(Thread::getEnableVerboseMode()) printf("In ~Thread Line: %d [%p] thread = %p\n",__LINE__,this,thread);
@ -213,12 +243,12 @@ std::vector<Thread *> Thread::getThreadList() {
void Thread::start() { void Thread::start() {
MutexSafeWrapper safeMutex(mutexthreadAccessor); MutexSafeWrapper safeMutex(mutexthreadAccessor);
currentState = thrsStarting;
BaseThread *base_thread = dynamic_cast<BaseThread *>(this); BaseThread *base_thread = dynamic_cast<BaseThread *>(this);
if(base_thread) base_thread->setStarted(true); if(base_thread) base_thread->setStarted(true);
thread = SDL_CreateThread(beginExecution, this); thread = SDL_CreateThread(beginExecution, this);
//assert(thread != NULL);
if(thread == NULL) { if(thread == NULL) {
if(base_thread) base_thread->setStarted(false); if(base_thread) base_thread->setStarted(false);
@ -241,28 +271,47 @@ void Thread::setPriority(Thread::Priority threadPriority) {
int Thread::beginExecution(void* data) { int Thread::beginExecution(void* data) {
Thread* thread = static_cast<Thread*> (data); Thread* thread = static_cast<Thread*> (data);
assert(thread != NULL);
if(thread == NULL) { if(thread == NULL) {
char szBuf[8096]=""; char szBuf[8096]="";
snprintf(szBuf,8095,"In [%s::%s Line: %d] thread == NULL",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); snprintf(szBuf,8095,"In [%s::%s Line: %d] thread == NULL",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
printf("%s",szBuf);
throw megaglest_runtime_error(szBuf); throw megaglest_runtime_error(szBuf);
} }
MutexSafeWrapper safeMutex(thread->mutexthreadAccessor);
thread->currentState = thrsExecuteStart;
safeMutex.ReleaseLock(true);
BaseThread *base_thread = dynamic_cast<BaseThread *>(thread); BaseThread *base_thread = dynamic_cast<BaseThread *>(thread);
//ThreadGarbageCollector *garbage_collector = dynamic_cast<ThreadGarbageCollector *>(thread); //ThreadGarbageCollector *garbage_collector = dynamic_cast<ThreadGarbageCollector *>(thread);
if(Thread::getEnableVerboseMode()) printf("In Thread::execute Line: %d thread = %p base_thread = %p [%s]\n",__LINE__,thread,base_thread,(base_thread != NULL ? base_thread->getUniqueID().c_str() : "n/a")); if(Thread::getEnableVerboseMode()) printf("In Thread::execute Line: %d thread = %p base_thread = %p [%s]\n",__LINE__,thread,base_thread,(base_thread != NULL ? base_thread->getUniqueID().c_str() : "n/a"));
if(thread->threadObjectValid() == true) { if(thread->threadObjectValid() == true) {
safeMutex.Lock();
thread->currentState = thrsExecuting;
safeMutex.ReleaseLock(true);
thread->execute(); thread->execute();
safeMutex.Lock();
thread->currentState = thrsExecuted;
safeMutex.ReleaseLock(true);
} }
if(Thread::getEnableVerboseMode()) printf("In Thread::execute Line: %d thread = %p base_thread = %p [%s]\n",__LINE__,thread,base_thread,(base_thread != NULL ? base_thread->getUniqueID().c_str() : "n/a")); if(Thread::getEnableVerboseMode()) printf("In Thread::execute Line: %d thread = %p base_thread = %p [%s]\n",__LINE__,thread,base_thread,(base_thread != NULL ? base_thread->getUniqueID().c_str() : "n/a"));
if(thread->threadObjectValid() == true) { if(thread->threadObjectValid() == true) {
safeMutex.Lock();
thread->currentState = thrsExecuteAutoClean;
safeMutex.ReleaseLock(true);
thread->queueAutoCleanThread(); thread->queueAutoCleanThread();
} }
if(Thread::getEnableVerboseMode()) printf("In Thread::execute Line: %d\n",__LINE__); if(Thread::getEnableVerboseMode()) printf("In Thread::execute Line: %d\n",__LINE__);
safeMutex.Lock();
thread->currentState = thrsExecuteComplete;
safeMutex.ReleaseLock();
return 0; return 0;
} }