summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qsemaphore.h
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2017-02-11 10:10:18 +0100
committerMarc Mutz <marc.mutz@kdab.com>2017-02-14 06:46:03 +0000
commitf0ee4ed0a28d274c7a8efeb9e6ac8642e020e2cc (patch)
tree5e7d7d42888b948d62241b60d0418bea0009b28e /src/corelib/thread/qsemaphore.h
parent9c765522d1c4f8090b5f5d391b1740fc4bd67664 (diff)
Long live QSemaphoreReleaser!
This is a simple RAII class that makes semaphore releasing reliable in the face of exceptions and early returns. This code originates from KDTools' KDSemaphoreReleaser[1], but has been extensively reworked to support C++11 move semantics. [1] https://docs.kdab.com/kdtools/2.3.0/class_k_d_semaphore_releaser.html [ChangeLog][QtCore][QSemaphore] Added a new RAII class, QSemaphoreReleaser, to reliably perform release() calls. Change-Id: I6aff64d37cc0882b17c4419817bde60b542f34d9 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io> Reviewed-by: David Faure <david.faure@kdab.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/thread/qsemaphore.h')
-rw-r--r--src/corelib/thread/qsemaphore.h39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/corelib/thread/qsemaphore.h b/src/corelib/thread/qsemaphore.h
index adb9d73e50..a92740c8ce 100644
--- a/src/corelib/thread/qsemaphore.h
+++ b/src/corelib/thread/qsemaphore.h
@@ -69,6 +69,45 @@ private:
QSemaphorePrivate *d;
};
+class QSemaphoreReleaser
+{
+ QSemaphore *m_sem = nullptr;
+ int m_n;
+public:
+ QSemaphoreReleaser() = default;
+ explicit QSemaphoreReleaser(QSemaphore &sem, int n = 1) Q_DECL_NOTHROW
+ : m_sem(&sem), m_n(n) {}
+ explicit QSemaphoreReleaser(QSemaphore *sem, int n = 1) Q_DECL_NOTHROW
+ : m_sem(sem), m_n(n) {}
+ QSemaphoreReleaser(QSemaphoreReleaser &&other) Q_DECL_NOTHROW
+ : m_sem(other.m_sem), m_n(other.m_n)
+ { other.m_sem = nullptr; }
+ QSemaphoreReleaser &operator=(QSemaphoreReleaser &&other) Q_DECL_NOTHROW
+ { QSemaphoreReleaser moved(std::move(other)); swap(moved); return *this; }
+
+ ~QSemaphoreReleaser()
+ {
+ if (m_sem)
+ m_sem->release(m_n);
+ }
+
+ void swap(QSemaphoreReleaser &other) Q_DECL_NOTHROW
+ {
+ qSwap(m_sem, other.m_sem);
+ qSwap(m_n, other.m_n);
+ }
+
+ QSemaphore *semaphore() const Q_DECL_NOTHROW
+ { return m_sem; }
+
+ QSemaphore *cancel() Q_DECL_NOTHROW
+ {
+ QSemaphore *old = m_sem;
+ m_sem = nullptr;
+ return old;
+ }
+};
+
#endif // QT_NO_THREAD
QT_END_NAMESPACE