// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QSEMAPHORE_H #define QSEMAPHORE_H #include #include #include QT_REQUIRE_CONFIG(thread); QT_BEGIN_NAMESPACE class QSemaphorePrivate; class Q_CORE_EXPORT QSemaphore { public: explicit QSemaphore(int n = 0); ~QSemaphore(); void acquire(int n = 1); bool tryAcquire(int n = 1); QT_CORE_INLINE_SINCE(6, 6) bool tryAcquire(int n, int timeout); bool tryAcquire(int n, QDeadlineTimer timeout); #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) template bool tryAcquire(int n, std::chrono::duration timeout) { return tryAcquire(n, QDeadlineTimer(timeout)); } #endif void release(int n = 1); int available() const; // std::counting_semaphore compatibility: bool try_acquire() noexcept { return tryAcquire(); } template bool try_acquire_for(const std::chrono::duration &timeout) { return tryAcquire(1, timeout); } template bool try_acquire_until(const std::chrono::time_point &tp) { return try_acquire_for(tp - Clock::now()); } private: Q_DISABLE_COPY(QSemaphore) union { QSemaphorePrivate *d; QBasicAtomicInteger u; QBasicAtomicInteger u32[2]; QBasicAtomicInteger u64; }; }; #if QT_CORE_INLINE_IMPL_SINCE(6, 6) bool QSemaphore::tryAcquire(int n, int timeout) { return tryAcquire(n, QDeadlineTimer(timeout)); } #endif class QSemaphoreReleaser { public: Q_NODISCARD_CTOR QSemaphoreReleaser() = default; Q_NODISCARD_CTOR explicit QSemaphoreReleaser(QSemaphore &sem, int n = 1) noexcept : m_sem(&sem), m_n(n) {} Q_NODISCARD_CTOR explicit QSemaphoreReleaser(QSemaphore *sem, int n = 1) noexcept : m_sem(sem), m_n(n) {} Q_NODISCARD_CTOR QSemaphoreReleaser(QSemaphoreReleaser &&other) noexcept : m_sem(other.cancel()), m_n(other.m_n) {} QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSemaphoreReleaser) ~QSemaphoreReleaser() { if (m_sem) m_sem->release(m_n); } void swap(QSemaphoreReleaser &other) noexcept { qt_ptr_swap(m_sem, other.m_sem); std::swap(m_n, other.m_n); } QSemaphore *semaphore() const noexcept { return m_sem; } QSemaphore *cancel() noexcept { return std::exchange(m_sem, nullptr); } private: QSemaphore *m_sem = nullptr; int m_n; }; QT_END_NAMESPACE #endif // QSEMAPHORE_H