diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2017-02-11 10:10:18 +0100 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2017-02-14 06:46:03 +0000 |
commit | f0ee4ed0a28d274c7a8efeb9e6ac8642e020e2cc (patch) | |
tree | 5e7d7d42888b948d62241b60d0418bea0009b28e /src/corelib/thread/qsemaphore.h | |
parent | 9c765522d1c4f8090b5f5d391b1740fc4bd67664 (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.h | 39 |
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 |