From 696d13ee0e378e3f14eb624cae2335bc05f74d06 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 8 Mar 2007 00:22:11 +0000 Subject: [PATCH] added wxMutex::LockTimeout() (modified patch 1671637) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@44671 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + docs/latex/wx/mutex.tex | 26 +++++++++++++++++++++- include/wx/thread.h | 5 +++++ include/wx/thrimpl.cpp | 8 +++++++ src/msw/thread.cpp | 15 ++++++++++--- src/unix/threadpsx.cpp | 49 ++++++++++++++++++++++++++++++++++++++--- 6 files changed, 97 insertions(+), 7 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 2ba3c52ce5..05d265ae3d 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -35,6 +35,7 @@ All: - Fixed tab-related drawing and hit-testing bugs in wxRichTextCtrl. - Implemented background colour in wxRichTextCtrl. - Fixed crashes in helpview when opening a file. +- Added wxMutex::LockTimeout() (Aleksandr Napylov) wxGTK: diff --git a/docs/latex/wx/mutex.tex b/docs/latex/wx/mutex.tex index 64c95d8c84..fadf27236b 100644 --- a/docs/latex/wx/mutex.tex +++ b/docs/latex/wx/mutex.tex @@ -93,23 +93,27 @@ None. \latexignore{\rtfignore{\wxheading{Members}}} + \membersection{wxMutex::wxMutex}\label{wxmutexctor} \func{}{wxMutex}{\param{wxMutexType }{type = {\tt wxMUTEX\_DEFAULT}}} Default constructor. + \membersection{wxMutex::\destruct{wxMutex}}\label{wxmutexdtor} \func{}{\destruct{wxMutex}}{\void} Destroys the wxMutex object. + \membersection{wxMutex::Lock}\label{wxmutexlock} \func{wxMutexError}{Lock}{\void} -Locks the mutex object. +Locks the mutex object. This is equivalent to +\helpref{LockTimeout}{wxmutexlocktimeout} with infinite timeout. \wxheading{Return value} @@ -121,6 +125,25 @@ One of: \twocolitem{{\bf wxMUTEX\_DEAD\_LOCK}}{A deadlock situation was detected.} \end{twocollist} + +\membersection{wxMutex::LockTimeout}\label{wxmutexlocktimeout} + +\func{wxMutexError}{LockTimeout}{\param{unsigned long}{ msec}} + +Try to lock the mutex object during the specified time interval. + +\wxheading{Return value} + +One of: + +\twocolwidtha{7cm} +\begin{twocollist}\itemsep=0pt +\twocolitem{{\bf wxMUTEX\_NO\_ERROR}}{Mutex successfully locked.} +\twocolitem{{\bf wxMUTEX\_TIMEOUT}}{Mutex couldn't be acquired before timeout expiration.} +\twocolitem{{\bf wxMUTEX\_DEAD\_LOCK}}{A deadlock situation was detected.} +\end{twocollist} + + \membersection{wxMutex::TryLock}\label{wxmutextrylock} \func{wxMutexError}{TryLock}{\void} @@ -137,6 +160,7 @@ One of: \twocolitem{{\bf wxMUTEX\_BUSY}}{The mutex is already locked by another thread.} \end{twocollist} + \membersection{wxMutex::Unlock}\label{wxmutexunlock} \func{wxMutexError}{Unlock}{\void} diff --git a/include/wx/thread.h b/include/wx/thread.h index 036b3d0adb..b95652dcac 100644 --- a/include/wx/thread.h +++ b/include/wx/thread.h @@ -38,6 +38,7 @@ enum wxMutexError wxMUTEX_DEAD_LOCK, // mutex is already locked by the calling thread wxMUTEX_BUSY, // mutex is already locked by another thread wxMUTEX_UNLOCKED, // attempt to unlock a mutex which is not locked + wxMUTEX_TIMEOUT, // LockTimeout() has timed out wxMUTEX_MISC_ERROR // any other error }; @@ -149,6 +150,10 @@ public: // The caller must call Unlock() later if Lock() returned wxMUTEX_NO_ERROR. wxMutexError Lock(); + // Same as Lock() but return wxMUTEX_TIMEOUT if the mutex can't be locked + // during the given number of milliseconds + wxMutexError LockTimeout(unsigned long ms); + // Try to lock the mutex: if it is currently locked, return immediately // with an error. Otherwise the caller must call Unlock(). wxMutexError TryLock(); diff --git a/include/wx/thrimpl.cpp b/include/wx/thrimpl.cpp index ba4aa31bb7..63b837fec6 100644 --- a/include/wx/thrimpl.cpp +++ b/include/wx/thrimpl.cpp @@ -44,6 +44,14 @@ wxMutexError wxMutex::Lock() return m_internal->Lock(); } +wxMutexError wxMutex::LockTimeout(unsigned long ms) +{ + wxCHECK_MSG( m_internal, wxMUTEX_INVALID, + _T("wxMutex::Lock(): not initialized") ); + + return m_internal->Lock(ms); +} + wxMutexError wxMutex::TryLock() { wxCHECK_MSG( m_internal, wxMUTEX_INVALID, diff --git a/src/msw/thread.cpp b/src/msw/thread.cpp index 74ab15f4c9..9fe2deef2c 100644 --- a/src/msw/thread.cpp +++ b/src/msw/thread.cpp @@ -178,7 +178,8 @@ public: bool IsOk() const { return m_mutex != NULL; } wxMutexError Lock() { return LockTimeout(INFINITE); } - wxMutexError TryLock() { return LockTimeout(0); } + wxMutexError Lock(unsigned long ms) { return LockTimeout(ms); } + wxMutexError TryLock(); wxMutexError Unlock(); private: @@ -196,7 +197,7 @@ wxMutexInternal::wxMutexInternal(wxMutexType WXUNUSED(mutexType)) m_mutex = ::CreateMutex ( NULL, // default secutiry attributes - false, // not initially locked + FALSE, // not initially locked NULL // no name ); @@ -217,6 +218,14 @@ wxMutexInternal::~wxMutexInternal() } } +wxMutexError wxMutexInternal::TryLock() +{ + const wxMutexError rc = LockTimeout(0); + + // we have a special return code for timeout in this case + return rc == wxMUTEX_TIMEOUT ? wxMUTEX_BUSY : rc; +} + wxMutexError wxMutexInternal::LockTimeout(DWORD milliseconds) { DWORD rc = ::WaitForSingleObject(m_mutex, milliseconds); @@ -237,7 +246,7 @@ wxMutexError wxMutexInternal::LockTimeout(DWORD milliseconds) break; case WAIT_TIMEOUT: - return wxMUTEX_BUSY; + return wxMUTEX_TIMEOUT; case WAIT_ABANDONED: // checked for above default: diff --git a/src/unix/threadpsx.cpp b/src/unix/threadpsx.cpp index 983ac3632a..36943023ce 100644 --- a/src/unix/threadpsx.cpp +++ b/src/unix/threadpsx.cpp @@ -163,11 +163,16 @@ public: ~wxMutexInternal(); wxMutexError Lock(); + wxMutexError Lock(unsigned long ms); wxMutexError TryLock(); wxMutexError Unlock(); bool IsOk() const { return m_isOk; } +private: + // convert the result of pthread_mutex_[timed]lock() call to wx return code + wxMutexError HandleLockResult(int err); + private: pthread_mutex_t m_mutex; bool m_isOk; @@ -245,7 +250,41 @@ wxMutexInternal::~wxMutexInternal() wxMutexError wxMutexInternal::Lock() { - int err = pthread_mutex_lock(&m_mutex); + return HandleLockResult(pthread_mutex_lock(&m_mutex)); +} + +wxMutexError wxMutexInternal::Lock(unsigned long ms) +{ + static const long MSEC_IN_SEC = 1000; + static const long NSEC_IN_MSEC = 1000000; + static const long NSEC_IN_SEC = MSEC_IN_SEC * NSEC_IN_MSEC; + + time_t seconds = ms/MSEC_IN_SEC; + long nanoseconds = (ms % MSEC_IN_SEC) * NSEC_IN_MSEC; + timespec ts = { 0, 0 }; + + if ( clock_gettime(CLOCK_REALTIME, &ts) == 0 ) + { + ts.tv_sec += seconds; + ts.tv_nsec += nanoseconds; + if ( ts.tv_nsec > NSEC_IN_SEC ) + { + ts.tv_sec += 1; + ts.tv_nsec -= NSEC_IN_SEC; + } + } + else // fall back on system timer + { + wxLogDebug(_T("clock_gettime(CLOCK_REALTIME) failed")); + ts.tv_sec = time(NULL) + seconds; + ts.tv_nsec = nanoseconds; + } + + return HandleLockResult(pthread_mutex_timedlock(&m_mutex, &ts)); +} + +wxMutexError wxMutexInternal::HandleLockResult(int err) +{ switch ( err ) { case EDEADLK: @@ -255,19 +294,23 @@ wxMutexError wxMutexInternal::Lock() return wxMUTEX_DEAD_LOCK; case EINVAL: - wxLogDebug(_T("pthread_mutex_lock(): mutex not initialized.")); + wxLogDebug(_T("pthread_mutex_[timed]lock(): mutex not initialized")); break; + case ETIMEDOUT: + return wxMUTEX_TIMEOUT; + case 0: return wxMUTEX_NO_ERROR; default: - wxLogApiError(_T("pthread_mutex_lock()"), err); + wxLogApiError(_T("pthread_mutex_[timed]lock()"), err); } return wxMUTEX_MISC_ERROR; } + wxMutexError wxMutexInternal::TryLock() { int err = pthread_mutex_trylock(&m_mutex); -- 2.45.2