added wxMutex::LockTimeout() (modified patch 1671637)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@44671 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2007-03-08 00:22:11 +00:00
parent 4738d6746b
commit 696d13ee0e
6 changed files with 97 additions and 7 deletions

View File

@@ -35,6 +35,7 @@ All:
- Fixed tab-related drawing and hit-testing bugs in wxRichTextCtrl. - Fixed tab-related drawing and hit-testing bugs in wxRichTextCtrl.
- Implemented background colour in wxRichTextCtrl. - Implemented background colour in wxRichTextCtrl.
- Fixed crashes in helpview when opening a file. - Fixed crashes in helpview when opening a file.
- Added wxMutex::LockTimeout() (Aleksandr Napylov)
wxGTK: wxGTK:

View File

@@ -93,23 +93,27 @@ None.
\latexignore{\rtfignore{\wxheading{Members}}} \latexignore{\rtfignore{\wxheading{Members}}}
\membersection{wxMutex::wxMutex}\label{wxmutexctor} \membersection{wxMutex::wxMutex}\label{wxmutexctor}
\func{}{wxMutex}{\param{wxMutexType }{type = {\tt wxMUTEX\_DEFAULT}}} \func{}{wxMutex}{\param{wxMutexType }{type = {\tt wxMUTEX\_DEFAULT}}}
Default constructor. Default constructor.
\membersection{wxMutex::\destruct{wxMutex}}\label{wxmutexdtor} \membersection{wxMutex::\destruct{wxMutex}}\label{wxmutexdtor}
\func{}{\destruct{wxMutex}}{\void} \func{}{\destruct{wxMutex}}{\void}
Destroys the wxMutex object. Destroys the wxMutex object.
\membersection{wxMutex::Lock}\label{wxmutexlock} \membersection{wxMutex::Lock}\label{wxmutexlock}
\func{wxMutexError}{Lock}{\void} \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} \wxheading{Return value}
@@ -121,6 +125,25 @@ One of:
\twocolitem{{\bf wxMUTEX\_DEAD\_LOCK}}{A deadlock situation was detected.} \twocolitem{{\bf wxMUTEX\_DEAD\_LOCK}}{A deadlock situation was detected.}
\end{twocollist} \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} \membersection{wxMutex::TryLock}\label{wxmutextrylock}
\func{wxMutexError}{TryLock}{\void} \func{wxMutexError}{TryLock}{\void}
@@ -137,6 +160,7 @@ One of:
\twocolitem{{\bf wxMUTEX\_BUSY}}{The mutex is already locked by another thread.} \twocolitem{{\bf wxMUTEX\_BUSY}}{The mutex is already locked by another thread.}
\end{twocollist} \end{twocollist}
\membersection{wxMutex::Unlock}\label{wxmutexunlock} \membersection{wxMutex::Unlock}\label{wxmutexunlock}
\func{wxMutexError}{Unlock}{\void} \func{wxMutexError}{Unlock}{\void}

View File

@@ -38,6 +38,7 @@ enum wxMutexError
wxMUTEX_DEAD_LOCK, // mutex is already locked by the calling thread wxMUTEX_DEAD_LOCK, // mutex is already locked by the calling thread
wxMUTEX_BUSY, // mutex is already locked by another thread wxMUTEX_BUSY, // mutex is already locked by another thread
wxMUTEX_UNLOCKED, // attempt to unlock a mutex which is not locked wxMUTEX_UNLOCKED, // attempt to unlock a mutex which is not locked
wxMUTEX_TIMEOUT, // LockTimeout() has timed out
wxMUTEX_MISC_ERROR // any other error wxMUTEX_MISC_ERROR // any other error
}; };
@@ -149,6 +150,10 @@ public:
// The caller must call Unlock() later if Lock() returned wxMUTEX_NO_ERROR. // The caller must call Unlock() later if Lock() returned wxMUTEX_NO_ERROR.
wxMutexError Lock(); 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 // Try to lock the mutex: if it is currently locked, return immediately
// with an error. Otherwise the caller must call Unlock(). // with an error. Otherwise the caller must call Unlock().
wxMutexError TryLock(); wxMutexError TryLock();

