5#ifndef QATOMICSCOPEDVALUEROLLBACK_H
6#define QATOMICSCOPEDVALUEROLLBACK_H
8#include <QtCore/qassert.h>
9#include <QtCore/qatomic.h>
10#include <QtCore/qcompilerdetection.h>
11#include <QtCore/qtclasshelpermacros.h>
12#include <QtCore/qtconfigmacros.h>
20class QAtomicScopedValueRollback
22 std::atomic<T> &m_atomic;
24 std::memory_order m_mo;
26 Q_DISABLE_COPY_MOVE(QAtomicScopedValueRollback)
28 static constexpr std::memory_order store_part(std::memory_order mo)
noexcept
31 case std::memory_order_relaxed:
32 case std::memory_order_consume:
33 case std::memory_order_acquire:
return std::memory_order_relaxed;
34 case std::memory_order_release:
35 case std::memory_order_acq_rel:
return std::memory_order_release;
36 case std::memory_order_seq_cst:
return std::memory_order_seq_cst;
39#if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
43 return std::memory_order_seq_cst;
46 static constexpr std::memory_order load_part(std::memory_order mo)
noexcept
49 case std::memory_order_relaxed:
50 case std::memory_order_release:
return std::memory_order_relaxed;
51 case std::memory_order_consume:
return std::memory_order_consume;
52 case std::memory_order_acquire:
53 case std::memory_order_acq_rel:
return std::memory_order_acquire;
54 case std::memory_order_seq_cst:
return std::memory_order_seq_cst;
57#if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
61 return std::memory_order_seq_cst;
69 QAtomicScopedValueRollback(std::atomic<T> &var,
70 std::memory_order mo = std::memory_order_seq_cst)
71 : m_atomic(var), m_value(var.load(load_part(mo))), m_mo(mo) {}
75 QAtomicScopedValueRollback(std::atomic<T> &var, T value,
76 std::memory_order mo = std::memory_order_seq_cst)
77 : m_atomic(var), m_value(var.exchange(std::move(value), mo)), m_mo(mo) {}
84 QAtomicScopedValueRollback(QBasicAtomicInteger<T> &var,
85 std::memory_order mo = std::memory_order_seq_cst)
86 : QAtomicScopedValueRollback(var._q_value, mo) {}
90 QAtomicScopedValueRollback(QBasicAtomicInteger<T> &var, T value,
91 std::memory_order mo = std::memory_order_seq_cst)
92 : QAtomicScopedValueRollback(var._q_value, std::move(value), mo) {}
99 QAtomicScopedValueRollback(QBasicAtomicPointer<std::remove_pointer_t<T>> &var,
100 std::memory_order mo = std::memory_order_seq_cst)
101 : QAtomicScopedValueRollback(var._q_value, mo) {}
105 QAtomicScopedValueRollback(QBasicAtomicPointer<std::remove_pointer_t<T>> &var, T value,
106 std::memory_order mo = std::memory_order_seq_cst)
107 : QAtomicScopedValueRollback(var._q_value, std::move(value), mo) {}
109 ~QAtomicScopedValueRollback()
111 m_atomic.store(std::move(m_value), store_part(m_mo));
116 m_value = m_atomic.load(load_part(m_mo));
124QAtomicScopedValueRollback(QBasicAtomicPointer<T> &, std::memory_order)
125 -> QAtomicScopedValueRollback<T*>;
127template <
typename T,
typename V,
128 std::enable_if_t<std::is_convertible_v<V, T>,
bool> =
true>
129QAtomicScopedValueRollback(std::atomic<T>&, V)
130 -> QAtomicScopedValueRollback<T>;
131template <
typename T,
typename V,
132 std::enable_if_t<std::is_convertible_v<V, T>,
bool> =
true>
133QAtomicScopedValueRollback(std::atomic<T>&, V, std::memory_order)
134 -> QAtomicScopedValueRollback<T>;
136template <
typename T,
typename V,
137 std::enable_if_t<std::is_convertible_v<V, T>,
bool> =
true>
138QAtomicScopedValueRollback(QBasicAtomicInteger<T>&, V)
139 -> QAtomicScopedValueRollback<T>;
140template <
typename T,
typename V,
141 std::enable_if_t<std::is_convertible_v<V, T>,
bool> =
true>
142QAtomicScopedValueRollback(QBasicAtomicInteger<T>&, V, std::memory_order)
143 -> QAtomicScopedValueRollback<T>;
145template <
typename T,
typename V,
146 std::enable_if_t<std::is_convertible_v<V, T*>,
bool> =
true>
147QAtomicScopedValueRollback(QBasicAtomicPointer<T>&, V)
148 -> QAtomicScopedValueRollback<T*>;
149template <
typename T,
typename V,
150 std::enable_if_t<std::is_convertible_v<V, T*>,
bool> =
true>
151QAtomicScopedValueRollback(QBasicAtomicPointer<T>&, V, std::memory_order)
152 -> QAtomicScopedValueRollback<T*>;
QAtomicScopedValueRollback(QBasicAtomicPointer< T > &) -> QAtomicScopedValueRollback< T * >