Revision: 2448 http://rigsofrods.svn.sourceforge.net/rigsofrods/?rev=2448&view=rev Author: rorthomas Date: 2012-02-04 17:35:51 +0000 (Sat, 04 Feb 2012) Log Message: ----------- fixedmemory leaks, worker threads are high performance now
Modified Paths: -------------- trunk/source/main/physics/BeamFactory.cpp trunk/source/main/physics/threading/BeamThread.h trunk/source/main/physics/threading/BeamWorker.cpp trunk/source/main/physics/threading/BeamWorker.h trunk/source/main/physics/threading/BeamWorkerManager.cpp trunk/source/main/physics/threading/BeamWorkerManager.h trunk/source/main/utils/utils.cpp trunk/source/main/utils/utils.h Modified: trunk/source/main/physics/BeamFactory.cpp =================================================================== --- trunk/source/main/physics/BeamFactory.cpp 2012-02-04 15:38:52 UTC (rev 2447) +++ trunk/source/main/physics/BeamFactory.cpp 2012-02-04 17:35:51 UTC (rev 2448) @@ -81,7 +81,7 @@ // TEST for Beamworker - //BeamWorkerManager::getSingleton(); + //BeamWorkerManager::createThread(); } BeamFactory::~BeamFactory() Modified: trunk/source/main/physics/threading/BeamThread.h =================================================================== --- trunk/source/main/physics/threading/BeamThread.h 2012-02-04 15:38:52 UTC (rev 2447) +++ trunk/source/main/physics/threading/BeamThread.h 2012-02-04 17:35:51 UTC (rev 2448) @@ -26,6 +26,7 @@ #include "BeamWorkerManager.h" #include "BeamFactory.h" #include "Singleton.h" +#include "utils.h" // this class should be derived by every thread that wants to access the Beam array // it will automatically register with the thread manager upon initialization @@ -44,4 +45,4 @@ } }; -#endif // __BeamThread_H__ \ No newline at end of file +#endif // __BeamThread_H__ Modified: trunk/source/main/physics/threading/BeamWorker.cpp =================================================================== --- trunk/source/main/physics/threading/BeamWorker.cpp 2012-02-04 15:38:52 UTC (rev 2447) +++ trunk/source/main/physics/threading/BeamWorker.cpp 2012-02-04 17:35:51 UTC (rev 2448) @@ -34,21 +34,32 @@ void *threadWorkerEntry(void *beamWorkerPtr) { - // call worker method in class - BeamWorker *worker = (BeamWorker*)beamWorkerPtr; + // create new beam worker inside the new thread, not outside! + BeamWorker *worker = new BeamWorker(); worker->_startWorkerLoop(); + delete(worker); pthread_exit(NULL); return NULL; } BeamWorker::BeamWorker() : running(true), test1(0) { - pthread_create(&thread, NULL, threadWorkerEntry, (void*)this); } +void BeamWorker::createThread() +{ + pthread_t thread; + int res = pthread_create(&thread, NULL, threadWorkerEntry, NULL); + if(res) + { + perror("error creating new thread: "); + } + pthread_detach(thread); +} + BeamWorker::~BeamWorker() { - // TODO: make sure the thread is gone! + running = false; } void BeamWorker::_startWorkerLoop() @@ -62,7 +73,8 @@ } #endif //USE_CRASHRPT - LOG("TR| BeamWorker created: " + TOSTRING(ThreadID::getID())); + + //LOG("TR| BeamWorker created: " + getThreadIDAsString()); try { // additional exception handler required, otherwise RoR just crashes upon exception @@ -76,21 +88,20 @@ } } catch(Ogre::Exception& e) { - LOG("TR| BeamWorker exception: " + TOSTRING(ThreadID::getID()) + ": " + e.getFullDescription()); + LOG("TR| BeamWorker exception: " + getThreadIDAsString() + ": " + e.getFullDescription()); // TODO: error handling } - LOG("TR| BeamWorker exiting: " + TOSTRING(ThreadID::getID())); - delete(this); + //LOG("TR| BeamWorker exiting: " + getThreadIDAsString()); } void BeamWorker::_doWork() { float seconds = Ogre::Math::RangeRandom(0.1f, 2.0f); - LOG("TR| BeamWorker doing work: " + TOSTRING(ThreadID::getID()) + " sleeping " + TOSTRING(seconds) + " seconds"); + //LOG("TR| BeamWorker doing work: " + getThreadIDAsString() + " sleeping " + TOSTRING(seconds) + " seconds"); test1 += seconds; - if(test1 > 5) + if(test1 > 20) killWorker(); sleepMilliSeconds(seconds); Modified: trunk/source/main/physics/threading/BeamWorker.h =================================================================== --- trunk/source/main/physics/threading/BeamWorker.h 2012-02-04 15:38:52 UTC (rev 2447) +++ trunk/source/main/physics/threading/BeamWorker.h 2012-02-04 17:35:51 UTC (rev 2448) @@ -28,16 +28,18 @@ // this class wraps a thread that acts as worker thread. // it will request work and sync with the others -class BeamWorker : public BeamThread +class BeamWorker : + public BeamThread { protected: - pthread_t thread; bool running; float test1; public: BeamWorker(); ~BeamWorker(); + + static void createThread(); // called from the new thread, do not execute manually void _startWorkerLoop(); void killWorker() { running=false; } Modified: trunk/source/main/physics/threading/BeamWorkerManager.cpp =================================================================== --- trunk/source/main/physics/threading/BeamWorkerManager.cpp 2012-02-04 15:38:52 UTC (rev 2447) +++ trunk/source/main/physics/threading/BeamWorkerManager.cpp 2012-02-04 17:35:51 UTC (rev 2448) @@ -33,8 +33,9 @@ void *threadWorkerManagerEntry(void* ptr) { - BeamWorkerManager *btlm = (BeamWorkerManager*)ptr; - btlm->_startWorkerLoop(); + // create instance inside the new thread, not outside + BeamWorkerManager::getSingleton()._startWorkerLoop(); + // delete singleton maybe? pthread_exit(NULL); return NULL; } @@ -53,37 +54,50 @@ pthread_cond_init(&done_count_cv, NULL); threads.clear(); - - // start worker thread: - pthread_create(&workerThread, NULL, threadWorkerManagerEntry, (void*)this); } - BeamWorkerManager::~BeamWorkerManager() { - pthread_cond_destroy(&done_count_cv); pthread_mutex_destroy(&api_mutex); pthread_mutex_destroy(&done_count_mutex); + pthread_cond_destroy(&done_count_cv); } +void BeamWorkerManager::createThread() +{ + // start worker thread: + pthread_t workerThread; + int res = pthread_create(&workerThread, NULL, threadWorkerManagerEntry, NULL); + if(res) + { + perror("error starting thread: "); + } + pthread_detach(workerThread); +} + void BeamWorkerManager::_startWorkerLoop() { - LOG("worker manager started in thread " + TOSTRING(ThreadID::getID())); + LOG("worker manager started in thread " + getThreadIDAsString()); int rc = 0; struct timespec timeout; + int local_done_count = -1; while (1) { MUTEX_LOCK(&done_count_mutex); while (done_count < threadsSize) { - LOG("TR| worker loop continued, waiting for more threads | threads waiting: " + TOSTRING(done_count) + " / " + TOSTRING(threadsSize)); + //LOG("TR| worker loop continued, waiting for more threads | threads waiting: " + TOSTRING(done_count) + " / " + TOSTRING(threadsSize)); // set timeout +#if 1 + pthread_cond_wait(&done_count_cv, &done_count_mutex); +#else timeout.tv_sec = time(NULL); - timeout.tv_nsec = 5000; + timeout.tv_nsec = 50000; // then wait for signal or time rc = pthread_cond_timedwait(&done_count_cv, &done_count_mutex, &timeout); +#endif //0 } LOG("TR| worker loop done | threads waiting: " + TOSTRING(done_count) + " / " + TOSTRING(threadsSize)); MUTEX_UNLOCK(&done_count_mutex); @@ -95,55 +109,64 @@ _checkRunThreads(); // TODO: make modifications on truck array in here - if(threadsSize < 409) - sleepMilliSeconds(100); + // sleepMilliSeconds(100); // reset counter, continue all threads via signal LOG("TR| worker loop: un-pausing all threads"); MUTEX_LOCK(&done_count_mutex); done_count=0; // send signals to the threads + MUTEX_LOCK(&api_mutex); threadMap::iterator it; for(it = threads.begin(); it != threads.end(); ++it) { pthread_cond_signal(&it->second.work_cv); } + MUTEX_UNLOCK(&api_mutex); + MUTEX_UNLOCK(&done_count_mutex); } } void BeamWorkerManager::_checkRunThreads() { + int c = 0; for(int i=threadsSize; i < targetThreadSize; i++) - new BeamWorker(); + { + BeamWorker::createThread(); + c++; + } + if(c>0) + LOG("TR| "+ TOSTRING(c) + " threads died, restarted them"); } void BeamWorkerManager::addThread(BeamThread *bthread) { - // threadID is not valid in this context! MUTEX_LOCK(&api_mutex); + unsigned long tid = getThreadID(); workerData_t wd; pthread_mutex_init(&wd.work_mutex, NULL); pthread_cond_init(&wd.work_cv, NULL); wd.bthread = bthread; - wd.threadID = -1; - LOG("TR| add Thread: " + TOSTRING(bthread)); - threads[bthread] = wd; + wd.threadID = tid; + //LOG("TR| add Thread: " + TOSTRING((unsigned long)bthread) + " / thread " + TOSTRING(tid)); + // using insert instead of [] -> speed + threads.insert(std::pair<BeamThread*, workerData_t>(bthread, wd)); threadsSize = threads.size(); MUTEX_UNLOCK(&api_mutex); } void BeamWorkerManager::removeThread(BeamThread *bthread) { - // threadID is not valid in this context! MUTEX_LOCK(&api_mutex); + unsigned long tid = getThreadID(); threadMap::iterator it = threads.find(bthread); if(it == threads.end()) { - LOG("unknown thread calling remove: class " + TOSTRING((unsigned long)bthread)); + LOG("TR| unknown thread calling remove: class " + TOSTRING((unsigned long)bthread) + " / thread " + TOSTRING(tid)); return; } - LOG("TR| remove Thread: " + TOSTRING((unsigned long)bthread)); + //LOG("TR| remove Thread: " + TOSTRING((unsigned long)bthread) + " / thread " + TOSTRING(tid)); workerData_t &wd = it->second; pthread_cond_destroy(&wd.work_cv); pthread_mutex_destroy(&wd.work_mutex); @@ -155,17 +178,21 @@ MUTEX_LOCK(&done_count_mutex); pthread_cond_signal(&done_count_cv); MUTEX_UNLOCK(&done_count_mutex); - } void BeamWorkerManager::syncThreads(BeamThread *bthread) { - unsigned int tid = ThreadID::getID(); - LOG("TR| Thread visiting syncing point| class: " + TOSTRING((unsigned long)bthread) + " / thread: " + TOSTRING(tid)); + unsigned long tid = getThreadID(); + //LOG("TR| Thread visiting syncing point| class: " + TOSTRING((unsigned long)bthread) + " / thread: " + TOSTRING(tid)); + + // yes, we need this lock here + MUTEX_LOCK(&api_mutex); threadMap::iterator it = threads.find(bthread); + MUTEX_UNLOCK(&api_mutex); + // result? if(it == threads.end()) { - LOG("unknown thread calling: " + TOSTRING(tid) + " / class " + TOSTRING((unsigned long)bthread)); + LOG("TR| unknown thread calling: " + TOSTRING(tid) + " / class " + TOSTRING((unsigned long)bthread)); return; } Modified: trunk/source/main/physics/threading/BeamWorkerManager.h =================================================================== --- trunk/source/main/physics/threading/BeamWorkerManager.h 2012-02-04 15:38:52 UTC (rev 2447) +++ trunk/source/main/physics/threading/BeamWorkerManager.h 2012-02-04 17:35:51 UTC (rev 2448) @@ -25,11 +25,13 @@ #include "BeamFactory.h" #include "Singleton.h" +#include "utils.h" class BeamThread; // Manager that manages all threads and the beam locking -class BeamWorkerManager : public RoRSingleton<BeamWorkerManager> +class BeamWorkerManager : + public RoRSingleton<BeamWorkerManager> { friend class BeamThread; friend class RoRSingleton<BeamWorkerManager>; @@ -38,29 +40,30 @@ { pthread_mutex_t work_mutex; pthread_cond_t work_cv; - int threadID; + unsigned long threadID; BeamThread *bthread; } workerData_t; typedef std::map <BeamThread*, workerData_t> threadMap; threadMap threads; - int threadsSize; - int targetThreadSize; + unsigned long threadsSize; + unsigned long targetThreadSize; - int done_count; + unsigned long done_count; pthread_mutex_t api_mutex; pthread_mutex_t done_count_mutex; pthread_cond_t done_count_cv; - pthread_t workerThread; BeamWorkerManager(); ~BeamWorkerManager(); + void addThread(BeamThread *bthread); void removeThread(BeamThread *bthread); void syncThreads(BeamThread *bthread); public: + static void createThread(); void _startWorkerLoop(); void _checkRunThreads(); }; Modified: trunk/source/main/utils/utils.cpp =================================================================== --- trunk/source/main/utils/utils.cpp 2012-02-04 15:38:52 UTC (rev 2447) +++ trunk/source/main/utils/utils.cpp 2012-02-04 17:35:51 UTC (rev 2448) @@ -329,29 +329,3 @@ str.erase(0, str.find_first_not_of(delims)); // trim left } -pthread_key_t ThreadID::key; -pthread_once_t ThreadID::key_once = PTHREAD_ONCE_INIT; -unsigned int ThreadID::tuid = 1; - -unsigned int ThreadID::getID() -{ - ThreadID *ptr = NULL; - pthread_once(&key_once, ThreadID::make_key); - ptr = (ThreadID*)pthread_getspecific(key); - - if( !ptr ) { - ptr = new ThreadID(); - pthread_setspecific(key, (void*)ptr); - } - - return ptr->thread_id; -} - -ThreadID::ThreadID() : thread_id( tuid ) -{ - tuid++; -} -void ThreadID::make_key() -{ - pthread_key_create(&key, NULL); -} Modified: trunk/source/main/utils/utils.h =================================================================== --- trunk/source/main/utils/utils.h 2012-02-04 15:38:52 UTC (rev 2447) +++ trunk/source/main/utils/utils.h 2012-02-04 17:35:51 UTC (rev 2448) @@ -112,20 +112,14 @@ #endif } -class ThreadID +inline unsigned long getThreadID() { + return (unsigned long)pthread_self(); +} -public: - static unsigned int getID(); +inline Ogre::String getThreadIDAsString() +{ + return TOSTRING(getThreadID()); +} -private: - ThreadID(); - static void make_key(); - - unsigned int thread_id; - static pthread_key_t key; - static pthread_once_t key_once; - static unsigned int tuid; -}; - #endif //UTILS_H_ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Try before you buy = See our experts in action! The most comprehensive online learning library for Microsoft developers is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3, Metro Style Apps, more. Free future releases when you subscribe now! http://p.sf.net/sfu/learndevnow-dev2 _______________________________________________ Rigsofrods-devel mailing list Rigsofrods-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/rigsofrods-devel