View File

@@ -44,6 +44,14 @@ wxMutexError wxMutex::Lock()
return m_internal->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() wxMutexError wxMutex::TryLock()
{ {
wxCHECK_MSG( m_internal, wxMUTEX_INVALID, wxCHECK_MSG( m_internal, wxMUTEX_INVALID,

View File

@@ -178,7 +178,8 @@ public:
bool IsOk() const { return m_mutex != NULL; } bool IsOk() const { return m_mutex != NULL; }
wxMutexError Lock() { return LockTimeout(INFINITE); } wxMutexError Lock() { return LockTimeout(INFINITE); }
wxMutexError TryLock() { return LockTimeout(0); } wxMutexError Lock(unsigned long ms) { return LockTimeout(ms); }
wxMutexError TryLock();
wxMutexError Unlock(); wxMutexError Unlock();
private: private:
@@ -196,7 +197,7 @@ wxMutexInternal::wxMutexInternal(wxMutexType WXUNUSED(mutexType))
m_mutex = ::CreateMutex m_mutex = ::CreateMutex
( (
NULL, // default secutiry attributes NULL, // default secutiry attributes
false, // not initially locked FALSE, // not initially locked
NULL // no name 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) wxMutexError wxMutexInternal::LockTimeout(DWORD milliseconds)
{ {
DWORD rc = ::WaitForSingleObject(m_mutex, milliseconds); DWORD rc = ::WaitForSingleObject(m_mutex, milliseconds);
@@ -237,7 +246,7 @@ wxMutexError wxMutexInternal::LockTimeout(DWORD milliseconds)
break; break;
case WAIT_TIMEOUT: case WAIT_TIMEOUT:
return wxMUTEX_BUSY; return wxMUTEX_TIMEOUT;
case WAIT_ABANDONED: // checked for above case WAIT_ABANDONED: // checked for above
default: default:

View File

@@ -163,11 +163,16 @@ public:
~wxMutexInternal(); ~wxMutexInternal();
wxMutexError Lock(); wxMutexError Lock();
wxMutexError Lock(unsigned long ms);
wxMutexError TryLock(); wxMutexError TryLock();
wxMutexError Unlock(); wxMutexError Unlock();
bool IsOk() const { return m_isOk; } 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: private:
pthread_mutex_t m_mutex; pthread_mutex_t m_mutex;
bool m_isOk; bool m_isOk;
@@ -245,7 +250,41 @@ wxMutexInternal::~wxMutexInternal()
wxMutexError wxMutexInternal::Lock() 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 ) switch ( err )
{ {
case EDEADLK: case EDEADLK:
@@ -255,19 +294,23 @@ wxMutexError wxMutexInternal::Lock()
return wxMUTEX_DEAD_LOCK; return wxMUTEX_DEAD_LOCK;
case EINVAL: case EINVAL:
wxLogDebug(_T("pthread_mutex_lock(): mutex not initialized.")); wxLogDebug(_T("pthread_mutex_[timed]lock(): mutex not initialized"));
break; break;
case ETIMEDOUT:
return wxMUTEX_TIMEOUT;
case 0: case 0:
return wxMUTEX_NO_ERROR; return wxMUTEX_NO_ERROR;
default: default:
wxLogApiError(_T("pthread_mutex_lock()"), err); wxLogApiError(_T("pthread_mutex_[timed]lock()"), err);
} }
return wxMUTEX_MISC_ERROR; return wxMUTEX_MISC_ERROR;
} }
wxMutexError wxMutexInternal::TryLock() wxMutexError wxMutexInternal::TryLock()
{ {
int err = pthread_mutex_trylock(&m_mutex); int err = pthread_mutex_trylock(&m_mutex);