Made wxMSW wxMutex non-recursive by checking reentrance

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@55469 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robert Roebling 2008-09-05 08:54:09 +00:00
parent 9c5313d170
commit 424c9ce771
2 changed files with 33 additions and 4 deletions

View File

@ -860,7 +860,7 @@ public:
*/
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. */
@ -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
@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
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

View File

@ -189,12 +189,16 @@ private:
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
wxMutexInternal::wxMutexInternal(wxMutexType WXUNUSED(mutexType))
wxMutexInternal::wxMutexInternal(wxMutexType mutexType)
{
// 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
);
m_type = mutexType;
m_owningThread = 0;
m_isLocked = false;
if ( !m_mutex )
{
wxLogLastError(_T("CreateMutex()"));
}
}
wxMutexInternal::~wxMutexInternal()
@ -231,6 +240,16 @@ wxMutexError wxMutexInternal::TryLock()
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 )
{
@ -261,6 +280,13 @@ wxMutexError wxMutexInternal::LockTimeout(DWORD milliseconds)
return wxMUTEX_MISC_ERROR;
}
if (m_type == wxMUTEX_DEFAULT)
{
// required for checking recursiveness
m_isLocked = true;
m_owningThread = wxThread::GetCurrentId();
}
return wxMUTEX_NO_ERROR;
}
@ -272,6 +298,9 @@ wxMutexError wxMutexInternal::Unlock()
return wxMUTEX_MISC_ERROR;
}
// required for checking recursiveness
m_isLocked = false;
return wxMUTEX_NO_ERROR;
}