blob: 95890f7519d0a5d8d1e38c1bfa77998eaf1dbd65 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
// Copyright (C) 2024 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLATCH_P_H
#define QLATCH_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an implementation
// detail. This header file may change from version to version without notice,
// or even be removed.
//
// We mean it.
//
#include <QtCore/qbasicatomic.h>
#include <QtCore/qtsan_impl.h>
#include <private/qglobal_p.h>
#include <limits>
QT_BEGIN_NAMESPACE
class QLatch
{
public:
constexpr explicit QLatch(int expected) noexcept
: counter(expected | NoWaiters)
{}
int pending() const noexcept
{
return (counter.loadAcquire() & CounterMask);
}
void countDown(int n = 1) noexcept
{
QtTsan::latchCountDown(&counter);
if (counter.fetchAndSubRelease(n) == n) // addAndFetch(n) == 0
wakeUp();
}
bool tryWait() const noexcept
{
if (pending() != 0)
return false;
QtTsan::latchWait(&counter);
return true;
}
void wait() noexcept // not const
{
if (int current = counter.loadAcquire(); (current & CounterMask) != 0) {
waitInternal(current);
QtTsan::latchWait(&counter);
}
}
void arriveAndWait(int n = 1) noexcept
{
countDown(n);
wait();
}
// API compatible with C++20:
static constexpr int max() noexcept { return std::numeric_limits<int>::max(); }
void count_down(int n = 1) noexcept { countDown(n); }
bool try_wait() const noexcept { return tryWait(); }
void arrive_and_wait(int n = 1) noexcept { arriveAndWait(n); }
private:
static constexpr int NoWaitersBit = 31;
static constexpr int NoWaiters = 1 << NoWaitersBit;
static constexpr int CounterMask = ~NoWaiters;
QBasicAtomicInt counter;
Q_DISABLE_COPY_MOVE(QLatch)
#ifdef QATOMICWAIT_USE_FALLBACK
# define Q_LATCH_EXPORT /* being linked into the unit test */
#else
# define Q_LATCH_EXPORT Q_CORE_EXPORT
#endif
void Q_LATCH_EXPORT waitInternal(int current) noexcept;
void Q_LATCH_EXPORT wakeUp() noexcept;
#undef Q_LATCH_EXPORT
};
QT_END_NAMESPACE
#endif // QLATCH_P_H
|