diff --git a/source/glest_game/main/main.cpp b/source/glest_game/main/main.cpp index f57cee87..29e464ac 100644 --- a/source/glest_game/main/main.cpp +++ b/source/glest_game/main/main.cpp @@ -90,38 +90,50 @@ static string mg_app_name = ""; static string mailStringSupport = ""; static bool sdl_quitCalled = false; -bool disableheadless_console = false; -bool disableBacktrace = false; -bool gameInitialized = false; +static bool disableheadless_console = false; +static bool disableBacktrace = false; +static bool gameInitialized = false; -Program *mainProgram = NULL; -FileCRCPreCacheThread *preCacheThread = NULL; -string runtimeErrorMsg = ""; +static Program *mainProgram = NULL; +static FileCRCPreCacheThread *preCacheThread = NULL; +static string runtimeErrorMsg = ""; void cleanupCRCThread() { if(preCacheThread != NULL) { if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + const double MAX_THREAD_WAIT = 60; + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("START - shutting down crc threads\n"); time_t elapsed = time(NULL); preCacheThread->signalQuit(); for(;preCacheThread->canShutdown(false) == false && - difftime(time(NULL),elapsed) <= 45;) { + difftime(time(NULL),elapsed) <= MAX_THREAD_WAIT;) { //sleep(150); } - if(preCacheThread->canShutdown(false)) { - if(preCacheThread->shutdownAndWait() == true) { + if(difftime(time(NULL),elapsed) <= MAX_THREAD_WAIT) { + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("B - shutting down crc threads\n"); + + for(;preCacheThread->shutdownAndWait() == false && + difftime(time(NULL),elapsed) <= MAX_THREAD_WAIT;) { + } + if(preCacheThread->getRunningStatus() == false) { delete preCacheThread; + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("C - shutting down crc threads\n"); } if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } else { - if(preCacheThread->shutdownAndWait() == true) { + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("D - shutting down crc threads\n"); + + if(preCacheThread->canShutdown(false) == true) { if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); delete preCacheThread; + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("E - shutting down crc threads\n"); //printf("Stopping broadcast thread [%p] - C\n",broadCastThread); } } + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("F - shutting down crc threads\n"); preCacheThread = NULL; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } diff --git a/source/shared_lib/include/platform/common/simple_threads.h b/source/shared_lib/include/platform/common/simple_threads.h index 1ee20490..8d8b14fe 100644 --- a/source/shared_lib/include/platform/common/simple_threads.h +++ b/source/shared_lib/include/platform/common/simple_threads.h @@ -57,6 +57,8 @@ public: void setWorkerThreadTechPaths(vector value) { this->workerThreadTechPaths = value; } void setFileCRCPreCacheThreadCallbackInterface(FileCRCPreCacheThreadCallbackInterface *value) { processTechCB = value; } vector getPendingTextureList(int maxTexturesToGet); + + virtual bool canShutdown(bool deleteSelfIfShutdownDelayed); }; // ===================================================== diff --git a/source/shared_lib/include/util/leak_dumper.h b/source/shared_lib/include/util/leak_dumper.h index 64917d4b..d9fc0d29 100644 --- a/source/shared_lib/include/util/leak_dumper.h +++ b/source/shared_lib/include/util/leak_dumper.h @@ -16,7 +16,6 @@ //SL_LEAK_DUMP controls if leak dumping is enabled or not #ifdef SL_LEAK_DUMP - #include // START - Special includes because the use a special new operator that we cannot override @@ -31,6 +30,7 @@ #include "thread.h" using Shared::Platform::Mutex; +using Shared::Platform::MutexSafeWrapper; // START - For gcc backtrace //#if defined(__GNUC__) && !defined(__MINGW32__) && !defined(__FreeBSD__) && !defined(BSD) @@ -48,7 +48,7 @@ using namespace std; //occurred in a file where this header is included will have //file and line number -static bool want_full_leak_stacktrace = true; +static bool want_full_leak_stacktrace = false; static bool want_full_leak_stacktrace_line_numbers = false; struct AllocInfo { @@ -282,16 +282,15 @@ private: private: inline AllocRegistry() { - mutex = getMutex(); + // manual memory allocation + void *mymutex_mem = malloc(sizeof(Mutex)); + // in place new operator + mutex = new(mymutex_mem) Mutex; + string value = AllocInfo::get_application_binary(); reset(); } - static Mutex * getMutex() { - static Mutex mymutex; - return &mymutex; - } - private: AllocInfo allocs[maxAllocs]; //array to store allocation info int allocCount; //allocations @@ -302,7 +301,7 @@ private: public: ~AllocRegistry(); - static AllocRegistry &getInstance() { + inline static AllocRegistry &getInstance() { static AllocRegistry allocRegistry; return allocRegistry; } @@ -320,9 +319,50 @@ public: } } - void allocate(AllocInfo info); - void deallocate(void* ptr, bool array,const char* file, int line); - //void reset(); + inline void allocate(AllocInfo info) { + //if(info.line == 0) return; + + MutexSafeWrapper safeMutexMasterList(mutex); + //printf("ALLOCATE.\tfile: %s, line: %d, bytes: %lu, array: %d inuse: %d\n", info.file, info.line, info.bytes, info.array, info.inuse); + + if(info.line > 0) { + ++allocCount; + allocBytes += info.bytes; + } + for(int i = (nextFreeIndex >= 0 ? nextFreeIndex : 0); i < maxAllocs; ++i) { + if(allocs[i].freetouse == true && allocs[i].inuse == false) { + allocs[i]= info; + nextFreeIndex=-1; + + return; + } + } + + printf("ALLOCATE NOT MONITORED.\tfile: %s, line: %d, ptr [%p], bytes: %lu, array: %d inuse: %d, \n%s\n", info.file, info.line, info.ptr, info.bytes, info.array, info.inuse, info.stack.c_str()); + + ++nonMonitoredCount; + nonMonitoredBytes+= info.bytes; + } + + inline void deallocate(void* ptr, bool array,const char* file, int line) { + //if(line == 0) return; + + MutexSafeWrapper safeMutexMasterList(mutex); + + for(int i=0; i < maxAllocs; ++i) { + if(allocs[i].freetouse == false && allocs[i].inuse == true && + allocs[i].ptr == ptr && allocs[i].array == array) { + allocs[i].freetouse= true; + allocs[i].inuse = false; + nextFreeIndex=i; + + return; + } + } + + if(line > 0) printf("WARNING, possible error on pointer delete for ptr [%p] array = %d, file [%s] line: %d\n%s\n",ptr,array,file, line,AllocInfo::getStackTrace().c_str()); + } + void dump(const char *path); }; diff --git a/source/shared_lib/sources/platform/common/simple_threads.cpp b/source/shared_lib/sources/platform/common/simple_threads.cpp index 92c5a0c8..e74a2ef0 100644 --- a/source/shared_lib/sources/platform/common/simple_threads.cpp +++ b/source/shared_lib/sources/platform/common/simple_threads.cpp @@ -41,6 +41,16 @@ FileCRCPreCacheThread::FileCRCPreCacheThread(vector techDataPaths, this->processTechCB = processTechCB; } +bool FileCRCPreCacheThread::canShutdown(bool deleteSelfIfShutdownDelayed) { + bool ret = (getExecutingTask() == false); + if(ret == false && deleteSelfIfShutdownDelayed == true) { + setDeleteSelfOnExecutionDone(deleteSelfIfShutdownDelayed); + signalQuit(); + } + + return ret; +} + void FileCRCPreCacheThread::execute() { { RunningStatusSafeWrapper runningStatus(this); @@ -166,6 +176,14 @@ void FileCRCPreCacheThread::execute() { hasRunningWorkerThread == true) { sleep(10); } + 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(); + } + } + } } if(SystemFlags::VERBOSE_MODE_ENABLED) printf("********************** CRC Controller thread took %.2f seconds END **********************\n",difftime(time(NULL),elapsedTime)); } diff --git a/source/shared_lib/sources/util/leak_dumper.cpp b/source/shared_lib/sources/util/leak_dumper.cpp index 8c7489a6..751430ec 100644 --- a/source/shared_lib/sources/util/leak_dumper.cpp +++ b/source/shared_lib/sources/util/leak_dumper.cpp @@ -11,7 +11,6 @@ #include "leak_dumper.h" #ifdef SL_LEAK_DUMP -using Shared::Platform::MutexSafeWrapper; bool AllocInfo::application_binary_initialized = false; //static AllocRegistry memoryLeaks = AllocRegistry::getInstance(); @@ -24,59 +23,9 @@ bool AllocInfo::application_binary_initialized = false; AllocRegistry::~AllocRegistry() { dump("leak_dump.log"); -} -void AllocRegistry::allocate(AllocInfo info) { - //if(info.line == 0) return; - - MutexSafeWrapper safeMutexMasterList(mutex); - //printf("ALLOCATE.\tfile: %s, line: %d, bytes: %lu, array: %d inuse: %d\n", info.file, info.line, info.bytes, info.array, info.inuse); - - if(info.line > 0) { - ++allocCount; - allocBytes += info.bytes; - } - //bool found = false; - for(int i = (nextFreeIndex >= 0 ? nextFreeIndex : 0); i < maxAllocs; ++i) { - if(allocs[i].freetouse == true && allocs[i].inuse == false) { - allocs[i]= info; - nextFreeIndex=-1; - //found = true; - return; - } - } - - //if(found == false) { - //printf("ALLOCATE NOT MONITORED\n"); - printf("ALLOCATE NOT MONITORED.\tfile: %s, line: %d, ptr [%p], bytes: %lu, array: %d inuse: %d, \n%s\n", info.file, info.line, info.ptr, info.bytes, info.array, info.inuse, info.stack.c_str()); - - ++nonMonitoredCount; - nonMonitoredBytes+= info.bytes; - //} -} - -void AllocRegistry::deallocate(void* ptr, bool array,const char* file, int line) { - //if(line == 0) return; - - MutexSafeWrapper safeMutexMasterList(mutex); - - //bool found = false; - for(int i=0; i < maxAllocs; ++i) { - if(allocs[i].freetouse == false && allocs[i].inuse == true && - allocs[i].ptr == ptr && allocs[i].array == array) { - allocs[i].freetouse= true; - allocs[i].inuse = false; - nextFreeIndex=i; - - //found = true; - //break; - return; - } - } - - //if(found == false) { - if(line > 0) printf("WARNING, possible error on pointer delete for ptr [%p] array = %d, file [%s] line: %d\n%s\n",ptr,array,file, line,AllocInfo::getStackTrace().c_str()); - //} + free(mutex); + mutex = NULL; } void AllocRegistry::dump(const char *path) { @@ -98,7 +47,7 @@ void AllocRegistry::dump(const char *path) { leakBytes += info.bytes; //allocs[i].stack = AllocInfo::getStackTrace(); - fprintf(f, "Leak #%d.\tfile: %s, line: %d, ptr [%p], bytes: %lu, array: %d, inuse: %d\n%s", ++leakCount, info.file, info.line, info.ptr, info.bytes, info.array,info.inuse,info.stack.c_str()); + fprintf(f, "Leak #%d.\tfile: %s, line: %d, ptr [%p], bytes: %lu, array: %d, inuse: %d\n%s\n", ++leakCount, info.file, info.line, info.ptr, info.bytes, info.array,info.inuse,info.stack.c_str()); } } }