summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qatomicwait_p.h
blob: 9a25e56863cdd38ea18385b034a4edb4a271e834 (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
// Copyright (C) 2025 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#ifndef QATOMICWAIT_P_H
#define QATOMICWAIT_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 "qbasicatomic.h"
#include <private/qglobal_p.h>

QT_BEGIN_NAMESPACE

namespace QtPrivate {
enum class WakeMode { One = 1, All = -1 };

#ifdef QATOMICWAIT_USE_FALLBACK
#  define Q_ATOMICWAIT_EXPORT /* being linked into the unit test */
#else
#  define Q_ATOMICWAIT_EXPORT Q_CORE_EXPORT
#endif

Q_ATOMICWAIT_EXPORT void _q_atomicWait(const void *address, const void *old, qsizetype size) noexcept;
Q_ATOMICWAIT_EXPORT void _q_atomicWake(void *address, WakeMode) noexcept;

#undef Q_ATOMICWAIT_EXPORT
}

namespace QtFallbackAtomicWait {
// C++20- & C23-like API
template <typename T> std::enable_if_t<std::has_unique_object_representations_v<T>>
atomic_wait_explicit(const std::atomic<T> *atomic, T old, std::memory_order mo) noexcept
{
    Q_ASSERT(mo == std::memory_order_relaxed || mo == std::memory_order_acquire
             || mo == std::memory_order_seq_cst);
    QtPrivate::_q_atomicWait(atomic, &old, sizeof(T));
    std::atomic_thread_fence(mo);
}

template <typename T> std::enable_if_t<std::has_unique_object_representations_v<T>>
atomic_wait(const std::atomic<T> *atomic, T old) noexcept
{
    atomic_wait_explicit(atomic, old, std::memory_order_seq_cst);
}

template <typename T> std::enable_if_t<std::has_unique_object_representations_v<T>>
atomic_notify_one(std::atomic<T> *atomic)
{
    QtPrivate::_q_atomicWake(atomic, QtPrivate::WakeMode::One);
}

template <typename T> std::enable_if_t<std::has_unique_object_representations_v<T>>
atomic_notify_all(std::atomic<T> *atomic)
{
    QtPrivate::_q_atomicWake(atomic, QtPrivate::WakeMode::All);
}
} // namespace QtFallbackAtomicWait

namespace q20 {
#ifdef __cpp_lib_atomic_wait
using std::atomic_wait;
using std::atomic_wait_explicit;
using std::atomic_notify_all;
using std::atomic_notify_one;
#else
using QtFallbackAtomicWait::atomic_wait;
using QtFallbackAtomicWait::atomic_wait_explicit;
using QtFallbackAtomicWait::atomic_notify_all;
using QtFallbackAtomicWait::atomic_notify_one;
#endif
} // namespace QtNativeAtomicWait

QT_END_NAMESPACE

#endif // QATOMICWAIT_P_H