aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/ftw/qqmlrefcount_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/ftw/qqmlrefcount_p.h')
-rw-r--r--src/qml/qml/ftw/qqmlrefcount_p.h68
1 files changed, 51 insertions, 17 deletions
diff --git a/src/qml/qml/ftw/qqmlrefcount_p.h b/src/qml/qml/ftw/qqmlrefcount_p.h
index 8b4b5b1535..e7616915eb 100644
--- a/src/qml/qml/ftw/qqmlrefcount_p.h
+++ b/src/qml/qml/ftw/qqmlrefcount_p.h
@@ -21,23 +21,34 @@
QT_BEGIN_NAMESPACE
+template <typename T>
+class QQmlRefCounted;
-class Q_QML_PRIVATE_EXPORT QQmlRefCount
+class QQmlRefCount
{
Q_DISABLE_COPY_MOVE(QQmlRefCount)
public:
inline QQmlRefCount();
inline void addref() const;
- inline void release() const;
inline int count() const;
-protected:
- inline virtual ~QQmlRefCount();
+private:
+ inline ~QQmlRefCount();
+ template <typename T> friend class QQmlRefCounted;
private:
mutable QAtomicInt refCount;
};
+template <typename T>
+class QQmlRefCounted : public QQmlRefCount
+{
+public:
+ inline void release() const;
+protected:
+ inline ~QQmlRefCounted();
+};
+
template<class T>
class QQmlRefPointer
{
@@ -46,16 +57,16 @@ public:
AddRef,
Adopt
};
- inline QQmlRefPointer();
- inline QQmlRefPointer(T *, Mode m = AddRef);
- inline QQmlRefPointer(const QQmlRefPointer<T> &);
- inline QQmlRefPointer(QQmlRefPointer<T> &&);
+ Q_NODISCARD_CTOR inline QQmlRefPointer() noexcept;
+ Q_NODISCARD_CTOR inline QQmlRefPointer(T *, Mode m = AddRef);
+ Q_NODISCARD_CTOR inline QQmlRefPointer(const QQmlRefPointer &);
+ Q_NODISCARD_CTOR inline QQmlRefPointer(QQmlRefPointer &&) noexcept;
inline ~QQmlRefPointer();
void swap(QQmlRefPointer &other) noexcept { qt_ptr_swap(o, other.o); }
inline QQmlRefPointer<T> &operator=(const QQmlRefPointer<T> &o);
- inline QQmlRefPointer<T> &operator=(QQmlRefPointer<T> &&o);
+ inline QQmlRefPointer<T> &operator=(QQmlRefPointer<T> &&o) noexcept;
inline bool isNull() const { return !o; }
@@ -68,8 +79,20 @@ public:
inline T* take() { T *res = o; o = nullptr; return res; }
- friend bool operator==(const QQmlRefPointer &a, const QQmlRefPointer &b) { return a.o == b.o; }
- friend bool operator!=(const QQmlRefPointer &a, const QQmlRefPointer &b) { return !(a == b); }
+ friend bool operator==(const QQmlRefPointer &a, const QQmlRefPointer &b) noexcept
+ {
+ return a.o == b.o;
+ }
+
+ friend bool operator!=(const QQmlRefPointer &a, const QQmlRefPointer &b) noexcept
+ {
+ return !(a == b);
+ }
+
+ friend size_t qHash(const QQmlRefPointer &v, size_t seed = 0) noexcept
+ {
+ return qHash(v.o, seed);
+ }
void reset(T *t = nullptr)
{
@@ -90,7 +113,7 @@ namespace QQml {
/*!
\internal
Creates a QQmlRefPointer which takes ownership of a newly constructed T.
- T must derive from QQmlRefCount (as we rely on an initial refcount of _1_).
+ T must derive from QQmlRefCounted<T> (as we rely on an initial refcount of _1_).
T will be constructed by forwarding \a args to its constructor.
*/
template <typename T, typename ...Args>
@@ -120,11 +143,22 @@ void QQmlRefCount::addref() const
refCount.ref();
}
-void QQmlRefCount::release() const
+template <typename T>
+void QQmlRefCounted<T>::release() const
{
+ static_assert(std::is_base_of_v<QQmlRefCounted, T>,
+ "QQmlRefCounted<T> must be a base of T (CRTP)");
Q_ASSERT(refCount.loadRelaxed() > 0);
if (!refCount.deref())
- delete this;
+ delete static_cast<const T *>(this);
+}
+
+template <typename T>
+QQmlRefCounted<T>::~QQmlRefCounted()
+{
+ static_assert(std::is_final_v<T> || std::has_virtual_destructor_v<T>,
+ "T must either be marked final or have a virtual dtor, "
+ "lest release() runs into UB.");
}
int QQmlRefCount::count() const
@@ -133,7 +167,7 @@ int QQmlRefCount::count() const
}
template<class T>
-QQmlRefPointer<T>::QQmlRefPointer()
+QQmlRefPointer<T>::QQmlRefPointer() noexcept
: o(nullptr)
{
}
@@ -154,7 +188,7 @@ QQmlRefPointer<T>::QQmlRefPointer(const QQmlRefPointer<T> &other)
}
template <class T>
-QQmlRefPointer<T>::QQmlRefPointer(QQmlRefPointer<T> &&other)
+QQmlRefPointer<T>::QQmlRefPointer(QQmlRefPointer<T> &&other) noexcept
: o(other.take())
{
}
@@ -179,7 +213,7 @@ QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(const QQmlRefPointer<T> &other)
}
template <class T>
-QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(QQmlRefPointer<T> &&other)
+QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(QQmlRefPointer<T> &&other) noexcept
{
QQmlRefPointer<T> m(std::move(other));
swap(m);