[prev in list] [next in list] [prev in thread] [next in thread] 

List:       sptk-commits
Subject:    r1036 - in trunk: sptk4 src/utils
From:       alexey () mail ! total-knowledge ! com
Date:       2009-10-30 2:39:59
Message-ID: courier.000000004AEA51FF.00005D38 () mail ! total-knowledge ! com
[Download RAW message or body]

Author: alexey
Date: 2009-10-29 19:39:59 -0700 (Thu, 29 Oct 2009)
New Revision: 1036

Modified:
   trunk/sptk4/CSafeList.h
   trunk/sptk4/CSafeQueue.h
   trunk/sptk4/CThread.h
   trunk/sptk4/CThreadManager.h
   trunk/src/utils/CThread.cpp
   trunk/src/utils/CThreadManager.cpp
Log:
Removed some race conditions

Modified: trunk/sptk4/CSafeList.h
===================================================================
--- trunk/sptk4/CSafeList.h	2009-10-30 02:37:16 UTC (rev 1035)
+++ trunk/sptk4/CSafeList.h	2009-10-30 02:39:59 UTC (rev 1036)
@@ -54,7 +54,7 @@
 /// thread).
 template <class T>
 class CSafeList {
-    std::list<T>    m_list;             ///< List of the Ts
+    std::list<T>*   m_list;             ///< List of the Ts
     CWaiter         m_lock;             ///< Lock to protect list operations
     CSemaphore      m_popSemaphore;     ///< Semaphore to waiting for an item if list is empty
     CSemaphore      m_pushSemaphore;    ///< Semaphore to wait if list is full
@@ -73,8 +73,15 @@
     CSafeList(uint32_t maxListItems=0) :
         m_pushSemaphore(maxListItems), m_maxListItems(maxListItems)
     {
+        m_list = new std::list<T>;
     }
 
+    ~CSafeList()
+    {
+        GUARD(m_lock);
+        delete m_list;
+    }
+
     /// @brief Places the item to the list tail
     /// @param item T&, a new list item
     void push_back(const T& item)
@@ -83,7 +90,7 @@
             m_pushSemaphore.wait();
         {
             CGuard guard(m_lock);
-            m_list.push_back(item);
+            m_list->push_back(item);
         }
         m_popSemaphore.post();
     }
@@ -96,7 +103,7 @@
             m_pushSemaphore.wait();
         {
             CGuard guard(m_lock);
-            m_list.push_front(item);
+            m_list->push_front(item);
         }
         m_popSemaphore.post();
     }
