1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QSEMAPHORE_H
6#define QSEMAPHORE_H
7
8#include <QtCore/qglobal.h>
9#include <QtCore/qdeadlinetimer.h>
10
11#include <chrono>
12
13QT_BEGIN_NAMESPACE
14
15class QSemaphorePrivate;
16class Q_CORE_EXPORT QSemaphore
17{
18public:
19 explicit QSemaphore(int n = 0);
20 ~QSemaphore();
21
22 void acquire(int n = 1);
23 bool tryAcquire(int n = 1);
24 QT_CORE_INLINE_SINCE(6, 6)
25 bool tryAcquire(int n, int timeout);
26 bool tryAcquire(int n, QDeadlineTimer timeout);
27#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
28 template <typename Rep, typename Period>
29 bool tryAcquire(int n, std::chrono::duration<Rep, Period> timeout)
30 { return tryAcquire(n, timeout: QDeadlineTimer(timeout)); }
31#endif
32
33 void release(int n = 1);
34
35 int available() const;
36
37 // std::counting_semaphore compatibility:
38 bool try_acquire() noexcept { return tryAcquire(); }
39 template <typename Rep, typename Period>
40 bool try_acquire_for(const std::chrono::duration<Rep, Period> &timeout)
41 { return tryAcquire(1, timeout); }
42 template <typename Clock, typename Duration>
43 bool try_acquire_until(const std::chrono::time_point<Clock, Duration> &tp)
44 {
45 return try_acquire_for(tp - Clock::now());
46 }
47private:
48 Q_DISABLE_COPY(QSemaphore)
49
50 union {
51 QSemaphorePrivate *d;
52 QBasicAtomicInteger<quintptr> u;
53 QBasicAtomicInteger<quint32> u32[2];
54 QBasicAtomicInteger<quint64> u64;
55 };
56};
57
58#if QT_CORE_INLINE_IMPL_SINCE(6, 6)
59bool QSemaphore::tryAcquire(int n, int timeout)
60{
61 return tryAcquire(n, timeout: QDeadlineTimer(timeout));
62}
63#endif
64
65class QSemaphoreReleaser
66{
67public:
68 Q_NODISCARD_CTOR
69 QSemaphoreReleaser() = default;
70 Q_NODISCARD_CTOR
71 explicit QSemaphoreReleaser(QSemaphore &sem, int n = 1) noexcept
72 : m_sem(&sem), m_n(n) {}
73 Q_NODISCARD_CTOR
74 explicit QSemaphoreReleaser(QSemaphore *sem, int n = 1) noexcept
75 : m_sem(sem), m_n(n) {}
76 Q_NODISCARD_CTOR
77 QSemaphoreReleaser(QSemaphoreReleaser &&other) noexcept
78 : m_sem(other.cancel()), m_n(other.m_n) {}
79 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSemaphoreReleaser)
80
81 ~QSemaphoreReleaser()
82 {
83 if (m_sem)
84 m_sem->release(n: m_n);
85 }
86
87 void swap(QSemaphoreReleaser &other) noexcept
88 {
89 qt_ptr_swap(lhs&: m_sem, rhs&: other.m_sem);
90 std::swap(a&: m_n, b&: other.m_n);
91 }
92
93 QSemaphore *semaphore() const noexcept
94 { return m_sem; }
95
96 QSemaphore *cancel() noexcept
97 {
98 return std::exchange(obj&: m_sem, new_val: nullptr);
99 }
100
101private:
102 QSemaphore *m_sem = nullptr;
103 int m_n = 0;
104};
105
106QT_END_NAMESPACE
107
108#endif // QSEMAPHORE_H
109

source code of qtbase/src/corelib/thread/qsemaphore.h