MegaGlest/source/shared_lib/sources/platform/common/simple_threads.cpp

792 lines
37 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 "simple_threads.h"
#include "util.h"
#include "platform_common.h"
#include <algorithm>
#include "conversion.h"
#include "platform_util.h"
#include "cache_manager.h"
#include "leak_dumper.h"
using namespace std;
using namespace Shared::Util;
using namespace Shared::PlatformCommon;
namespace Shared { namespace PlatformCommon {
const static int MAX_FileCRCPreCacheThread_WORKER_THREADS = 3;
const static double PAUSE_SECONDS_BETWEEN_WORKERS = 15;
string FileCRCPreCacheThread::preCacheThreadCacheLookupKey = "";
FileCRCPreCacheThread::FileCRCPreCacheThread() : BaseThread(),
mutexPauseForGame(new Mutex(CODE_AT_LINE)) {
techDataPaths.clear();
workerThreadTechPaths.clear();
preCacheWorkerThreadList.clear();
processTechCB = NULL;
pauseForGame = false;
uniqueID = "FileCRCPreCacheThread";
}
FileCRCPreCacheThread::FileCRCPreCacheThread(vector<string> techDataPaths,
vector<string> workerThreadTechPaths,
FileCRCPreCacheThreadCallbackInterface *processTechCB) :
mutexPauseForGame(new Mutex(CODE_AT_LINE)) {
this->techDataPaths = techDataPaths;
this->workerThreadTechPaths = workerThreadTechPaths;
preCacheWorkerThreadList.clear();
this->processTechCB = processTechCB;
pauseForGame = false;
uniqueID = "FileCRCPreCacheThread";
}
FileCRCPreCacheThread::~FileCRCPreCacheThread() {
bool threadControllerMode = (workerThreadTechPaths.size() == 0);
FileCRCPreCacheThread * &preCacheCRCThreadPtr = CacheManager::getCachedItem< FileCRCPreCacheThread * >(preCacheThreadCacheLookupKey);
if(preCacheCRCThreadPtr != NULL && threadControllerMode == true) {
preCacheCRCThreadPtr = NULL;
}
delete mutexPauseForGame;
mutexPauseForGame = NULL;
}
void FileCRCPreCacheThread::setPauseForGame(bool pauseForGame) {
static string mutexOwnerId = CODE_AT_LINE;
MutexSafeWrapper safeMutex(mutexPauseForGame,mutexOwnerId);
this->pauseForGame = pauseForGame;
for(unsigned int index = 0; index < preCacheWorkerThreadList.size(); ++index) {
FileCRCPreCacheThread *worker = preCacheWorkerThreadList[index];
if(worker != NULL) {
worker->setPauseForGame(this->pauseForGame);
}
}
}
bool FileCRCPreCacheThread::getPauseForGame() {
static string mutexOwnerId = CODE_AT_LINE;
MutexSafeWrapper safeMutex(mutexPauseForGame,mutexOwnerId);
return this->pauseForGame;
}
bool FileCRCPreCacheThread::canShutdown(bool deleteSelfIfShutdownDelayed) {
bool ret = (getExecutingTask() == false);
if(ret == false && deleteSelfIfShutdownDelayed == true) {
setDeleteSelfOnExecutionDone(deleteSelfIfShutdownDelayed);
deleteSelfIfRequired();
signalQuit();
}
return ret;
}
void FileCRCPreCacheThread::execute() {
{
RunningStatusSafeWrapper runningStatus(this);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
if(getQuitStatus() == true) {
deleteSelfIfRequired();
return;
}
bool threadControllerMode = (workerThreadTechPaths.size() == 0);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("FILE CRC PreCache thread is running threadControllerMode = %d\n",threadControllerMode);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"FILE CRC PreCache thread is running threadControllerMode = %d\n",threadControllerMode);
try {
if(threadControllerMode == true) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("********************** CRC Controller thread START **********************\n");
time_t elapsedTime = time(NULL);
Checksum::clearFileCache();
vector<string> techPaths;
findDirs(techDataPaths, techPaths);
if(techPaths.empty() == false) {
// Always calc megapack first so its up to date sooner
const string megapackTechtreeName = "megapack";
vector<string>::iterator iterFindMegaPack = std::find(techPaths.begin(),techPaths.end(),megapackTechtreeName);
if(iterFindMegaPack != techPaths.end()) {
techPaths.erase(iterFindMegaPack);
techPaths.insert(techPaths.begin(),megapackTechtreeName);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Found megapack techtree and placing it at the TOP of the list\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
}
unsigned int techsPerWorker = ((unsigned int)techPaths.size() / (unsigned int)MAX_FileCRCPreCacheThread_WORKER_THREADS);
if(techPaths.size() % MAX_FileCRCPreCacheThread_WORKER_THREADS != 0) {
techsPerWorker++;
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] techsPerWorker = %u, MAX_FileCRCPreCacheThread_WORKER_THREADS = %d, techPaths.size() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,techsPerWorker,MAX_FileCRCPreCacheThread_WORKER_THREADS,(int)techPaths.size());
try {
unsigned int consumedWorkers = 0;
for(unsigned int workerIdx = 0; workerIdx < (unsigned int)MAX_FileCRCPreCacheThread_WORKER_THREADS; ++workerIdx) {
if(getQuitStatus() == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
break;
}
unsigned int currentWorkerMax = ((unsigned int)techPaths.size() - consumedWorkers);
if(currentWorkerMax > techsPerWorker) {
currentWorkerMax = techsPerWorker;
}
vector<string> workerTechList;
unsigned int endConsumerIndex = consumedWorkers + currentWorkerMax;
for(unsigned int idx = consumedWorkers; idx < endConsumerIndex; idx++) {
string techName = techPaths[idx];
workerTechList.push_back(techName);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Spawning CRC thread for Tech [%s] [%u of %lu]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,techName.c_str(),idx+1,techPaths.size());
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] workerIdx = %u, currentWorkerMax = %u, endConsumerIndex = %u\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,workerIdx,currentWorkerMax,endConsumerIndex);
// Pause before launching this worker thread
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("About to process CRC for factions waiting...\n");
time_t pauseTime = time(NULL);
while(getQuitStatus() == false &&
difftime(time(NULL),pauseTime) <= PAUSE_SECONDS_BETWEEN_WORKERS) {
sleep(25);
}
if(getQuitStatus() == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
break;
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Starting CRC for faction workers...\n");
FileCRCPreCacheThread *workerThread =
new FileCRCPreCacheThread(techDataPaths,
workerTechList,
this->processTechCB);
static string mutexOwnerId = string(extractFileFromDirectoryPath(__FILE__).c_str()) + string("_") + intToStr(__LINE__);
workerThread->setUniqueID(mutexOwnerId);
workerThread->setPauseForGame(this->getPauseForGame());
static string mutexOwnerId2 = CODE_AT_LINE;
MutexSafeWrapper safeMutexPause(mutexPauseForGame,mutexOwnerId2);
preCacheWorkerThreadList.push_back(workerThread);
safeMutexPause.ReleaseLock();
workerThread->start();
consumedWorkers += currentWorkerMax;
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Spawning CRC thread, preCacheWorkerThreadList.size() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,(int)preCacheWorkerThreadList.size());
if(consumedWorkers >= techPaths.size()) {
break;
}
}
}
catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
}
catch(...) {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] UNKNOWN Error\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unknown error\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
}
sleep(0);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Waiting for Spawned CRC threads to complete, preCacheWorkerThreadList.size() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,(int)preCacheWorkerThreadList.size());
try {
bool hasRunningWorkerThread = true;
for(;hasRunningWorkerThread == true;) {
hasRunningWorkerThread = false;
for(unsigned int idx = 0; idx < preCacheWorkerThreadList.size(); idx++) {
FileCRCPreCacheThread *workerThread = preCacheWorkerThreadList[idx];
if(workerThread != NULL) {
if(workerThread->getRunningStatus() == true) {
hasRunningWorkerThread = true;
if(getQuitStatus() == true &&
workerThread->getQuitStatus() == false) {
workerThread->signalQuit();
}
}
else if(workerThread->getRunningStatus() == false) {
sleep(25);
static string mutexOwnerId2 = CODE_AT_LINE;
MutexSafeWrapper safeMutexPause(mutexPauseForGame,mutexOwnerId2);
delete workerThread;
preCacheWorkerThreadList[idx] = NULL;
safeMutexPause.ReleaseLock();
}
}
}
if( getQuitStatus() == false &&
hasRunningWorkerThread == true) {
sleep(25);
}
else if(getQuitStatus() == true) {
for(unsigned int idx = 0; idx < preCacheWorkerThreadList.size(); idx++) {
FileCRCPreCacheThread *workerThread = preCacheWorkerThreadList[idx];
if(workerThread != NULL && workerThread->getQuitStatus() == false) {
workerThread->signalQuit();
}
}
}
}
}
catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
}
catch(...) {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] UNKNOWN Error\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unknown error\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("********************** CRC Controller thread took %.2f seconds END **********************\n",difftime(time(NULL),elapsedTime));
}
}
else {
try {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\tStarting CRC for faction worker thread for techs: %d...\n",(int)workerThreadTechPaths.size());
for(unsigned int idx = 0; idx < workerThreadTechPaths.size(); idx++) {
string techName = this->workerThreadTechPaths[idx];
if(getQuitStatus() == true) {
break;
}
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("--------------------- CRC worker thread START for tech [%s] ---------------------------\n",techName.c_str());
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] caching CRC value for Tech [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,techName.c_str());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] caching CRC value for Tech [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,techName.c_str());
time_t elapsedTime = time(NULL);
// Clear existing CRC to force a CRC refresh
//string pathSearchString = string("/") + techName + string("/*");
//const string filterFileExt = ".xml";
//clearFolderTreeContentsCheckSum(techDataPaths, pathSearchString, filterFileExt);
//clearFolderTreeContentsCheckSumList(techDataPaths, pathSearchString, filterFileExt);
if(getQuitStatus() == true) {
break;
}
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("--------------------- CRC worker thread running for tech [%s] ---------------------------\n",techName.c_str());
if(getQuitStatus() == false) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\t\tAbout to process CRC for techName [%s]\n",techName.c_str());
// Do not process CRC's while game in progress
if(getPauseForGame() == true) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\t\tGame in progress so waiting to process CRC for techName [%s]\n",techName.c_str());
for(;getPauseForGame() == true &&
getQuitStatus() == false;) {
sleep(25);
}
if(getQuitStatus() == true) {
break;
}
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\t\tStart Processing CRC for techName [%s]\n",techName.c_str());
uint32 techCRC = getFolderTreeContentsCheckSumRecursively(techDataPaths, string("/") + techName + string("/*"), ".xml", NULL, true);
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] cached CRC value for Tech [%s] is [%d] took %.3f seconds.\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,techName.c_str(),techCRC,difftime(time(NULL),elapsedTime));
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] cached CRC value for Tech [%s] is [%u] took %.3f seconds.\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,techName.c_str(),techCRC,difftime(time(NULL),elapsedTime));
vector<string> results;
for(unsigned int idx = 0; idx < techDataPaths.size(); idx++) {
string &techPath = techDataPaths[idx];
endPathWithSlash(techPath);
findAll(techPath + techName + "/factions/*.", results, false, false);
if(results.empty() == false) {
break;
}
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\t\tStarting CRC for faction worker thread for results: %d...\n",(int)results.size());
if(results.empty() == true) {
for(unsigned int factionIdx = 0;
factionIdx < results.size();
++factionIdx) {
string factionName = results[factionIdx];
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\t\t\tAbout to process CRC for factionName [%s]\n",factionName.c_str());
// Do not process CRC's while game in progress
if(getPauseForGame() == true) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\t\t\tGame in progress so waiting to process CRC for factionName [%s]\n",factionName.c_str());
for(;getPauseForGame() == true &&
getQuitStatus() == false;) {
sleep(25);
}
if(getQuitStatus() == true) {
break;
}
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\t\t\tStart Processing CRC for factionName [%s]\n",factionName.c_str());
uint32 factionCRC = getFolderTreeContentsCheckSumRecursively(techDataPaths, "/" + techName + "/factions/" + factionName + "/*", ".xml", NULL, true);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\t\t\tDone Processing CRC for factionName [%s] CRC [%d]\n",factionName.c_str(),factionCRC);
}
}
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] cached CRC value for Tech [%s] is [%d] took %.3f seconds.\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,techName.c_str(),techCRC,difftime(time(NULL),elapsedTime));
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] cached CRC value for Tech [%s] is [%d] took %.3f seconds.\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,techName.c_str(),techCRC,difftime(time(NULL),elapsedTime));
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("--------------------- CRC worker thread END for tech [%s] ---------------------------\n",techName.c_str());
if(getQuitStatus() == true) {
break;
}
}
}
catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
}
catch(...) {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] UNKNOWN Error\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unknown error\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
}
}
}
catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
}
catch(...) {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] UNKNOWN Error\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unknown error\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] FILE CRC PreCache thread is exiting...\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] FILE CRC PreCache thread is exiting...\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
}
deleteSelfIfRequired();
}
SimpleTaskThread::SimpleTaskThread( SimpleTaskCallbackInterface *simpleTaskInterface,
unsigned int executionCount,
unsigned int millisecsBetweenExecutions,
bool needTaskSignal,
void *userdata, bool wantSetupAndShutdown) : BaseThread(),
simpleTaskInterface(NULL),
overrideShutdownTask(NULL),
mutexSimpleTaskInterfaceValid(new Mutex(CODE_AT_LINE)),
mutexTaskSignaller(new Mutex(CODE_AT_LINE)),
mutexLastExecuteTimestamp(new Mutex(CODE_AT_LINE)) {
uniqueID = "SimpleTaskThread";
this->simpleTaskInterface = simpleTaskInterface;
this->simpleTaskInterfaceValid = (this->simpleTaskInterface != NULL);
this->executionCount = executionCount;
this->millisecsBetweenExecutions = millisecsBetweenExecutions;
this->needTaskSignal = needTaskSignal;
this->overrideShutdownTask = NULL;
this->userdata = userdata;
this->wantSetupAndShutdown = wantSetupAndShutdown;
//if(this->userdata != NULL) {
// printf("IN SImpleThread this->userdata [%p]\n",this->userdata);
//}
setTaskSignalled(false);
string mutexOwnerId = CODE_AT_LINE;
MutexSafeWrapper safeMutex(mutexLastExecuteTimestamp,mutexOwnerId);
mutexLastExecuteTimestamp->setOwnerId(mutexOwnerId);
lastExecuteTimestamp = time(NULL);
if(this->wantSetupAndShutdown == true) {
string mutexOwnerId1 = CODE_AT_LINE;
MutexSafeWrapper safeMutex1(mutexSimpleTaskInterfaceValid,mutexOwnerId1);
if(this->simpleTaskInterfaceValid == true) {
safeMutex1.ReleaseLock();
this->simpleTaskInterface->setupTask(this,userdata);
}
}
}
SimpleTaskThread::~SimpleTaskThread() {
//printf("~SimpleTaskThread LINE: %d this = %p\n",__LINE__,this);
try {
cleanup();
delete mutexSimpleTaskInterfaceValid;
mutexSimpleTaskInterfaceValid = NULL;
delete mutexTaskSignaller;
mutexTaskSignaller = NULL;
delete mutexLastExecuteTimestamp;
mutexLastExecuteTimestamp = NULL;
}
catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,this->getUniqueID().c_str());
throw megaglest_runtime_error(ex.what());
//abort();
}
//printf("~SimpleTaskThread LINE: %d this = %p\n",__LINE__,this);
}
void SimpleTaskThread::cleanup() {
//printf("~SimpleTaskThread LINE: %d this = %p\n",__LINE__,this);
if(this->wantSetupAndShutdown == true) {
if(this->overrideShutdownTask != NULL) {
//printf("~SimpleTaskThread LINE: %d this = %p\n",__LINE__,this);
this->overrideShutdownTask(this);
this->overrideShutdownTask = NULL;
}
else if(this->simpleTaskInterface != NULL) {
//printf("~SimpleTaskThread LINE: %d this = %p\n",__LINE__,this);
string mutexOwnerId1 = CODE_AT_LINE;
MutexSafeWrapper safeMutex1(mutexSimpleTaskInterfaceValid,mutexOwnerId1);
//printf("~SimpleTaskThread LINE: %d this = %p\n",__LINE__,this);
if(this->simpleTaskInterfaceValid == true) {
//printf("~SimpleTaskThread LINE: %d this = %p\n",__LINE__,this);
safeMutex1.ReleaseLock();
//printf("~SimpleTaskThread LINE: %d this = %p\n",__LINE__,this);
this->simpleTaskInterface->shutdownTask(this,userdata);
this->simpleTaskInterface = NULL;
//printf("~SimpleTaskThread LINE: %d this = %p\n",__LINE__,this);
}
}
}
//printf("~SimpleTaskThread LINE: %d this = %p\n",__LINE__,this);
}
void SimpleTaskThread::setOverrideShutdownTask(taskFunctionCallback *ptr) {
this->overrideShutdownTask = ptr;
}
bool SimpleTaskThread::isThreadExecutionLagging() {
string mutexOwnerId = CODE_AT_LINE;
MutexSafeWrapper safeMutex(mutexLastExecuteTimestamp,mutexOwnerId);
mutexLastExecuteTimestamp->setOwnerId(mutexOwnerId);
bool result = (difftime(time(NULL),lastExecuteTimestamp) >= 5.0);
safeMutex.ReleaseLock();
return result;
}
bool SimpleTaskThread::canShutdown(bool deleteSelfIfShutdownDelayed) {
bool ret = (getExecutingTask() == false);
if(ret == false && deleteSelfIfShutdownDelayed == true) {
setDeleteSelfOnExecutionDone(deleteSelfIfShutdownDelayed);
deleteSelfIfRequired();
signalQuit();
}
return ret;
}
bool SimpleTaskThread::getSimpleTaskInterfaceValid() {
string mutexOwnerId1 = CODE_AT_LINE;
MutexSafeWrapper safeMutex1(mutexSimpleTaskInterfaceValid,mutexOwnerId1);
return this->simpleTaskInterfaceValid;
}
void SimpleTaskThread::setSimpleTaskInterfaceValid(bool value) {
string mutexOwnerId1 = CODE_AT_LINE;
MutexSafeWrapper safeMutex1(mutexSimpleTaskInterfaceValid,mutexOwnerId1);
this->simpleTaskInterfaceValid = value;
}
void SimpleTaskThread::execute() {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
void *ptr_cpy = this->ptr;
bool mustDeleteSelf = false;
{
{
RunningStatusSafeWrapper runningStatus(this);
try {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
if(getQuitStatus() == true) {
return;
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,this->getUniqueID().c_str());
unsigned int idx = 0;
for(;this->simpleTaskInterface != NULL;) {
string mutexOwnerId1 = CODE_AT_LINE;
MutexSafeWrapper safeMutex1(mutexSimpleTaskInterfaceValid,mutexOwnerId1);
if(this->simpleTaskInterfaceValid == false) {
break;
}
safeMutex1.ReleaseLock();
bool runTask = true;
if(needTaskSignal == true) {
runTask = getTaskSignalled();
if(runTask == true) {
setTaskSignalled(false);
}
}
if(getQuitStatus() == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,this->getUniqueID().c_str());
break;
}
else if(runTask == true) {
if(getQuitStatus() == false) {
ExecutingTaskSafeWrapper safeExecutingTaskMutex(this);
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
this->simpleTaskInterface->simpleTask(this,this->userdata);
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
if(getQuitStatus() == true) {
break;
}
string mutexOwnerId = CODE_AT_LINE;
MutexSafeWrapper safeMutex(mutexLastExecuteTimestamp,mutexOwnerId);
mutexLastExecuteTimestamp->setOwnerId(mutexOwnerId);
lastExecuteTimestamp = time(NULL);
safeMutex.ReleaseLock();
}
}
if(this->executionCount > 0) {
idx++;
if(idx >= this->executionCount) {
break;
}
}
if(getQuitStatus() == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,this->getUniqueID().c_str());
break;
}
sleep(this->millisecsBetweenExecutions);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s] END\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,this->getUniqueID().c_str());
mustDeleteSelf = getDeleteSelfOnExecutionDone();
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
}
catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,this->getUniqueID().c_str());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s] END\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,this->getUniqueID().c_str());
mustDeleteSelf = getDeleteSelfOnExecutionDone();
throw megaglest_runtime_error(ex.what());
}
}
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
if(mustDeleteSelf == true) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
if(isThreadDeleted(ptr_cpy) == false) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
this->setDeleteAfterExecute(true);
}
return;
}
}
void SimpleTaskThread::setTaskSignalled(bool value) {
string mutexOwnerId = CODE_AT_LINE;
MutexSafeWrapper safeMutex(mutexTaskSignaller,mutexOwnerId);
mutexTaskSignaller->setOwnerId(mutexOwnerId);
taskSignalled = value;
safeMutex.ReleaseLock();
}
bool SimpleTaskThread::getTaskSignalled() {
string mutexOwnerId = CODE_AT_LINE;
MutexSafeWrapper safeMutex(mutexTaskSignaller,mutexOwnerId);
mutexTaskSignaller->setOwnerId(mutexOwnerId);
bool retval = taskSignalled;
safeMutex.ReleaseLock();
return retval;
}
// -------------------------------------------------
LogFileThread::LogFileThread() : BaseThread(), mutexLogList(new Mutex(CODE_AT_LINE)) {
uniqueID = "LogFileThread";
logList.clear();
lastSaveToDisk = time(NULL);
static string mutexOwnerId = CODE_AT_LINE;
mutexLogList->setOwnerId(mutexOwnerId);
}
LogFileThread::~LogFileThread() {
delete mutexLogList;
mutexLogList = NULL;
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("#1 In [%s::%s Line: %d] LogFile thread is deleting\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
}
void LogFileThread::addLogEntry(SystemFlags::DebugType type, string logEntry) {
static string mutexOwnerId = CODE_AT_LINE;
MutexSafeWrapper safeMutex(mutexLogList,mutexOwnerId);
mutexLogList->setOwnerId(mutexOwnerId);
LogFileEntry entry;
entry.type = type;
entry.entry = logEntry;
entry.entryDateTime = time(NULL);
logList.push_back(entry);
//if(logList.size() >= 750000) {
// saveToDisk(false,true);
//}
}
bool LogFileThread::checkSaveCurrentLogBufferToDisk() {
bool ret = false;
if(difftime(time(NULL),lastSaveToDisk) >= 5.0 ||
(difftime(time(NULL), lastSaveToDisk) >= 2.0 &&
LogFileThread::getLogEntryBufferCount() >= 1000000)) {
lastSaveToDisk = time(NULL);
ret = true;
}
return ret;
}
void LogFileThread::execute() {
void *ptr_cpy = this->ptr;
bool mustDeleteSelf = false;
{
RunningStatusSafeWrapper runningStatus(this);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
if(getQuitStatus() == true) {
deleteSelfIfRequired();
return;
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"LogFile thread is running\n");
try {
ExecutingTaskSafeWrapper safeExecutingTaskMutex(this);
for(;this->getQuitStatus() == false;) {
while(this->getQuitStatus() == false &&
checkSaveCurrentLogBufferToDisk() == true) {
saveToDisk(false,false);
}
if(this->getQuitStatus() == false) {
sleep(25);
}
}
// Ensure remaining entryies are logged to disk on shutdown
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
saveToDisk(true,false);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
}
catch(const exception &ex) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
}
catch(...) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] UNKNOWN Error\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] LogFile thread is starting to exit\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
mustDeleteSelf = getDeleteSelfOnExecutionDone();
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] LogFile thread is exiting, mustDeleteSelf = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,mustDeleteSelf);
}
if(mustDeleteSelf == true) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] LogFile thread is deleting self\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
if(isThreadDeleted(ptr_cpy) == false) {
this->setDeleteAfterExecute(true);
}
return;
}
}
std::size_t LogFileThread::getLogEntryBufferCount() {
static string mutexOwnerId = CODE_AT_LINE;
MutexSafeWrapper safeMutex(mutexLogList,mutexOwnerId);
mutexLogList->setOwnerId(mutexOwnerId);
std::size_t logCount = logList.size();
safeMutex.ReleaseLock();
return logCount;
}
bool LogFileThread::canShutdown(bool deleteSelfIfShutdownDelayed) {
bool ret = (getExecutingTask() == false);
if(ret == false && deleteSelfIfShutdownDelayed == true) {
setDeleteSelfOnExecutionDone(deleteSelfIfShutdownDelayed);
deleteSelfIfRequired();
signalQuit();
}
return ret;
}
void LogFileThread::saveToDisk(bool forceSaveAll,bool logListAlreadyLocked) {
static string mutexOwnerId = CODE_AT_LINE;
MutexSafeWrapper safeMutex(NULL,mutexOwnerId);
if(logListAlreadyLocked == false) {
safeMutex.setMutex(mutexLogList);
mutexLogList->setOwnerId(mutexOwnerId);
}
std::size_t logCount = logList.size();
if(logCount > 0) {
vector<LogFileEntry> tempLogList = logList;
safeMutex.ReleaseLock(true);
logCount = tempLogList.size();
//if(forceSaveAll == false) {
// logCount = min(logCount,(std::size_t)2000000);
//}
if(logCount > 0) {
for(unsigned int i = 0; i < logCount; ++i) {
LogFileEntry &entry = tempLogList[i];
SystemFlags::logDebugEntry(entry.type, entry.entry, entry.entryDateTime);
}
safeMutex.Lock();
if(logList.size() > 0) {
if(logList.size() < logCount) {
char szBuf[8096]="";
snprintf(szBuf,8096,"logList.size() <= logCount [%lld][%lld]",(long long int)logList.size(),(long long int)logCount);
throw megaglest_runtime_error(szBuf);
}
logList.erase(logList.begin(),logList.begin() + logCount);
}
safeMutex.ReleaseLock();
}
}
else {
safeMutex.ReleaseLock();
}
}
}}//end namespace