1// Copyright (C) 2022 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 QATOMICSCOPEDVALUEROLLBACK_H
5#define QATOMICSCOPEDVALUEROLLBACK_H
6
7#include <QtCore/qassert.h>
8#include <QtCore/qatomic.h>
9#include <QtCore/qcompilerdetection.h>
10#include <QtCore/qtclasshelpermacros.h>
11#include <QtCore/qtconfigmacros.h>
12
13#include <atomic>
14
15QT_BEGIN_NAMESPACE
16
17template <typename T>
18class QAtomicScopedValueRollback
19{
20 std::atomic<T> &m_atomic;
21 T m_value;
22 std::memory_order m_mo;
23
24 Q_DISABLE_COPY_MOVE(QAtomicScopedValueRollback)
25
26 static constexpr std::memory_order store_part(std::memory_order mo) noexcept
27 {
28 switch (mo) {
29 case std::memory_order_relaxed:
30 case std::memory_order_consume:
31 case std::memory_order_acquire: return std::memory_order_relaxed;
32 case std::memory_order_release:
33 case std::memory_order_acq_rel: return std::memory_order_release;
34 case std::memory_order_seq_cst: return std::memory_order_seq_cst;
35 }
36 // GCC 8.x does not treat __builtin_unreachable() as constexpr
37#if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
38 // NOLINTNEXTLINE(qt-use-unreachable-return): Triggers on Clang, breaking GCC 8
39 Q_UNREACHABLE();
40#endif
41 return std::memory_order_seq_cst;
42 }
43
44 static constexpr std::memory_order load_part(std::memory_order mo) noexcept
45 {
46 switch (mo) {
47 case std::memory_order_relaxed:
48 case std::memory_order_release: return std::memory_order_relaxed;
49 case std::memory_order_consume: return std::memory_order_consume;
50 case std::memory_order_acquire:
51 case std::memory_order_acq_rel: return std::memory_order_acquire;
52 case std::memory_order_seq_cst: return std::memory_order_seq_cst;
53 }
54 // GCC 8.x does not treat __builtin_unreachable() as constexpr
55#if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
56 // NOLINTNEXTLINE(qt-use-unreachable-return): Triggers on Clang, breaking GCC 8
57 Q_UNREACHABLE();
58#endif
59 return std::memory_order_seq_cst;
60 }
61public:
62 //
63 // std::atomic:
64 //
65 Q_NODISCARD_CTOR
66 explicit constexpr
67 QAtomicScopedValueRollback(std::atomic<T> &var,
68 std::memory_order mo = std::memory_order_seq_cst)
69 : m_atomic(var), m_value(var.load(load_part(mo))), m_mo(mo) {}
70
71 Q_NODISCARD_CTOR
72 explicit constexpr
73 QAtomicScopedValueRollback(std::atomic<T> &var, T value,
74 std::memory_order mo = std::memory_order_seq_cst)
75 : m_atomic(var), m_value(var.exchange(value, mo)), m_mo(mo) {}
76
77 //
78 // Q(Basic)AtomicInteger:
79 //
80 Q_NODISCARD_CTOR
81 explicit constexpr
82 QAtomicScopedValueRollback(QBasicAtomicInteger<T> &var,
83 std::memory_order mo = std::memory_order_seq_cst)
84 : QAtomicScopedValueRollback(var._q_value, mo) {}
85
86 Q_NODISCARD_CTOR
87 explicit constexpr
88 QAtomicScopedValueRollback(QBasicAtomicInteger<T> &var, T value,
89 std::memory_order mo = std::memory_order_seq_cst)
90 : QAtomicScopedValueRollback(var._q_value, value, mo) {}
91
92 //
93 // Q(Basic)AtomicPointer:
94 //
95 Q_NODISCARD_CTOR
96 explicit constexpr
97 QAtomicScopedValueRollback(QBasicAtomicPointer<std::remove_pointer_t<T>> &var,
98 std::memory_order mo = std::memory_order_seq_cst)
99 : QAtomicScopedValueRollback(var._q_value, mo) {}
100
101 Q_NODISCARD_CTOR
102 explicit constexpr
103 QAtomicScopedValueRollback(QBasicAtomicPointer<std::remove_pointer_t<T>> &var, T value,
104 std::memory_order mo = std::memory_order_seq_cst)
105 : QAtomicScopedValueRollback(var._q_value, value, mo) {}
106
107 ~QAtomicScopedValueRollback()
108 {
109 m_atomic.store(m_value, store_part(mo: m_mo));
110 }
111
112 void commit()
113 {
114 m_value = m_atomic.load(load_part(mo: m_mo));
115 }
116};
117
118template <typename T>
119QAtomicScopedValueRollback(QBasicAtomicPointer<T> &)
120 -> QAtomicScopedValueRollback<T*>;
121template <typename T>
122QAtomicScopedValueRollback(QBasicAtomicPointer<T> &, std::memory_order)
123 -> QAtomicScopedValueRollback<T*>;
124
125QT_END_NAMESPACE
126
127#endif // QATOMICASCOPEDVALUEROLLBACK_H
128

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtbase/src/corelib/tools/qatomicscopedvaluerollback.h