]> git.saurik.com Git - wxWidgets.git/commitdiff
Made wxMSW wxMutex non-recursive by checking reentrance
authorRobert Roebling <robert@roebling.de>
Fri, 5 Sep 2008 08:54:09 +0000 (08:54 +0000)
committerRobert Roebling <robert@roebling.de>
Fri, 5 Sep 2008 08:54:09 +0000 (08:54 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@55469 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

interface/wx/thread.h
src/msw/thread.cpp

index b6eedd71c1ee717d007220417f6ab4ea422ab973..0e83c26d40ddeb2b14bd5e6b98f599348bffa6e9 100644 (file)
@@ -860,7 +860,7 @@ public:
 */
 enum wxMutexType
 {
 */
 enum wxMutexType
 {
-    /** Normal mutex: try to always use this one. Recursive under Windows. */
+    /** Normal non-recursive mutex: try to always use this one. */
     wxMUTEX_DEFAULT,   
 
     /** Recursive mutex: don't use these ones with wxCondition. */
     wxMUTEX_DEFAULT,   
 
     /** Recursive mutex: don't use these ones with wxCondition. */
@@ -909,9 +909,9 @@ enum wxMutexError
     had already locked before (instead of dead locking the entire process in this
     situation by starting to wait on a mutex which will never be released while the
     thread is waiting) but using them is not recommended under Unix and they are
     had already locked before (instead of dead locking the entire process in this
     situation by starting to wait on a mutex which will never be released while the
     thread is waiting) but using them is not recommended under Unix and they are
-    @b not recursive there by default. The reason for this is that recursive
+    @b not recursive by default. The reason for this is that recursive
     mutexes are not supported by all Unix flavours and, worse, they cannot be used
     mutexes are not supported by all Unix flavours and, worse, they cannot be used
-    with wxCondition. On the other hand, Win32 mutexes are always recursive.
+    with wxCondition.
 
     For example, when several threads use the data stored in the linked list,
     modifications to the list should only be allowed to one thread at a time
 
     For example, when several threads use the data stored in the linked list,
     modifications to the list should only be allowed to one thread at a time
index 072df5b37329d145816eb91693eddd21cdc91342..f6d9939eb4cf84b33813a57504e47467bca54982 100644 (file)
@@ -189,12 +189,16 @@ private:
     wxMutexError LockTimeout(DWORD milliseconds);
 
     HANDLE m_mutex;
     wxMutexError LockTimeout(DWORD milliseconds);
 
     HANDLE m_mutex;
+    
+    unsigned long m_owningThread;
+    bool m_isLocked;
+    wxMutexType m_type;
 
     DECLARE_NO_COPY_CLASS(wxMutexInternal)
 };
 
 // all mutexes are recursive under Win32 so we don't use mutexType
 
     DECLARE_NO_COPY_CLASS(wxMutexInternal)
 };
 
 // all mutexes are recursive under Win32 so we don't use mutexType
-wxMutexInternal::wxMutexInternal(wxMutexType WXUNUSED(mutexType))
+wxMutexInternal::wxMutexInternal(wxMutexType mutexType)
 {
     // create a nameless (hence intra process and always private) mutex
     m_mutex = ::CreateMutex
 {
     // create a nameless (hence intra process and always private) mutex
     m_mutex = ::CreateMutex
@@ -204,10 +208,15 @@ wxMutexInternal::wxMutexInternal(wxMutexType WXUNUSED(mutexType))
                     NULL        // no name
                 );
 
                     NULL        // no name
                 );
 
+    m_type = mutexType;
+    m_owningThread = 0;
+    m_isLocked = false;
+
     if ( !m_mutex )
     {
         wxLogLastError(_T("CreateMutex()"));
     }
     if ( !m_mutex )
     {
         wxLogLastError(_T("CreateMutex()"));
     }
+    
 }
 
 wxMutexInternal::~wxMutexInternal()
 }
 
 wxMutexInternal::~wxMutexInternal()
@@ -231,6 +240,16 @@ wxMutexError wxMutexInternal::TryLock()
 
 wxMutexError wxMutexInternal::LockTimeout(DWORD milliseconds)
 {
 
 wxMutexError wxMutexInternal::LockTimeout(DWORD milliseconds)
 {
+    if (m_type == wxMUTEX_DEFAULT)
+    {
+        // Don't allow recursive
+        if (m_isLocked)
+        {
+            if (m_owningThread == wxThread::GetCurrentId())
+                return wxMUTEX_DEAD_LOCK;
+        }
+    }
+
     DWORD rc = ::WaitForSingleObject(m_mutex, milliseconds);
     if ( rc == WAIT_ABANDONED )
     {
     DWORD rc = ::WaitForSingleObject(m_mutex, milliseconds);
     if ( rc == WAIT_ABANDONED )
     {
@@ -261,6 +280,13 @@ wxMutexError wxMutexInternal::LockTimeout(DWORD milliseconds)
             return wxMUTEX_MISC_ERROR;
     }
 
             return wxMUTEX_MISC_ERROR;
     }
 
+    if (m_type == wxMUTEX_DEFAULT)
+    { 
+        // required for checking recursiveness
+        m_isLocked = true;
+        m_owningThread = wxThread::GetCurrentId();
+    }
+    
     return wxMUTEX_NO_ERROR;
 }
 
     return wxMUTEX_NO_ERROR;
 }
 
@@ -272,6 +298,9 @@ wxMutexError wxMutexInternal::Unlock()
 
         return wxMUTEX_MISC_ERROR;
     }
 
         return wxMUTEX_MISC_ERROR;
     }
+    
+    // required for checking recursiveness
+    m_isLocked = false;
 
     return wxMUTEX_NO_ERROR;
 }
 
     return wxMUTEX_NO_ERROR;
 }