Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/QtCore/qatomicscopedvaluerollback.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Copyright (C) 2022 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 
0004 #ifndef QATOMICSCOPEDVALUEROLLBACK_H
0005 #define QATOMICSCOPEDVALUEROLLBACK_H
0006 
0007 #include <QtCore/qassert.h>
0008 #include <QtCore/qatomic.h>
0009 #include <QtCore/qcompilerdetection.h>
0010 #include <QtCore/qtclasshelpermacros.h>
0011 #include <QtCore/qtconfigmacros.h>
0012 
0013 #include <atomic>
0014 
0015 QT_BEGIN_NAMESPACE
0016 
0017 template <typename T>
0018 class QAtomicScopedValueRollback
0019 {
0020     std::atomic<T> &m_atomic;
0021     T m_value;
0022     std::memory_order m_mo;
0023 
0024     Q_DISABLE_COPY_MOVE(QAtomicScopedValueRollback)
0025 
0026     static constexpr std::memory_order store_part(std::memory_order mo) noexcept
0027     {
0028         switch (mo) {
0029         case std::memory_order_relaxed:
0030         case std::memory_order_consume:
0031         case std::memory_order_acquire: return std::memory_order_relaxed;
0032         case std::memory_order_release:
0033         case std::memory_order_acq_rel: return std::memory_order_release;
0034         case std::memory_order_seq_cst: return std::memory_order_seq_cst;
0035         }
0036         // GCC 8.x does not treat __builtin_unreachable() as constexpr
0037 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
0038         // NOLINTNEXTLINE(qt-use-unreachable-return): Triggers on Clang, breaking GCC 8
0039         Q_UNREACHABLE();
0040 #endif
0041         return std::memory_order_seq_cst;
0042     }
0043 
0044     static constexpr std::memory_order load_part(std::memory_order mo) noexcept
0045     {
0046         switch (mo) {
0047         case std::memory_order_relaxed:
0048         case std::memory_order_release: return std::memory_order_relaxed;
0049         case std::memory_order_consume: return std::memory_order_consume;
0050         case std::memory_order_acquire:
0051         case std::memory_order_acq_rel: return std::memory_order_acquire;
0052         case std::memory_order_seq_cst: return std::memory_order_seq_cst;
0053         }
0054         // GCC 8.x does not treat __builtin_unreachable() as constexpr
0055 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
0056         // NOLINTNEXTLINE(qt-use-unreachable-return): Triggers on Clang, breaking GCC 8
0057         Q_UNREACHABLE();
0058 #endif
0059         return std::memory_order_seq_cst;
0060     }
0061 public:
0062     //
0063     // std::atomic:
0064     //
0065     Q_NODISCARD_CTOR
0066     explicit constexpr
0067     QAtomicScopedValueRollback(std::atomic<T> &var,
0068                                std::memory_order mo = std::memory_order_seq_cst)
0069         : m_atomic(var), m_value(var.load(load_part(mo))), m_mo(mo) {}
0070 
0071     Q_NODISCARD_CTOR
0072     explicit constexpr
0073     QAtomicScopedValueRollback(std::atomic<T> &var, T value,
0074                                std::memory_order mo = std::memory_order_seq_cst)
0075         : m_atomic(var), m_value(var.exchange(value, mo)), m_mo(mo) {}
0076 
0077     //
0078     // Q(Basic)AtomicInteger:
0079     //
0080     Q_NODISCARD_CTOR
0081     explicit constexpr
0082     QAtomicScopedValueRollback(QBasicAtomicInteger<T> &var,
0083                                std::memory_order mo = std::memory_order_seq_cst)
0084         : QAtomicScopedValueRollback(var._q_value, mo) {}
0085 
0086     Q_NODISCARD_CTOR
0087     explicit constexpr
0088     QAtomicScopedValueRollback(QBasicAtomicInteger<T> &var, T value,
0089                                std::memory_order mo = std::memory_order_seq_cst)
0090         : QAtomicScopedValueRollback(var._q_value, value, mo) {}
0091 
0092     //
0093     // Q(Basic)AtomicPointer:
0094     //
0095     Q_NODISCARD_CTOR
0096     explicit constexpr
0097     QAtomicScopedValueRollback(QBasicAtomicPointer<std::remove_pointer_t<T>> &var,
0098                                std::memory_order mo = std::memory_order_seq_cst)
0099         : QAtomicScopedValueRollback(var._q_value, mo) {}
0100 
0101     Q_NODISCARD_CTOR
0102     explicit constexpr
0103     QAtomicScopedValueRollback(QBasicAtomicPointer<std::remove_pointer_t<T>> &var, T value,
0104                                std::memory_order mo = std::memory_order_seq_cst)
0105         : QAtomicScopedValueRollback(var._q_value, value, mo) {}
0106 
0107     ~QAtomicScopedValueRollback()
0108     {
0109         m_atomic.store(m_value, store_part(m_mo));
0110     }
0111 
0112     void commit()
0113     {
0114         m_value = m_atomic.load(load_part(m_mo));
0115     }
0116 };
0117 
0118 template <typename T>
0119 QAtomicScopedValueRollback(QBasicAtomicPointer<T> &)
0120     -> QAtomicScopedValueRollback<T*>;
0121 template <typename T>
0122 QAtomicScopedValueRollback(QBasicAtomicPointer<T> &, std::memory_order)
0123     -> QAtomicScopedValueRollback<T*>;
0124 
0125 QT_END_NAMESPACE
0126 
0127 #endif // QATOMICASCOPEDVALUEROLLBACK_H