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

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