1/****************************************************************************
2**
3** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#if 0
41#pragma qt_sync_skip_header_check
42#pragma qt_sync_stop_processing
43#endif
44
45#ifndef QSHAREDDATA_IMPL_H
46#define QSHAREDDATA_IMPL_H
47
48#include <QtCore/qglobal.h>
49#include <QtCore/qshareddata.h>
50
51QT_BEGIN_NAMESPACE
52
53namespace QtPrivate {
54
55template <typename T>
56class QExplicitlySharedDataPointerV2
57{
58 T *d;
59
60public:
61 constexpr QExplicitlySharedDataPointerV2() noexcept : d(nullptr) {}
62
63 explicit QExplicitlySharedDataPointerV2(T *t) noexcept
64 : d(t)
65 {
66 if (d)
67 d->ref.ref();
68 }
69
70 QExplicitlySharedDataPointerV2(T *t, QAdoptSharedDataTag) noexcept
71 : d(t)
72 {
73 }
74
75 QExplicitlySharedDataPointerV2(const QExplicitlySharedDataPointerV2 &other) noexcept
76 : d(other.d)
77 {
78 if (d)
79 d->ref.ref();
80 }
81
82 QExplicitlySharedDataPointerV2 &operator=(const QExplicitlySharedDataPointerV2 &other) noexcept
83 {
84 QExplicitlySharedDataPointerV2 copy(other);
85 swap(copy);
86 return *this;
87 }
88
89 QExplicitlySharedDataPointerV2(QExplicitlySharedDataPointerV2 &&other) noexcept
90 : d(qExchange(other.d, nullptr))
91 {
92 }
93
94 QExplicitlySharedDataPointerV2 &operator=(QExplicitlySharedDataPointerV2 &&other) noexcept
95 {
96 QExplicitlySharedDataPointerV2 moved(std::move(other));
97 swap(moved);
98 return *this;
99 }
100
101 ~QExplicitlySharedDataPointerV2()
102 {
103 if (d && !d->ref.deref())
104 delete d;
105 }
106
107 void detach()
108 {
109 if (!d) {
110 // should this codepath be here on in all user's detach()?
111 d = new T;
112 d->ref.ref();
113 } else if (d->ref.loadRelaxed() != 1) {
114 // TODO: qAtomicDetach here...?
115 QExplicitlySharedDataPointerV2 copy(new T(*d));
116 swap(copy);
117 }
118 }
119
120 void reset(T *t = nullptr) noexcept
121 {
122 if (d && !d->ref.deref())
123 delete d;
124 d = t;
125 if (d)
126 d->ref.ref();
127 }
128
129 constexpr T *take() noexcept
130 {
131 return qExchange(d, nullptr);
132 }
133
134 bool isShared() const noexcept
135 {
136 return d && d->ref.loadRelaxed() != 1;
137 }
138
139 constexpr void swap(QExplicitlySharedDataPointerV2 &other) noexcept
140 {
141 qSwap(d, other.d);
142 }
143
144 // important change from QExplicitlySharedDataPointer: deep const
145 constexpr T &operator*() { return *d; }
146 constexpr T *operator->() { return d; }
147 constexpr const T &operator*() const { return *d; }
148 constexpr const T *operator->() const { return d; }
149
150 constexpr T *data() noexcept { return d; }
151 constexpr const T *data() const noexcept { return d; }
152
153 constexpr explicit operator bool() const noexcept { return d; }
154
155 constexpr friend bool operator==(const QExplicitlySharedDataPointerV2 &lhs,
156 const QExplicitlySharedDataPointerV2 &rhs) noexcept
157 {
158 return lhs.d == rhs.d;
159 }
160
161 constexpr friend bool operator!=(const QExplicitlySharedDataPointerV2 &lhs,
162 const QExplicitlySharedDataPointerV2 &rhs) noexcept
163 {
164 return lhs.d != rhs.d;
165 }
166};
167
168template <typename T>
169constexpr void swap(QExplicitlySharedDataPointerV2<T> &lhs, QExplicitlySharedDataPointerV2<T> &rhs) noexcept
170{
171 lhs.swap(rhs);
172}
173
174} // namespace QtPrivate
175
176QT_END_NAMESPACE
177
178#endif // QSHAREDDATA_IMPL_H
179