364 lines
13 KiB
C++
364 lines
13 KiB
C++
// ==============================================================
|
|
// This file is part of Glest Shared Library (www.glest.org)
|
|
//
|
|
// Copyright (C) 2009-2010 Titus Tscharntke (info@titusgames.de) and
|
|
// Mark Vejvoda (mark_vejvoda@hotmail.com)
|
|
//
|
|
// You can redistribute this code and/or modify it under
|
|
// the terms of the GNU General Public License as published
|
|
// by the Free Software Foundation; either version 2 of the
|
|
// License, or (at your option) any later version
|
|
// ==============================================================
|
|
|
|
#include "base_thread.h"
|
|
#include "platform_common.h"
|
|
#include "util.h"
|
|
#include "conversion.h"
|
|
#include "platform_util.h"
|
|
#include <time.h>
|
|
|
|
using namespace Shared::Util;
|
|
|
|
namespace Shared { namespace PlatformCommon {
|
|
|
|
Mutex BaseThread::mutexMasterThreadList;
|
|
std::map<void *,int> BaseThread::masterThreadList;
|
|
|
|
BaseThread::BaseThread() : Thread(),
|
|
mutexRunning(new Mutex(CODE_AT_LINE)),
|
|
mutexQuit(new Mutex(CODE_AT_LINE)),
|
|
mutexBeginExecution(new Mutex(CODE_AT_LINE)),
|
|
mutexDeleteSelfOnExecutionDone(new Mutex(CODE_AT_LINE)),
|
|
mutexThreadObjectAccessor(new Mutex(CODE_AT_LINE)),
|
|
mutexThreadOwnerValid(new Mutex(CODE_AT_LINE)),
|
|
mutexExecutingTask(new Mutex(CODE_AT_LINE)),
|
|
mutexStarted(new Mutex(CODE_AT_LINE)),
|
|
ptr(NULL), genericData(NULL) {
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
ptr = this;
|
|
MutexSafeWrapper safeMutexMasterList(&mutexMasterThreadList);
|
|
masterThreadList[ptr]++;
|
|
safeMutexMasterList.ReleaseLock();
|
|
|
|
uniqueID = "base_thread";
|
|
|
|
setQuitStatus(false);
|
|
setRunningStatus(false);
|
|
setStarted(false);
|
|
setHasBeginExecution(false);
|
|
setExecutingTask(false);
|
|
setDeleteSelfOnExecutionDone(false);
|
|
setThreadOwnerValid(true);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
}
|
|
|
|
Mutex * BaseThread::getMutexThreadObjectAccessor() {
|
|
return mutexThreadObjectAccessor;
|
|
}
|
|
|
|
BaseThread::~BaseThread() {
|
|
|
|
//printf("In ~BaseThread Line: %d uniqueID [%s]\n",__LINE__,uniqueID.c_str());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
|
|
|
|
//BaseThread *base_thread = dynamic_cast<BaseThread *>(this);
|
|
if(this->getStarted() == false) {
|
|
time_t elapsed = time(NULL);
|
|
for(;this->getStarted() == false &&
|
|
difftime((long int)time(NULL),elapsed) <= 3;) {
|
|
sleep(5);
|
|
}
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
|
|
bool ret = shutdownAndWait();
|
|
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);
|
|
|
|
//printf("In ~BaseThread Line: %d uniqueID [%s]\n",__LINE__,uniqueID.c_str());
|
|
|
|
MutexSafeWrapper safeMutexMasterList(&mutexMasterThreadList);
|
|
|
|
//printf("In ~BaseThread Line: %d uniqueID [%s]\n",__LINE__,uniqueID.c_str());
|
|
|
|
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);
|
|
|
|
//printf("In ~BaseThread Line: %d uniqueID [%s]\n",__LINE__,uniqueID.c_str());
|
|
|
|
if(masterThreadList.find(this) == masterThreadList.end()) {
|
|
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);
|
|
|
|
char szBuf[8096]="";
|
|
snprintf(szBuf,8096,"invalid thread delete for ptr: %p",this);
|
|
throw megaglest_runtime_error(szBuf);
|
|
}
|
|
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);
|
|
|
|
//printf("In ~BaseThread Line: %d uniqueID [%s]\n",__LINE__,uniqueID.c_str());
|
|
|
|
masterThreadList[this]--;
|
|
if(masterThreadList[this] <= 0) {
|
|
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);
|
|
masterThreadList.erase(this);
|
|
}
|
|
|
|
//printf("In ~BaseThread Line: %d uniqueID [%s]\n",__LINE__,uniqueID.c_str());
|
|
|
|
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);
|
|
|
|
safeMutexMasterList.ReleaseLock();
|
|
|
|
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);
|
|
|
|
|
|
delete mutexRunning;
|
|
mutexRunning = NULL;
|
|
delete mutexQuit;
|
|
mutexQuit = NULL;
|
|
delete mutexBeginExecution;
|
|
mutexBeginExecution = NULL;
|
|
delete mutexDeleteSelfOnExecutionDone;
|
|
mutexDeleteSelfOnExecutionDone = NULL;
|
|
delete mutexThreadObjectAccessor;
|
|
mutexThreadObjectAccessor = NULL;
|
|
delete mutexThreadOwnerValid;
|
|
mutexThreadOwnerValid = NULL;
|
|
delete mutexExecutingTask;
|
|
mutexExecutingTask = NULL;
|
|
delete mutexStarted;
|
|
mutexStarted = NULL;
|
|
|
|
//printf("In ~BaseThread Line: %d uniqueID [%s] [%p]\n",__LINE__,uniqueID.c_str(),this);
|
|
}
|
|
|
|
bool BaseThread::getStarted() {
|
|
static string mutexOwnerId = CODE_AT_LINE;
|
|
MutexSafeWrapper safeMutex(mutexStarted,mutexOwnerId);
|
|
mutexStarted->setOwnerId(mutexOwnerId);
|
|
bool retval = started;
|
|
safeMutex.ReleaseLock();
|
|
|
|
return retval;
|
|
}
|
|
|
|
void BaseThread::setStarted(bool value) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
|
|
|
|
static string mutexOwnerId = CODE_AT_LINE;
|
|
MutexSafeWrapper safeMutex(mutexStarted,mutexOwnerId);
|
|
mutexStarted->setOwnerId(mutexOwnerId);
|
|
started = value;
|
|
safeMutex.ReleaseLock();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
|
|
}
|
|
|
|
bool BaseThread::isThreadDeleted(void *ptr) {
|
|
bool result = false;
|
|
MutexSafeWrapper safeMutexMasterList(&mutexMasterThreadList);
|
|
if(masterThreadList.find(ptr) != masterThreadList.end()) {
|
|
result = (masterThreadList[ptr] <= 0);
|
|
}
|
|
safeMutexMasterList.ReleaseLock();
|
|
return result;
|
|
}
|
|
|
|
Mutex * BaseThread::getMutexThreadOwnerValid() {
|
|
if(getThreadOwnerValid() == true) {
|
|
return mutexThreadOwnerValid;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void BaseThread::setThreadOwnerValid(bool value) {
|
|
static string mutexOwnerId = CODE_AT_LINE;
|
|
MutexSafeWrapper safeMutex(mutexThreadOwnerValid,mutexOwnerId);
|
|
mutexThreadOwnerValid->setOwnerId(mutexOwnerId);
|
|
threadOwnerValid = value;
|
|
safeMutex.ReleaseLock();
|
|
}
|
|
|
|
bool BaseThread::getThreadOwnerValid() {
|
|
//bool ret = false;
|
|
static string mutexOwnerId = CODE_AT_LINE;
|
|
MutexSafeWrapper safeMutex(mutexThreadOwnerValid,mutexOwnerId);
|
|
//mutexThreadOwnerValid.setOwnerId(mutexOwnerId);
|
|
bool ret = threadOwnerValid;
|
|
safeMutex.ReleaseLock();
|
|
|
|
return ret;
|
|
}
|
|
|
|
void BaseThread::signalQuit() {
|
|
setQuitStatus(true);
|
|
}
|
|
|
|
void BaseThread::setQuitStatus(bool value) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
|
|
|
|
static string mutexOwnerId = CODE_AT_LINE;
|
|
MutexSafeWrapper safeMutex(mutexQuit,mutexOwnerId);
|
|
mutexQuit->setOwnerId(mutexOwnerId);
|
|
quit = value;
|
|
safeMutex.ReleaseLock();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
|
|
}
|
|
|
|
bool BaseThread::getQuitStatus() {
|
|
//bool retval = false;
|
|
static string mutexOwnerId = CODE_AT_LINE;
|
|
MutexSafeWrapper safeMutex(mutexQuit,mutexOwnerId);
|
|
//mutexQuit.setOwnerId(mutexOwnerId);
|
|
bool retval = quit;
|
|
safeMutex.ReleaseLock();
|
|
|
|
return retval;
|
|
}
|
|
|
|
bool BaseThread::getHasBeginExecution() {
|
|
//bool retval = false;
|
|
static string mutexOwnerId = CODE_AT_LINE;
|
|
MutexSafeWrapper safeMutex(mutexBeginExecution,mutexOwnerId);
|
|
//mutexBeginExecution.setOwnerId(mutexOwnerId);
|
|
bool retval = hasBeginExecution;
|
|
safeMutex.ReleaseLock();
|
|
|
|
return retval;
|
|
}
|
|
|
|
void BaseThread::setHasBeginExecution(bool value) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
|
|
|
|
static string mutexOwnerId = CODE_AT_LINE;
|
|
MutexSafeWrapper safeMutex(mutexBeginExecution,mutexOwnerId);
|
|
mutexBeginExecution->setOwnerId(mutexOwnerId);
|
|
hasBeginExecution = value;
|
|
safeMutex.ReleaseLock();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
|
|
}
|
|
|
|
bool BaseThread::getRunningStatus() {
|
|
//bool retval = false;
|
|
|
|
static string mutexOwnerId = CODE_AT_LINE;
|
|
MutexSafeWrapper safeMutex(mutexRunning,mutexOwnerId);
|
|
bool retval = running;
|
|
safeMutex.ReleaseLock();
|
|
|
|
if(retval == false) {
|
|
retval = !getHasBeginExecution();
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
void BaseThread::setRunningStatus(bool value) {
|
|
static string mutexOwnerId = CODE_AT_LINE;
|
|
MutexSafeWrapper safeMutex(mutexRunning,mutexOwnerId);
|
|
mutexRunning->setOwnerId(mutexOwnerId);
|
|
running = value;
|
|
if(value == true) {
|
|
setHasBeginExecution(true);
|
|
}
|
|
safeMutex.ReleaseLock();
|
|
}
|
|
|
|
void BaseThread::setExecutingTask(bool value) {
|
|
static string mutexOwnerId = CODE_AT_LINE;
|
|
MutexSafeWrapper safeMutex(mutexExecutingTask,mutexOwnerId);
|
|
mutexExecutingTask->setOwnerId(mutexOwnerId);
|
|
executingTask = value;
|
|
safeMutex.ReleaseLock();
|
|
}
|
|
|
|
bool BaseThread::getExecutingTask() {
|
|
//bool retval = false;
|
|
static string mutexOwnerId = CODE_AT_LINE;
|
|
MutexSafeWrapper safeMutex(mutexExecutingTask,mutexOwnerId);
|
|
bool retval = executingTask;
|
|
safeMutex.ReleaseLock();
|
|
|
|
return retval;
|
|
}
|
|
|
|
bool BaseThread::getDeleteSelfOnExecutionDone() {
|
|
//bool retval = false;
|
|
static string mutexOwnerId = CODE_AT_LINE;
|
|
MutexSafeWrapper safeMutex(mutexDeleteSelfOnExecutionDone,mutexOwnerId);
|
|
bool retval = deleteSelfOnExecutionDone;
|
|
safeMutex.ReleaseLock();
|
|
|
|
return retval;
|
|
}
|
|
|
|
void BaseThread::setDeleteSelfOnExecutionDone(bool value) {
|
|
static string mutexOwnerId = CODE_AT_LINE;
|
|
MutexSafeWrapper safeMutex(mutexDeleteSelfOnExecutionDone,mutexOwnerId);
|
|
mutexDeleteSelfOnExecutionDone->setOwnerId(mutexOwnerId);
|
|
deleteSelfOnExecutionDone = value;
|
|
}
|
|
|
|
void BaseThread::deleteSelfIfRequired() {
|
|
if(getDeleteSelfOnExecutionDone() == true) {
|
|
if(isThreadDeleted(this->ptr) == false) {
|
|
this->setDeleteAfterExecute(true);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
bool BaseThread::canShutdown(bool deleteSelfIfShutdownDelayed) {
|
|
return true;
|
|
}
|
|
|
|
bool BaseThread::shutdownAndWait(BaseThread *pThread) {
|
|
bool ret = false;
|
|
if(pThread != NULL) {
|
|
ret = pThread->shutdownAndWait();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool BaseThread::shutdownAndWait() {
|
|
bool ret = true;
|
|
BaseThread *pThread = this;
|
|
//string uniqueID = (pThread != NULL ? pThread->getUniqueID() : "?");
|
|
string uniqueID = pThread->getUniqueID();
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
|
|
|
|
//if(pThread != NULL) {
|
|
if(pThread->getRunningStatus() == true) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
|
|
|
|
pThread->signalQuit();
|
|
sleep(0);
|
|
ret = false;
|
|
|
|
int maxWaitSeconds = 5;
|
|
if(pThread->canShutdown() == false) {
|
|
maxWaitSeconds = 2;
|
|
}
|
|
|
|
for( time_t elapsed = time(NULL); difftime(time(NULL),elapsed) <= maxWaitSeconds; ) {
|
|
if(pThread->getRunningStatus() == false) {
|
|
ret = true;
|
|
break;
|
|
}
|
|
|
|
sleep(0);
|
|
}
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
|
|
sleep(0);
|
|
}
|
|
//}
|
|
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);
|
|
return ret;
|
|
}
|
|
|
|
}}//end namespace
|