Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
quniquehandle_p.h
Go to the documentation of this file.
1
// Copyright (C) 2023 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
// Qt-Security score:significant reason:default
4
5
#
ifndef
QUNIQUEHANDLE_P_H
6
#
define
QUNIQUEHANDLE_P_H
7
8
//
9
// W A R N I N G
10
// -------------
11
//
12
// This file is not part of the Qt API. It exists purely as an
13
// implementation detail. This header file may change from version to
14
// version without notice, or even be removed.
15
//
16
// We mean it.
17
//
18
19
#
include
<
QtCore
/
qtconfigmacros
.
h
>
20
#
include
<
QtCore
/
qassert
.
h
>
21
#
include
<
QtCore
/
qcompare
.
h
>
22
#
include
<
QtCore
/
qfunctionaltools_impl
.
h
>
23
#
include
<
QtCore
/
qswap
.
h
>
24
#
include
<
QtCore
/
qtclasshelpermacros
.
h
>
25
26
#
include
<
memory
>
27
#
include
<
utility
>
28
#
include
<
type_traits
>
29
30
QT_BEGIN_NAMESPACE
31
32
/*! \internal QUniqueHandle is a general purpose RAII wrapper intended
33
for interfacing with resource-allocating C-style APIs, for example
34
operating system APIs, database engine APIs, or any other scenario
35
where resources are allocated and released, and where pointer
36
semantics does not seem a perfect fit.
37
38
QUniqueHandle does not support copying, because it is intended to
39
maintain ownership of resources that can not be copied. This makes
40
it safer to use than naked handle types, since ownership is
41
maintained by design.
42
43
The underlying handle object is described using a client supplied
44
HandleTraits object that is implemented per resource type. The
45
traits struct must describe two properties of a handle:
46
47
1) What value is considered invalid
48
2) How to close a resource.
49
50
Example 1:
51
52
struct InvalidHandleTraits {
53
using Type = HANDLE;
54
55
static Type invalidValue() {
56
return INVALID_HANDLE_VALUE;
57
}
58
59
static bool close(Type handle) {
60
return CloseHandle(handle) != 0;
61
}
62
}
63
64
using FileHandle = QUniqueHandle<InvalidHandleTraits>;
65
66
Usage:
67
68
// Takes ownership of returned handle.
69
FileHandle handle{ CreateFile(...) };
70
71
if (!handle.isValid()) {
72
qDebug() << GetLastError()
73
return;
74
}
75
76
...
77
78
Example 2:
79
80
struct SqLiteTraits {
81
using Type = sqlite3*;
82
83
static Type invalidValue() {
84
return nullptr;
85
}
86
87
static bool close(Type handle) {
88
sqlite3_close(handle);
89
return true;
90
}
91
}
92
93
using DbHandle = QUniqueHandle<SqLiteTraits>;
94
95
Usage:
96
97
DbHandle h;
98
99
// Take ownership of returned handle.
100
int result = sqlite3_open(":memory:", &h);
101
102
...
103
104
Example 3:
105
106
struct TempFileTraits {
107
using Type = FILE*;
108
109
static Type invalidValue() {
110
return nullptr;
111
}
112
113
static bool close(Type handle) {
114
return fclose(handle) == 0;
115
}
116
};
117
118
struct TempFileDeleter {
119
using Type = TempFileTraits::Type;
120
121
void operator()(Type handle) {
122
if (handle != TempFileTraits::invalidValue()) {
123
TempFileTraits::close(handle);
124
if (path)
125
remove(path);
126
}
127
}
128
129
const char* path{ nullptr };
130
};
131
132
using TempFileHandle = QUniqueHandle<TempFileTraits, TempFileDeleter>;
133
134
Usage:
135
136
TempFileHandle tempFile(fopen("temp.bin", "wb"), TempFileDeleter{ "my_temp.bin" });
137
138
...
139
140
NOTE: The QUniqueHandle assumes that closing a resource is
141
guaranteed to succeed, and provides no support for handling failure
142
to close a resource. It is therefore only recommended for use cases
143
where failure to close a resource is either not an error, or an
144
unrecoverable error.
145
*/
146
147
// clang-format off
148
149
namespace
QtUniqueHandleTraits
{
150
151
template
<
typename
HandleTraits>
152
struct
DefaultDeleter
153
{
154
using
Type
=
typename
HandleTraits::
Type
;
155
156
void
operator
()(
Type
handle)
const
noexcept
157
{
158
if
(handle != HandleTraits::invalidValue()) {
159
const
bool
success = HandleTraits::close(handle);
160
Q_ASSERT(success);
161
}
162
}
163
};
164
165
}
// namespace QtUniqueHandleTraits
166
167
template
<
typename
HandleTraits,
typename
Deleter = QtUniqueHandleTraits::DefaultDeleter<HandleTraits>>
168
class
QUniqueHandle
:
private
QtPrivate
::
CompactStorage
<
Deleter
>
169
{
170
using
Storage
=
QtPrivate
::
CompactStorage
<
Deleter
>;
171
172
template
<
typename
D
>
173
using
if_default_constructible
=
std
::
enable_if_t
<
std
::
is_default_constructible_v
<
D
>,
bool
>;
174
175
public
:
176
using
Type
=
typename
HandleTraits::
Type
;
177
static_assert
(
std
::is_nothrow_default_constructible_v<
Type
>);
178
static_assert
(
std
::is_nothrow_constructible_v<
Type
>);
179
static_assert
(
std
::is_nothrow_copy_constructible_v<
Type
>);
180
static_assert
(
std
::is_nothrow_move_constructible_v<
Type
>);
181
static_assert
(
std
::is_nothrow_copy_assignable_v<
Type
>);
182
static_assert
(
std
::is_nothrow_move_assignable_v<
Type
>);
183
static_assert
(
std
::is_nothrow_destructible_v<
Type
>);
184
static_assert
(
std
::is_nothrow_copy_constructible_v<Deleter>);
185
static_assert
(
std
::is_nothrow_move_constructible_v<Deleter>);
186
static_assert
(
std
::is_nothrow_copy_assignable_v<Deleter>);
187
static_assert
(
std
::is_nothrow_move_assignable_v<Deleter>);
188
static_assert
(
std
::is_nothrow_destructible_v<Deleter>);
189
static_assert
(
noexcept
(
std
::declval<
Type
>() ==
std
::declval<
Type
>()));
190
static_assert
(
noexcept
(
std
::declval<
Type
>() !=
std
::declval<
Type
>()));
191
static_assert
(
noexcept
(
std
::declval<
Type
>() <
std
::declval<
Type
>()));
192
static_assert
(
noexcept
(
std
::declval<
Type
>() <=
std
::declval<
Type
>()));
193
static_assert
(
noexcept
(
std
::declval<
Type
>() >
std
::declval<
Type
>()));
194
static_assert
(
noexcept
(
std
::declval<
Type
>() >=
std
::declval<
Type
>()));
195
196
template
<if_default_constructible<Deleter> =
true
>
197
QUniqueHandle
()
noexcept
198
{}
199
200
template
<if_default_constructible<Deleter> =
true
>
201
explicit
QUniqueHandle
(
const
Type
&handle)
noexcept
202
: m_handle{ handle }
203
{}
204
205
QUniqueHandle
(
const
Type
&handle,
const
Deleter &deleter)
noexcept
206
:
Storage
{
deleter
}, m_handle{ handle }
207
{}
208
209
QUniqueHandle
(
const
Type
&handle, Deleter &&deleter)
noexcept
210
:
Storage
{
std
::
move
(
deleter
) }, m_handle{ handle }
211
{}
212
213
QUniqueHandle
(
QUniqueHandle
&&other)
noexcept
214
:
Storage
{
std
::
move
(
other
.
deleter
()) }, m_handle{ other
.
release
(
)
}
215
{
216
}
217
218
~
QUniqueHandle
()
noexcept
219
{
220
close
(
)
;
221
}
222
223
void
swap
(
QUniqueHandle
&other)
noexcept
224
{
225
qSwap(m_handle, other.m_handle);
226
qSwap(deleter(), other.deleter());
227
}
228
229
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP
(
QUniqueHandle
)
230
231
QUniqueHandle
(
const
QUniqueHandle
&) =
delete
;
232
QUniqueHandle
&
operator
=(
const
QUniqueHandle
&) =
delete
;
233
234
235
[[nodiscard]]
bool
isValid
()
const
noexcept
236
{
237
return
m_handle != HandleTraits::invalidValue();
238
}
239
240
[[nodiscard]]
explicit
operator
bool
()
const
noexcept
241
{
242
return
isValid
(
)
;
243
}
244
245
[[nodiscard]]
Type
get
()
const
noexcept
246
{
247
return
m_handle;
248
}
249
250
[[nodiscard]] Deleter&
deleter
()
noexcept
251
{
252
return
Storage::object();
253
}
254
255
[[nodiscard]]
const
Deleter&
deleter
()
const
noexcept
256
{
257
return
Storage::object();
258
}
259
260
void
reset
(
const
Type
& handle = HandleTraits::invalidValue())
noexcept
261
{
262
if
(handle == m_handle)
263
return
;
264
265
close
(
)
;
266
m_handle = handle;
267
}
268
269
[[nodiscard]]
Type
release
()
noexcept
270
{
271
return
std
::exchange(m_handle, HandleTraits::invalidValue());
272
}
273
274
[[nodiscard]]
Type
*
operator
&()
noexcept
// NOLINT(google-runtime-operator)
275
{
276
Q_ASSERT(!
isValid
(
)
);
277
return
&m_handle;
278
}
279
280
void
close
()
noexcept
281
{
282
if
(!
isValid
(
)
)
283
return
;
284
285
deleter()(m_handle);
286
287
m_handle = HandleTraits::invalidValue();
288
}
289
290
private
:
291
friend
bool
comparesEqual
(
const
QUniqueHandle
& lhs,
const
QUniqueHandle
& rhs)
noexcept
292
{
293
return
lhs
.
get
(
)
== rhs
.
get
(
)
;
294
}
295
296
friend
Qt
::
strong_ordering
compareThreeWay
(
const
QUniqueHandle
& lhs,
297
const
QUniqueHandle
& rhs)
noexcept
298
{
299
if
constexpr
(
std
::is_pointer_v<
Type
>)
300
return
qCompareThreeWay(Qt::totally_ordered_wrapper{ lhs.get() },
301
Qt::totally_ordered_wrapper{ rhs.get() });
302
else
303
return
qCompareThreeWay(lhs
.
get
(
)
, rhs
.
get
(
)
);
304
}
305
306
Q_DECLARE_STRONGLY_ORDERED
(
QUniqueHandle
)
307
308
Type
m_handle{ HandleTraits::invalidValue() };
309
};
310
311
// clang-format on
312
313
template
<
typename
Trait,
typename
Deleter>
314
void
swap
(
QUniqueHandle
<Trait, Deleter> &lhs,
QUniqueHandle
<Trait, Deleter> &rhs)
noexcept
315
{
316
lhs.swap(rhs);
317
}
318
319
320
QT_END_NAMESPACE
321
322
#
endif
QUniqueHandle
Definition
quniquehandle_p.h:169
QUniqueHandle::get
Type get() const noexcept
Definition
quniquehandle_p.h:245
QUniqueHandle::operator bool
operator bool() const noexcept
Definition
quniquehandle_p.h:240
QUniqueHandle::compareThreeWay
friend Qt::strong_ordering compareThreeWay(const QUniqueHandle &lhs, const QUniqueHandle &rhs) noexcept
Definition
quniquehandle_p.h:296
QUniqueHandle::swap
void swap(QUniqueHandle &other) noexcept
Definition
quniquehandle_p.h:223
QUniqueHandle::comparesEqual
friend bool comparesEqual(const QUniqueHandle &lhs, const QUniqueHandle &rhs) noexcept
Definition
quniquehandle_p.h:291
QUniqueHandle::QUniqueHandle
QUniqueHandle() noexcept
Definition
quniquehandle_p.h:197
QUniqueHandle::QUniqueHandle
QUniqueHandle(QUniqueHandle &&other) noexcept
Definition
quniquehandle_p.h:213
QUniqueHandle::isValid
bool isValid() const noexcept
Definition
quniquehandle_p.h:235
QUniqueHandle::deleter
const Deleter & deleter() const noexcept
Definition
quniquehandle_p.h:255
QUniqueHandle::~QUniqueHandle
~QUniqueHandle() noexcept
Definition
quniquehandle_p.h:218
QUniqueHandle::QUniqueHandle
QUniqueHandle(const Type &handle, const Deleter &deleter) noexcept
Definition
quniquehandle_p.h:205
QUniqueHandle::reset
void reset(const Type &handle=HandleTraits::invalidValue()) noexcept
Definition
quniquehandle_p.h:260
QUniqueHandle::QUniqueHandle
QUniqueHandle(const Type &handle, Deleter &&deleter) noexcept
Definition
quniquehandle_p.h:209
QUniqueHandle::operator=
QUniqueHandle & operator=(const QUniqueHandle &)=delete
QUniqueHandle::operator&
Type * operator&() noexcept
Definition
quniquehandle_p.h:274
QUniqueHandle::deleter
Deleter & deleter() noexcept
Definition
quniquehandle_p.h:250
QUniqueHandle::close
void close() noexcept
Definition
quniquehandle_p.h:280
QUniqueHandle::QUniqueHandle
QUniqueHandle(const Type &handle) noexcept
Definition
quniquehandle_p.h:201
QUniqueHandle::release
Type release() noexcept
Definition
quniquehandle_p.h:269
QUniqueHandle::Type
typename HandleTraits::Type Type
Definition
quniquehandle_p.h:176
QtUniqueHandleTraits
Definition
quniquehandle_types_windows.cpp:9
std
[33]
Definition
src_corelib_tools_qhash.cpp:421
swap
void swap(QUniqueHandle< Trait, Deleter > &lhs, QUniqueHandle< Trait, Deleter > &rhs) noexcept
Definition
quniquehandle_p.h:314
QtUniqueHandleTraits::DefaultDeleter
Definition
quniquehandle_p.h:153
QtUniqueHandleTraits::DefaultDeleter::operator()
void operator()(Type handle) const noexcept
Definition
quniquehandle_p.h:156
QtUniqueHandleTraits::DefaultDeleter::Type
typename HandleTraits::Type Type
Definition
quniquehandle_p.h:154
qtbase
src
corelib
tools
quniquehandle_p.h
Generated on
for Qt by
1.18.0