summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2012-08-02 16:15:22 +0200
committerQt by Nokia <qt-info@nokia.com>2012-08-25 10:35:26 +0200
commitc28204066c2d3bae989132ab15e8df437ae38f3d (patch)
tree989935de1629ae724d8826f16244e85907ad7043
parent98437f0e2edde7f5e49e1a6bea27ef130b58bee4 (diff)
Mark mutex locking and unlocking functions with noexcept
Unlocking a mutex can never throw an exception. That doesn't make sense and our code should make sure it can't happen. Right now, provided that the system-level functions don't throw, we don't either. Locking a mutex cannot throw on Linux because we use futexes directly. A non-recursive mutex is just a futex, whereas a recursive mutex uses a mutex (a futex) to manage a lock count. However, on other platforms, due to the freelist, there can be memory allocation, which means it might throw std::bad_alloc. Not because of the freelist itself (that uses malloc and will just crash if malloc fails) but because of Q_GLOBAL_STATIC. In 5.1, the global static will be noexcept provided the type's constructor is so too (it is, in this case). Change-Id: I4c562383f48de1be7827b9afb512d73eaf0792d5 Reviewed-by: Marc Mutz <marc.mutz@kdab.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/thread/qmutex.cpp18
-rw-r--r--src/corelib/thread/qmutex.h32
-rw-r--r--src/corelib/thread/qmutex_linux.cpp6
-rw-r--r--src/corelib/thread/qmutex_mac.cpp2
-rw-r--r--src/corelib/thread/qmutex_p.h8
-rw-r--r--src/corelib/thread/qmutex_unix.cpp2
-rw-r--r--src/corelib/thread/qmutex_win.cpp2
7 files changed, 37 insertions, 33 deletions
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
index a88e3ceef9..1d35b76c92 100644
--- a/src/corelib/thread/qmutex.cpp
+++ b/src/corelib/thread/qmutex.cpp
@@ -68,7 +68,6 @@ QT_BEGIN_NAMESPACE
- Do not use tryLock with timeout > 0, else you can have a leak (see the ~QMutex destructor)
*/
-
/*!
\class QMutex
\inmodule QtCore
@@ -179,7 +178,7 @@ QMutex::~QMutex()
\sa unlock()
*/
-void QMutex::lock()
+void QMutex::lock() QT_MUTEX_LOCK_NOEXCEPT
{
QBasicMutex::lock();
}
@@ -207,7 +206,7 @@ void QMutex::lock()
\sa lock(), unlock()
*/
-bool QMutex::tryLock(int timeout)
+bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
{
return QBasicMutex::tryLock(timeout);
}
@@ -219,7 +218,7 @@ bool QMutex::tryLock(int timeout)
\sa lock()
*/
-void QMutex::unlock()
+void QMutex::unlock() Q_DECL_NOTHROW
{
QBasicMutex::unlock();
}
@@ -332,7 +331,7 @@ bool QBasicMutex::isRecursive() {
/*!
\internal helper for lock()
*/
-bool QBasicMutex::lockInternal(int timeout)
+bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
{
while (!fastTryLock()) {
QMutexData *copy = d_ptr.loadAcquire();
@@ -425,7 +424,7 @@ bool QBasicMutex::lockInternal(int timeout)
/*!
\internal
*/
-void QBasicMutex::unlockInternal()
+void QBasicMutex::unlockInternal() Q_DECL_NOTHROW
{
QMutexData *copy = d_ptr.loadAcquire();
Q_ASSERT(copy); //we must be locked
@@ -493,7 +492,7 @@ void QMutexPrivate::release()
}
// atomically subtract "value" to the waiters, and remove the QMutexPrivate::BigNumber flag
-void QMutexPrivate::derefWaiters(int value)
+void QMutexPrivate::derefWaiters(int value) Q_DECL_NOTHROW
{
int old_waiters;
int new_waiters;
@@ -511,7 +510,8 @@ void QMutexPrivate::derefWaiters(int value)
/*!
\internal
*/
-bool QRecursiveMutexPrivate::lock(int timeout) {
+bool QRecursiveMutexPrivate::lock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
+{
Qt::HANDLE self = QThread::currentThreadId();
if (owner == self) {
++count;
@@ -533,7 +533,7 @@ bool QRecursiveMutexPrivate::lock(int timeout) {
/*!
\internal
*/
-void QRecursiveMutexPrivate::unlock()
+void QRecursiveMutexPrivate::unlock() Q_DECL_NOTHROW
{
if (count > 0) {
count--;
diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h
index 4fe4df09c6..5d4d6969f5 100644
--- a/src/corelib/thread/qmutex.h
+++ b/src/corelib/thread/qmutex.h
@@ -53,34 +53,40 @@ QT_BEGIN_NAMESPACE
#if !defined(QT_NO_THREAD) && !defined(qdoc)
+#ifdef Q_OS_LINUX
+# define QT_MUTEX_LOCK_NOEXCEPT Q_DECL_NOTHROW
+#else
+# define QT_MUTEX_LOCK_NOEXCEPT
+#endif
+
class QMutexData;
class Q_CORE_EXPORT QBasicMutex
{
public:
- inline void lock() {
+ inline void lock() QT_MUTEX_LOCK_NOEXCEPT {
if (!fastTryLock())
lockInternal();
}
- inline void unlock() {
+ inline void unlock() Q_DECL_NOTHROW {
Q_ASSERT(d_ptr.load()); //mutex must be locked
if (!d_ptr.testAndSetRelease(dummyLocked(), 0))
unlockInternal();
}
- bool tryLock(int timeout = 0) {
+ bool tryLock(int timeout = 0) QT_MUTEX_LOCK_NOEXCEPT {
return fastTryLock() || lockInternal(timeout);
}
bool isRecursive();
private:
- inline bool fastTryLock() {
+ inline bool fastTryLock() Q_DECL_NOTHROW {
return d_ptr.testAndSetAcquire(0, dummyLocked());
}
- bool lockInternal(int timeout = -1);
- void unlockInternal();
+ bool lockInternal(int timeout = -1) QT_MUTEX_LOCK_NOEXCEPT;
+ void unlockInternal() Q_DECL_NOTHROW;
QBasicAtomicPointer<QMutexData> d_ptr;
static inline QMutexData *dummyLocked() {
@@ -97,9 +103,9 @@ public:
explicit QMutex(RecursionMode mode = NonRecursive);
~QMutex();
- void lock();
- bool tryLock(int timeout = 0);
- void unlock();
+ void lock() QT_MUTEX_LOCK_NOEXCEPT;
+ bool tryLock(int timeout = 0) QT_MUTEX_LOCK_NOEXCEPT;
+ void unlock() Q_DECL_NOTHROW;
using QBasicMutex::isRecursive;
@@ -111,7 +117,7 @@ private:
class Q_CORE_EXPORT QMutexLocker
{
public:
- inline explicit QMutexLocker(QBasicMutex *m)
+ inline explicit QMutexLocker(QBasicMutex *m) QT_MUTEX_LOCK_NOEXCEPT
{
Q_ASSERT_X((reinterpret_cast<quintptr>(m) & quintptr(1u)) == quintptr(0),
"QMutexLocker", "QMutex pointer is misaligned");
@@ -124,7 +130,7 @@ public:
}
inline ~QMutexLocker() { unlock(); }
- inline void unlock()
+ inline void unlock() Q_DECL_NOTHROW
{
if ((val & quintptr(1u)) == quintptr(1u)) {
val &= ~quintptr(1u);
@@ -132,7 +138,7 @@ public:
}
}
- inline void relock()
+ inline void relock() QT_MUTEX_LOCK_NOEXCEPT
{
if (val) {
if ((val & quintptr(1u)) == quintptr(0u)) {
@@ -162,8 +168,6 @@ private:
quintptr val;
};
-
-
#else // QT_NO_THREAD or qdoc
class Q_CORE_EXPORT QMutex
diff --git a/src/corelib/thread/qmutex_linux.cpp b/src/corelib/thread/qmutex_linux.cpp
index a10bd35eff..3ccaeff4e3 100644
--- a/src/corelib/thread/qmutex_linux.cpp
+++ b/src/corelib/thread/qmutex_linux.cpp
@@ -87,7 +87,7 @@ static inline int futexFlags()
return value;
}
-static inline int _q_futex(void *addr, int op, int val, const struct timespec *timeout)
+static inline int _q_futex(void *addr, int op, int val, const struct timespec *timeout) Q_DECL_NOTHROW
{
volatile int *int_addr = reinterpret_cast<volatile int *>(addr);
#if Q_BYTE_ORDER == Q_BIG_ENDIAN && QT_POINTER_SIZE == 8
@@ -106,7 +106,7 @@ static inline QMutexData *dummyFutexValue()
return reinterpret_cast<QMutexData *>(quintptr(3));
}
-bool QBasicMutex::lockInternal(int timeout)
+bool QBasicMutex::lockInternal(int timeout) Q_DECL_NOTHROW
{
QElapsedTimer elapsedTimer;
if (timeout >= 1)
@@ -147,7 +147,7 @@ bool QBasicMutex::lockInternal(int timeout)
return true;
}
-void QBasicMutex::unlockInternal()
+void QBasicMutex::unlockInternal() Q_DECL_NOTHROW
{
QMutexData *d = d_ptr.load();
Q_ASSERT(d); //we must be locked
diff --git a/src/corelib/thread/qmutex_mac.cpp b/src/corelib/thread/qmutex_mac.cpp
index ecd3442d91..a828499ebd 100644
--- a/src/corelib/thread/qmutex_mac.cpp
+++ b/src/corelib/thread/qmutex_mac.cpp
@@ -84,7 +84,7 @@ bool QMutexPrivate::wait(int timeout)
return (r == KERN_SUCCESS);
}
-void QMutexPrivate::wakeUp()
+void QMutexPrivate::wakeUp() Q_DECL_NOTHROW
{
semaphore_signal(mach_semaphore);
}
diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h
index 92f13b1b7d..3ef99d5fc0 100644
--- a/src/corelib/thread/qmutex_p.h
+++ b/src/corelib/thread/qmutex_p.h
@@ -86,7 +86,7 @@ public:
QMutexPrivate();
bool wait(int timeout = -1);
- void wakeUp();
+ void wakeUp() Q_DECL_NOTHROW;
// Conrol the lifetime of the privates
QAtomicInt refCount;
@@ -115,7 +115,7 @@ public:
QAtomicInt waiters; //number of thread waiting
QAtomicInt possiblyUnlocked; //bool saying that a timed wait timed out
enum { BigNumber = 0x100000 }; //Must be bigger than the possible number of waiters (number of threads)
- void derefWaiters(int value);
+ void derefWaiters(int value) Q_DECL_NOTHROW;
//platform specific stuff
#if defined(Q_OS_MAC)
@@ -139,8 +139,8 @@ public:
uint count;
QMutex mutex;
- bool lock(int timeout);
- void unlock();
+ bool lock(int timeout) QT_MUTEX_LOCK_NOEXCEPT;
+ void unlock() Q_DECL_NOTHROW;
};
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp
index 0347d4b3da..6c74c68d8e 100644
--- a/src/corelib/thread/qmutex_unix.cpp
+++ b/src/corelib/thread/qmutex_unix.cpp
@@ -104,7 +104,7 @@ bool QMutexPrivate::wait(int timeout)
return ret;
}
-void QMutexPrivate::wakeUp()
+void QMutexPrivate::wakeUp() Q_DECL_NOTHROW
{
report_error(pthread_mutex_lock(&mutex), "QMutex::unlock", "mutex lock");
wakeup = true;
diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp
index 1fdf97b0d0..0e06c6a26e 100644
--- a/src/corelib/thread/qmutex_win.cpp
+++ b/src/corelib/thread/qmutex_win.cpp
@@ -61,7 +61,7 @@ bool QMutexPrivate::wait(int timeout)
return (WaitForSingleObject(event, timeout < 0 ? INFINITE : timeout) == WAIT_OBJECT_0);
}
-void QMutexPrivate::wakeUp()
+void QMutexPrivate::wakeUp() Q_DECL_NOTHROW
{ SetEvent(event); }
QT_END_NAMESPACE