1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QSHAREDHANDLE_P_H
5#define QSHAREDHANDLE_P_H
6
7#include <QtCore/private/quniquehandle_p.h>
8#include <QtCore/qtconfigmacros.h>
9#include <QtCore/qcompare.h>
10
11#if __cpp_lib_concepts
12# include <concepts>
13#endif
14
15//
16// W A R N I N G
17// -------------
18//
19// This file is not part of the Qt API. It exists purely as an
20// implementation detail. This header file may change from version to
21// version without notice, or even be removed.
22//
23// We mean it.
24//
25
26QT_BEGIN_NAMESPACE
27
28namespace QtPrivate {
29
30#if __cpp_lib_concepts
31
32// clang-format off
33
34// Define a concept for the traits
35template <typename T>
36concept QSharedHandleTraitsConcept = requires
37{
38 typename T::Type;
39
40 { T::invalidValue() } noexcept -> std::same_as<typename T::Type>;
41 { T::ref(std::declval<typename T::Type>()) } -> std::same_as<typename T::Type>;
42 { T::unref(std::declval<typename T::Type>()) } -> std::same_as<bool>;
43};
44
45// clang-format on
46
47#endif
48
49#if __cpp_lib_concepts
50template <QSharedHandleTraitsConcept SharedHandleTraits>
51#else
52template <typename SharedHandleTraits>
53#endif
54struct UniqueHandleTraitsFromSharedHandleTraits
55{
56 using Type = typename SharedHandleTraits::Type;
57
58 [[nodiscard]] static Type invalidValue() noexcept(noexcept(SharedHandleTraits::invalidValue()))
59 {
60 return SharedHandleTraits::invalidValue();
61 }
62
63 [[nodiscard]] static bool
64 close(Type handle) noexcept(noexcept(SharedHandleTraits::unref(handle)))
65 {
66 return SharedHandleTraits::unref(handle);
67 }
68};
69
70#if __cpp_lib_concepts
71template <QSharedHandleTraitsConcept HandleTraits>
72#else
73template <typename HandleTraits>
74#endif
75struct QSharedHandle : private QUniqueHandle<UniqueHandleTraitsFromSharedHandleTraits<HandleTraits>>
76{
77private:
78 using BaseClass = QUniqueHandle<UniqueHandleTraitsFromSharedHandleTraits<HandleTraits>>;
79
80 static constexpr bool BaseResetIsNoexcept =
81 noexcept(std::declval<BaseClass>().reset(std::declval<typename HandleTraits::Type>()));
82
83 static constexpr bool RefIsNoexcept =
84 noexcept(HandleTraits::ref(std::declval<typename HandleTraits::Type>()));
85
86 static constexpr bool BaseMoveIsNoexcept =
87 noexcept(std::declval<BaseClass>().operator=(std::move(std::declval<BaseClass>())));
88
89public:
90 using typename BaseClass::Type;
91
92 enum RefMode : uint8_t
93 {
94 HasRef,
95 NeedsRef,
96
97 // syntactic sugar
98 AddRef = NeedsRef,
99 NoAddRef = HasRef,
100 };
101
102 QSharedHandle() = default;
103
104 explicit QSharedHandle(typename HandleTraits::Type object, RefMode mode)
105 : BaseClass{ mode == NeedsRef ? HandleTraits::ref(object) : object }
106 {
107 }
108
109 QSharedHandle(const QSharedHandle &o)
110 : BaseClass{
111 HandleTraits::ref(o.get()),
112 }
113 {
114 }
115
116 QSharedHandle(QSharedHandle &&) noexcept = default;
117
118 // NOLINTNEXTLINE: bugprone-unhandled-self-assign
119 QSharedHandle &operator=(const QSharedHandle &o) noexcept(RefIsNoexcept && BaseResetIsNoexcept)
120 {
121 if (BaseClass::get() != o.get())
122 BaseClass::reset(HandleTraits::ref(o.get()));
123 return *this;
124 };
125
126 QSharedHandle &operator=(QSharedHandle &&o) noexcept(BaseMoveIsNoexcept)
127 {
128 BaseClass::operator=(std::forward<QSharedHandle>(o));
129 return *this;
130 }
131
132 void reset(typename HandleTraits::Type o,
133 RefMode mode) noexcept(RefIsNoexcept && BaseResetIsNoexcept)
134 {
135 if (mode == NeedsRef)
136 BaseClass::reset(HandleTraits::ref(o));
137 else
138 BaseClass::reset(o);
139 }
140
141 void reset() noexcept(BaseResetIsNoexcept) { BaseClass::reset(); }
142
143 [[nodiscard]] friend bool operator==(const QSharedHandle &lhs,
144 const QSharedHandle &rhs) noexcept
145 {
146 return lhs.get() == rhs.get();
147 }
148
149 [[nodiscard]] friend bool operator!=(const QSharedHandle &lhs,
150 const QSharedHandle &rhs) noexcept
151 {
152 return lhs.get() != rhs.get();
153 }
154
155 [[nodiscard]] friend bool operator<(const QSharedHandle &lhs, const QSharedHandle &rhs) noexcept
156 {
157 return lhs.get() < rhs.get();
158 }
159
160 [[nodiscard]] friend bool operator<=(const QSharedHandle &lhs,
161 const QSharedHandle &rhs) noexcept
162 {
163 return lhs.get() <= rhs.get();
164 }
165
166 [[nodiscard]] friend bool operator>(const QSharedHandle &lhs, const QSharedHandle &rhs) noexcept
167 {
168 return lhs.get() > rhs.get();
169 }
170
171 [[nodiscard]] friend bool operator>=(const QSharedHandle &lhs,
172 const QSharedHandle &rhs) noexcept
173 {
174 return lhs.get() >= rhs.get();
175 }
176
177 using BaseClass::get;
178 using BaseClass::isValid;
179 using BaseClass::operator bool;
180 using BaseClass::release;
181 using BaseClass::operator&;
182
183 void swap(QSharedHandle &other) noexcept(noexcept(std::declval<BaseClass>().swap(other)))
184 {
185 BaseClass::swap(other);
186 }
187};
188
189template <typename Trait>
190void swap(QSharedHandle<Trait> &lhs, QSharedHandle<Trait> &rhs) noexcept(noexcept(lhs.swap(rhs)))
191{
192 lhs.swap(rhs);
193}
194
195} // namespace QtPrivate
196
197QT_END_NAMESPACE
198
199#endif // QSHAREDHANDLE_P_H
200

source code of qtmultimedia/src/multimedia/qsharedhandle_p.h