Revision: 41956
          http://brlcad.svn.sourceforge.net/brlcad/?rev=41956&view=rev
Author:   davidloman
Date:     2011-01-05 19:24:58 +0000 (Wed, 05 Jan 2011)

Log Message:
-----------
Fix up a multithread issue in ControlledRunnable.  Proper mutex's are in place 
for 'runCmd' and 'runStatus'

Modified Paths:
--------------
    rt^3/trunk/include/ControlledThread.h
    rt^3/trunk/include/GSThread.h
    rt^3/trunk/src/GS/GeometryService.cxx
    rt^3/trunk/src/libNet/PortalManager.cxx
    rt^3/trunk/src/utility/ControlledThread.cxx
    rt^3/trunk/src/utility/GSThread.cxx

Modified: rt^3/trunk/include/ControlledThread.h
===================================================================
--- rt^3/trunk/include/ControlledThread.h       2011-01-05 17:26:21 UTC (rev 
41955)
+++ rt^3/trunk/include/ControlledThread.h       2011-01-05 19:24:58 UTC (rev 
41956)
@@ -27,6 +27,7 @@
 #include "GSThread.h"
 
 #include <QtCore/QString>
+#include <QtCore/QMutex>
 
 class ControlledThread : public GSThread
 {
@@ -42,6 +43,9 @@
        void terminate(bool block);
        QString getThreadName();
 
+       bool getRunStatus();
+       bool getRunCmd();
+
 protected:
        virtual bool preStartupHook();
        virtual bool postStartupHook();
@@ -54,12 +58,20 @@
        virtual bool preShutdownHook();
        virtual bool postShutdownHook();
 
+       void setRunCmd(bool newVal);
+       void setRunStatus(bool newVal);
+
+private:
+
        /* fields */
        QString threadName;
+
+       QMutex runCmdLock;
        bool runCmd;
+
+       QMutex runStatusLock;
        bool runStatus;
 
-private:
        /* Disable copy cstr and =operator */
        ControlledThread(ControlledThread const&){};
        ControlledThread& operator=(ControlledThread const&){};

Modified: rt^3/trunk/include/GSThread.h
===================================================================
--- rt^3/trunk/include/GSThread.h       2011-01-05 17:26:21 UTC (rev 41955)
+++ rt^3/trunk/include/GSThread.h       2011-01-05 19:24:58 UTC (rev 41956)
@@ -39,6 +39,8 @@
   static void msleep (unsigned long msecs);
   static void usleep (unsigned long usecs);
 
+  void terminate();
+
 protected:
 
   /* For thread management */

Modified: rt^3/trunk/src/GS/GeometryService.cxx
===================================================================
--- rt^3/trunk/src/GS/GeometryService.cxx       2011-01-05 17:26:21 UTC (rev 
41955)
+++ rt^3/trunk/src/GS/GeometryService.cxx       2011-01-05 19:24:58 UTC (rev 
41956)
@@ -86,7 +86,7 @@
        this->log->logINFO("GeometryService", "Starting PortalManager");
        this->portalMan->start();
 
-       while (this->runCmd) {
+       while (this->getRunStatus()) {
                GSThread::msleep(100);
        }
 

Modified: rt^3/trunk/src/libNet/PortalManager.cxx
===================================================================
--- rt^3/trunk/src/libNet/PortalManager.cxx     2011-01-05 17:26:21 UTC (rev 
41955)
+++ rt^3/trunk/src/libNet/PortalManager.cxx     2011-01-05 19:24:58 UTC (rev 
41956)
@@ -101,7 +101,7 @@
        bool readyAccept = false;
        bool readyException = false;
 
-       while (this->runCmd) {
+       while (this->getRunCmd()) {
                /* Set values EVERY loop since select() on *nix modifies this. 
*/
                timeout.tv_sec = 0;
                timeout.tv_usec = 50 * 1000;

Modified: rt^3/trunk/src/utility/ControlledThread.cxx
===================================================================
--- rt^3/trunk/src/utility/ControlledThread.cxx 2011-01-05 17:26:21 UTC (rev 
41955)
+++ rt^3/trunk/src/utility/ControlledThread.cxx 2011-01-05 19:24:58 UTC (rev 
41956)
@@ -22,6 +22,8 @@
  */
 
 #include "ControlledThread.h"
+#include "Logger.h"
+#include <QtCore/QMutexLocker>
 
 ControlledThread::ControlledThread(QString threadName) {
        if (threadName.length() <= 0) {
@@ -29,16 +31,16 @@
        } else {
                this->threadName = threadName;
        }
-       this->runCmd = false;
-       this->runStatus = false;
+       this->setRunCmd(false);
+       this->setRunStatus(false);
 }
 
 ControlledThread::~ControlledThread() {}
 
 void ControlledThread::start() {
        bool preRetVal = this->preStartupHook();
-       this->runCmd = true;
-       GSThread::start(); //call super class start
+       this->setRunCmd(true);
+       GSThread::start(); /* call super class start */
        bool postRetVal = this->postStartupHook();
 }
 
@@ -53,13 +55,27 @@
 }
 
 void ControlledThread::terminate(bool block) {
+
        bool preRetVal = this->preShutdownHook();
-       this->runCmd = false;
+       this->setRunCmd(false);
 
-       if (block)
-               while (this->isRunning()) {
+       quint64 maxFailsafeTimeMS = 5 * 1000;
+
+       if (block) {
+
+               quint64 startT = Logger::getCurrentTime();
+               quint64 stopT = 0;
+               while (this->getRunStatus()) {
                        GSThread::msleep(100); //TODO need a failsafe here.
+                       stopT = Logger::getCurrentTime();
+
+                       if ((stopT - startT) >= maxFailsafeTimeMS) {
+                               
Logger::getInstance()->logWARNING("ControlledThread", "terminate(block=true) 
reached failsafe.  Forcefully stopping thread.");
+                               GSThread::terminate();
+                               break;
+                       }
                }
+       }
 
        bool postRetVal = this->postShutdownHook();
 }
@@ -68,24 +84,24 @@
        if(!this->preRunHook())
                return;
 
-       this->runStatus = true;
-       this->runCmd = true;
+       this->setRunCmd(true);
+       this->setRunStatus(true);
        this->_run();
-       this->runStatus = false;
+       this->setRunStatus(false);
 
        if(!this->postRunHook())
                return;
 }
 
 void ControlledThread::_run() {
-       while (this->runCmd) {
+       while (this->getRunCmd()) {
                this->_runLoopPass();
        }
 }
 
 void ControlledThread::_runLoopPass() {
        //DOES NOTHING BY DEFAULT
-       GSThread::msleep(123);
+       GSThread::msleep(1);
 }
 
 /**
@@ -124,6 +140,32 @@
        return this->threadName;
 }
 
+bool
+ControlledThread::getRunCmd()
+{
+       QMutexLocker(&this->runCmdLock);
+       return this->runCmd;
+}
+
+bool
+ControlledThread::getRunStatus()
+{
+       QMutexLocker(&this->runStatusLock);
+       return this->runStatus;
+}
+
+void
+ControlledThread::setRunCmd(bool newVal) {
+       QMutexLocker(&this->runCmdLock);
+       this->runCmd = newVal;
+}
+
+void
+ControlledThread::setRunStatus(bool newVal) {
+       QMutexLocker(&this->runStatusLock);
+       this->runStatus = newVal;
+}
+
 /*
  * Local Variables:
  * tab-width: 8

Modified: rt^3/trunk/src/utility/GSThread.cxx
===================================================================
--- rt^3/trunk/src/utility/GSThread.cxx 2011-01-05 17:26:21 UTC (rev 41955)
+++ rt^3/trunk/src/utility/GSThread.cxx 2011-01-05 19:24:58 UTC (rev 41956)
@@ -38,6 +38,12 @@
 }
 
 void
+GSThread::terminate()
+{
+       QThread::terminate();
+}
+
+void
 GSThread::sleep(unsigned long secs)
 {
   QThread::sleep(secs);


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and, 
should the need arise, upgrade to a full multi-node Oracle RAC database 
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl
_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to