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
[email protected]
https://lists.sourceforge.net/lists/listinfo/rigsofrods-devel