1 | // Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #if 0 |
5 | #pragma qt_sync_skip_header_check |
6 | #pragma qt_sync_stop_processing |
7 | #endif |
8 | |
9 | #ifndef QSHAREDDATA_IMPL_H |
10 | #define QSHAREDDATA_IMPL_H |
11 | |
12 | #include <QtCore/qglobal.h> |
13 | #include <QtCore/qshareddata.h> |
14 | |
15 | QT_BEGIN_NAMESPACE |
16 | |
17 | namespace QtPrivate { |
18 | |
19 | template <typename T> |
20 | class QExplicitlySharedDataPointerV2 |
21 | { |
22 | T *d; |
23 | |
24 | public: |
25 | constexpr QExplicitlySharedDataPointerV2() noexcept : d(nullptr) {} |
26 | |
27 | explicit QExplicitlySharedDataPointerV2(T *t) noexcept |
28 | : d(t) |
29 | { |
30 | if (d) |
31 | d->ref.ref(); |
32 | } |
33 | |
34 | QExplicitlySharedDataPointerV2(T *t, QAdoptSharedDataTag) noexcept |
35 | : d(t) |
36 | { |
37 | } |
38 | |
39 | QExplicitlySharedDataPointerV2(const QExplicitlySharedDataPointerV2 &other) noexcept |
40 | : d(other.d) |
41 | { |
42 | if (d) |
43 | d->ref.ref(); |
44 | } |
45 | |
46 | QExplicitlySharedDataPointerV2 &operator=(const QExplicitlySharedDataPointerV2 &other) noexcept |
47 | { |
48 | QExplicitlySharedDataPointerV2 copy(other); |
49 | swap(other&: copy); |
50 | return *this; |
51 | } |
52 | |
53 | QExplicitlySharedDataPointerV2(QExplicitlySharedDataPointerV2 &&other) noexcept |
54 | : d(std::exchange(other.d, nullptr)) |
55 | { |
56 | } |
57 | |
58 | QExplicitlySharedDataPointerV2 &operator=(QExplicitlySharedDataPointerV2 &&other) noexcept |
59 | { |
60 | QExplicitlySharedDataPointerV2 moved(std::move(other)); |
61 | swap(other&: moved); |
62 | return *this; |
63 | } |
64 | |
65 | ~QExplicitlySharedDataPointerV2() |
66 | { |
67 | if (d && !d->ref.deref()) |
68 | delete d; |
69 | } |
70 | |
71 | void detach() |
72 | { |
73 | if (!d) { |
74 | // should this codepath be here on in all user's detach()? |
75 | d = new T; |
76 | d->ref.ref(); |
77 | } else if (d->ref.loadRelaxed() != 1) { |
78 | // TODO: qAtomicDetach here...? |
79 | QExplicitlySharedDataPointerV2 copy(new T(*d)); |
80 | swap(other&: copy); |
81 | } |
82 | } |
83 | |
84 | void reset(T *t = nullptr) noexcept |
85 | { |
86 | if (d && !d->ref.deref()) |
87 | delete d; |
88 | d = t; |
89 | if (d) |
90 | d->ref.ref(); |
91 | } |
92 | |
93 | constexpr T *take() noexcept |
94 | { |
95 | return std::exchange(d, nullptr); |
96 | } |
97 | |
98 | bool isShared() const noexcept |
99 | { |
100 | return d && d->ref.loadRelaxed() != 1; |
101 | } |
102 | |
103 | constexpr void swap(QExplicitlySharedDataPointerV2 &other) noexcept |
104 | { |
105 | qt_ptr_swap(d, other.d); |
106 | } |
107 | |
108 | // important change from QExplicitlySharedDataPointer: deep const |
109 | constexpr T &operator*() { return *d; } |
110 | constexpr T *operator->() { return d; } |
111 | constexpr const T &operator*() const { return *d; } |
112 | constexpr const T *operator->() const { return d; } |
113 | |
114 | constexpr T *data() noexcept { return d; } |
115 | constexpr const T *data() const noexcept { return d; } |
116 | |
117 | constexpr explicit operator bool() const noexcept { return d; } |
118 | |
119 | constexpr friend bool operator==(const QExplicitlySharedDataPointerV2 &lhs, |
120 | const QExplicitlySharedDataPointerV2 &rhs) noexcept |
121 | { |
122 | return lhs.d == rhs.d; |
123 | } |
124 | |
125 | constexpr friend bool operator!=(const QExplicitlySharedDataPointerV2 &lhs, |
126 | const QExplicitlySharedDataPointerV2 &rhs) noexcept |
127 | { |
128 | return lhs.d != rhs.d; |
129 | } |
130 | }; |
131 | |
132 | template <typename T> |
133 | constexpr void swap(QExplicitlySharedDataPointerV2<T> &lhs, QExplicitlySharedDataPointerV2<T> &rhs) noexcept |
134 | { |
135 | lhs.swap(rhs); |
136 | } |
137 | |
138 | } // namespace QtPrivate |
139 | |
140 | QT_END_NAMESPACE |
141 | |
142 | #endif // QSHAREDDATA_IMPL_H |
143 | |