@@ -114,8 +121,8 @@
         if (m_popSemaphore.wait(timeoutMS)) {
             try {
                 CGuard guard(m_lock);
-                item = m_list.front();
-                m_list.pop_front();
+                item = m_list->front();
+                m_list->pop_front();
                 if (m_maxListItems)
                     m_pushSemaphore.post();
                 return true;
@@ -139,8 +146,8 @@
         if (m_popSemaphore.wait(timeoutMS)) {
             try {
                 CGuard guard(m_lock);
-                item = m_list.back();
-                m_list.pop_back();
+                item = m_list->back();
+                m_list->pop_back();
                 if (m_maxListItems)
                     m_pushSemaphore.post();
                 return true;
@@ -160,7 +167,7 @@
     bool foreach(Method* method, void* parameter=NULL)
     {
         iterator itor;
-        for (itor = m_list.begin(); itor != m_list.end(); itor++) {
+        for (itor = m_list->begin(); itor != m_list->end(); itor++) {
             if (!method(*itor, parameter))
                 return false;
         }
@@ -171,39 +178,39 @@
     void erase(T& item)
     {
         GUARD(m_lock);
-        iterator itor = find(m_list.begin(),m_list.end(),item);
-        if (itor != m_list.end())
-            m_list.erase(itor);
+        iterator itor = find(m_list->begin(),m_list->end(),item);
+        if (itor != m_list->end())
+            m_list->erase(itor);
     }
 
     /// @brief Removes an item from the list
     bool exists(T& item)
     {
         GUARD(m_lock);
-        iterator itor = find(m_list.begin(),m_list.end(),item);
-        return (itor != m_list.end());
+        iterator itor = find(m_list->begin(),m_list->end(),item);
+        return (itor != m_list->end());
     }
 
     /// @brief Clears the list
     void clear()
     {
         GUARD(m_lock);
-        while (!m_list.empty())
-            m_list.pop_front();
+        while (!m_list->empty())
+            m_list->pop_front();
     }
 
     /// @brief Returns true if the list is empty
     bool empty()
     {
         GUARD(m_lock);
-        return m_list.empty();
+        return m_list->empty();
     }
 
     /// @brief Returns number of items in the list
     size_t size()
     {
         GUARD(m_lock);
-        return m_list.size();
+        return m_list->size();
     }
 };
 /// @}

Modified: trunk/sptk4/CSafeQueue.h
===================================================================
--- trunk/sptk4/CSafeQueue.h	2009-10-30 02:37:16 UTC (rev 1035)
+++ trunk/sptk4/CSafeQueue.h	2009-10-30 02:39:59 UTC (rev 1036)
@@ -54,7 +54,7 @@
 /// thread).
 template <class T>
 class CSafeQueue {
-    std::queue<T>   m_queue;            ///< Queue of the Ts
+    std::queue<T>*  m_queue;            ///< Queue of the Ts
     CWaiter         m_lock;             ///< Lock to protect queue operations
     CSemaphore      m_popSemaphore;     ///< Semaphore to waiting for an item if queue is empty
     CSemaphore      m_pushSemaphore;    ///< Semaphore to wait if queue is full
@@ -68,8 +68,17 @@
     CSafeQueue(uint32_t maxQueueItems=0) :
         m_pushSemaphore(maxQueueItems), m_maxQueueItems(maxQueueItems)
     {
+        m_queue = new std::queue<T>;
     }
 
+    /// @brief Destructor
+    ~CSafeQueue()
+    {
+        GUARD(m_lock);
+        delete m_queue;
+        m_queue = 0;
+    }
+
     /// @brief Places the item to the queue tail
     /// @param item T&, a new queue item
     void push(const T& item)
@@ -78,7 +87,7 @@
             m_pushSemaphore.wait();
         {
             CGuard guard(m_lock);
-            m_queue.push(item);
+            m_queue->push(item);
         }
         m_popSemaphore.post();
     }
@@ -96,8 +105,8 @@
         if (m_popSemaphore.wait(timeoutMS)) {
             try {
                 CGuard guard(m_lock);
-                item = m_queue.front();
-                m_queue.pop();
+                item = m_queue->front();
+                m_queue->pop();
                 if (m_maxQueueItems)
                     m_pushSemaphore.post();
                 return true;
@@ -112,22 +121,22 @@
     void clear()
     {
         GUARD(m_lock);
-        while (!m_queue.empty())
-            m_queue.pop();
+        while (!m_queue->empty())
+            m_queue->pop();
     }
 
     /// @brief Returns true if the queue is empty
     bool empty()
     {
         GUARD(m_lock);
-        return m_queue.empty();
+        return m_queue->empty();
     }
 
     /// @brief Returns number of items in the queue
     size_t size()
     {
         GUARD(m_lock);
-        return m_queue.size();
+        return m_queue->size();
     }
 };
 /// @}

Modified: trunk/sptk4/CThread.h
===================================================================
--- trunk/sptk4/CThread.h	2009-10-30 02:37:16 UTC (rev 1035)
+++ trunk/sptk4/CThread.h	2009-10-30 02:39:59 UTC (rev 1036)
@@ -37,6 +37,7 @@
 #define __CTHREAD_H__
 
 #include <sptk4/CWaiter.h>
+#include <sptk4/CGuard.h>
 #include <sptk4/CBaseLog.h>
 #include <sptk4/CStrings.h>
 
@@ -53,6 +54,8 @@
 /// by overwriting threadFunction().
 class CThread {
     friend class CThreadManager;
+    CWaiter           m_lock;       ///< Lock to protect data members
+    CThreadManager*   m_owner;      ///< Optional thread owner
 protected:
     bool              m_terminated; ///< Flag: is the thread terminated?
     bool              m_running;    ///< Flag: is the thread running?
@@ -60,11 +63,9 @@
     std::string       m_name;       ///< Thread name
     CBaseLog*         m_threadLog;  ///< Optional thread log (NULL for no logging)
     uint32_t          m_stackSize;  ///< Thread stack size (0 for system default)
-    CThreadManager*   m_owner;      ///< Optional thread owner
 #ifndef _WIN32
     pthread_t         m_thread;     ///< Thread handle
 #else
-
     HANDLE            m_thread;     ///< Thread handle
     HANDLE            m_timer;      ///< Thread timer handle
 #endif
@@ -96,6 +97,9 @@
     /// The thread function. Should be overwritten by the derived class.
     virtual void threadFunction() = 0;
 
+    /// @brief Sets the thread manager that owns this thread
+    void setOwner(CThreadManager* owner);
+
 public:
 
     /// Constructor
@@ -116,11 +120,13 @@
 
     /// Returns true if the thread is terminated
     bool terminated() {
+        GUARD(m_lock);
         return m_terminated;
     }
 
     /// Returns true if the thread is running
     bool running() {
+        GUARD(m_lock);
         return m_running;
     }
 

Modified: trunk/sptk4/CThreadManager.h
===================================================================
--- trunk/sptk4/CThreadManager.h	2009-10-30 02:37:16 UTC (rev 1035)
+++ trunk/sptk4/CThreadManager.h	2009-10-30 02:39:59 UTC (rev 1036)
@@ -72,6 +72,7 @@
     CSafeList<PCThread>     m_threads;                  ///< Threads list
     CSafeQueue<PCThread>    m_terminatedThreads;        ///< Terminated threads list
     CProxyLog*              m_log;                      ///< Shared log
+    bool                    m_shutdown;                 ///< True during thread manager shutdown
 
 protected:
     /// @brief Registers completed thread termination

Modified: trunk/src/utils/CThread.cpp
===================================================================
--- trunk/src/utils/CThread.cpp	2009-10-30 02:37:16 UTC (rev 1035)
+++ trunk/src/utils/CThread.cpp	2009-10-30 02:39:59 UTC (rev 1036)
@@ -73,6 +73,7 @@
 void CThread::threadCleanup(void *p)
 {
     CThread *thread = (CThread *) p;
+    GUARD(thread->m_lock);
     thread->onThreadExit();
 }
 
@@ -91,7 +92,10 @@
 {
     if (m_thread) {
         if (m_politeMode) {
-            m_terminated = true;
+            {
+                GUARD(m_lock);
+                m_terminated = true;
+            }
 #ifndef _WIN32
             // wait till the thread is stopping
             pthread_join(m_thread, 0);
@@ -112,6 +116,7 @@
 
 void CThread::terminate()
 {
+    GUARD(m_lock);
     if (m_terminated)
         return;
     m_terminated = true;
@@ -157,24 +162,43 @@
 
 void CThread::runThread()
 {
-    m_running = true;
+    {
+        GUARD(m_lock);
+        m_running = true;
+    }
+
     threadFunction();
-    m_running = false;
-    m_terminated = true;
 
-    if (m_owner)
-        m_owner->registerTerminated(this);
+    {
+        GUARD(m_lock);
+        m_running = false;
+        m_terminated = true;
 
+        if (m_owner) {
+            m_owner->registerTerminated(this);
+            m_owner = NULL;
+        }
+    }
+
     destroyThread();
 }
 
 void CThread::run()
 {
-    m_terminated = false;
-    m_running = true;
+    {
+        GUARD(m_lock);
+        m_terminated = false;
+        m_running = true;
+    }
     createThread();
 }
 
+void CThread::setOwner(CThreadManager* owner)
+{
+    GUARD(m_lock);
+    m_owner = owner;
+}
+
 void CThread::msleep(int msec)
 {
 #ifndef _WIN32

Modified: trunk/src/utils/CThreadManager.cpp
===================================================================
--- trunk/src/utils/CThreadManager.cpp	2009-10-30 02:37:16 UTC (rev 1035)
+++ trunk/src/utils/CThreadManager.cpp	2009-10-30 02:39:59 UTC (rev 1036)
@@ -40,7 +40,7 @@
 using namespace sptk;
 
 CThreadManager::CThreadManager(CBaseLog* log) :
-    CThread("Thread Manager")
+    CThread("Thread Manager"), m_shutdown(false)
 {
     if (log) {
         m_log = new CProxyLog(*log);
@@ -53,6 +53,10 @@
 
 CThreadManager::~CThreadManager()
 {
+    {
+        GUARD(m_lock);
+        m_shutdown = true;
+    }
     clear();
     if (m_log)
         delete m_log;
@@ -61,8 +65,10 @@
 void CThreadManager::registerTerminated(CThread* thread)
 {
     GUARD(*this);
-    erase(thread);
-    m_terminatedThreads.push(thread);
+    if (!m_shutdown) {
+        m_threads.erase(thread);
+        m_terminatedThreads.push(thread);
+    }
 }
 
 void CThreadManager::threadFunction()
@@ -110,7 +116,7 @@
 void CThreadManager::erase(CThread* thread)
 {
     m_threads.erase(thread);
-    thread->m_owner = NULL;
+    thread->setOwner(NULL);
 }
 
 void CThreadManager::run()

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic