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

Reply via email to