1// Copyright (C) 2022 Intel Corporation.
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 QNATIVEIPCKEY_H
5#define QNATIVEIPCKEY_H
6
7#include <QtCore/qglobal.h>
8#include <QtCore/qtcore-config.h>
9
10#if QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
11# include <QtCore/qstring.h>
12# include <QtCore/qobjectdefs.h>
13
14QT_BEGIN_NAMESPACE
15
16class QNativeIpcKeyPrivate;
17class QNativeIpcKey
18{
19 Q_GADGET_EXPORT(Q_CORE_EXPORT)
20public:
21 enum class Type : quint16 {
22 // 0 is reserved for the invalid type
23 // keep 1 through 0xff free, except for SystemV
24 SystemV = 0x51, // 'Q'
25
26 PosixRealtime = 0x100,
27 Windows,
28 };
29 Q_ENUM(Type)
30
31 static constexpr Type DefaultTypeForOs =
32#ifdef Q_OS_WIN
33 Type::Windows
34#else
35 Type::PosixRealtime
36#endif
37 ;
38 static Type legacyDefaultTypeForOs() noexcept;
39
40 constexpr QNativeIpcKey() noexcept = default;
41
42 explicit constexpr QNativeIpcKey(Type type) noexcept
43 : typeAndFlags{.type: type}
44 {
45 }
46
47 Q_IMPLICIT QNativeIpcKey(const QString &k, Type type = DefaultTypeForOs)
48 : key(k), typeAndFlags{.type: type}
49 {
50 }
51
52 QNativeIpcKey(const QNativeIpcKey &other)
53 : d(other.d), key(other.key), typeAndFlags(other.typeAndFlags)
54 {
55 if (isSlowPath())
56 copy_internal(other);
57 }
58
59 QNativeIpcKey(QNativeIpcKey &&other) noexcept
60 : d(std::exchange(obj&: other.d, new_val: nullptr)), key(std::move(other.key)),
61 typeAndFlags(std::move(other.typeAndFlags))
62 {
63 if (isSlowPath())
64 move_internal(other: std::move(other));
65 }
66
67 ~QNativeIpcKey()
68 {
69 if (isSlowPath())
70 destroy_internal();
71 }
72
73 QNativeIpcKey &operator=(const QNativeIpcKey &other)
74 {
75 typeAndFlags = other.typeAndFlags;
76 key = other.key;
77 if (isSlowPath() || other.isSlowPath())
78 return assign_internal(other);
79 Q_ASSERT(!d);
80 return *this;
81 }
82
83 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QNativeIpcKey)
84 void swap(QNativeIpcKey &other) noexcept
85 {
86 std::swap(a&: d, b&: other.d);
87 key.swap(other&: other.key);
88 typeAndFlags.swap(other&: other.typeAndFlags);
89 }
90
91 bool isEmpty() const noexcept
92 {
93 return key.isEmpty();
94 }
95
96 bool isValid() const noexcept
97 {
98 return type() != Type{};
99 }
100
101 constexpr Type type() const noexcept
102 {
103 return typeAndFlags.type;
104 }
105
106 constexpr void setType(Type type)
107 {
108 if (isSlowPath())
109 return setType_internal(type);
110 typeAndFlags.type = type;
111 }
112
113 QString nativeKey() const noexcept
114 {
115 return key;
116 }
117 void setNativeKey(const QString &newKey)
118 {
119 key = newKey;
120 if (isSlowPath())
121 setNativeKey_internal(newKey);
122 }
123
124 Q_CORE_EXPORT QString toString() const;
125 Q_CORE_EXPORT static QNativeIpcKey fromString(const QString &string);
126
127private:
128 struct TypeAndFlags {
129 Type type = DefaultTypeForOs;
130 quint16 reserved1 = {};
131 quint32 reserved2 = {};
132
133 void swap(TypeAndFlags &other) noexcept
134 {
135 std::swap(a&: type, b&: other.type);
136 std::swap(a&: reserved1, b&: other.reserved1);
137 std::swap(a&: reserved2, b&: other.reserved2);
138 }
139
140 friend constexpr bool operator==(const TypeAndFlags &lhs, const TypeAndFlags &rhs) noexcept
141 {
142 return lhs.type == rhs.type &&
143 lhs.reserved1 == rhs.reserved1 &&
144 lhs.reserved2 == rhs.reserved2;
145 }
146 };
147
148 QNativeIpcKeyPrivate *d = nullptr;
149 QString key;
150 TypeAndFlags typeAndFlags;
151
152 friend class QNativeIpcKeyPrivate;
153 constexpr bool isSlowPath() const noexcept
154 { return Q_UNLIKELY(d); }
155
156 friend Q_CORE_EXPORT size_t qHash(const QNativeIpcKey &ipcKey, size_t seed) noexcept;
157 friend size_t qHash(const QNativeIpcKey &ipcKey) noexcept
158 { return qHash(ipcKey, seed: 0); }
159
160 friend bool operator==(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept
161 {
162 if (!(lhs.typeAndFlags == rhs.typeAndFlags))
163 return false;
164 if (lhs.key != rhs.key)
165 return false;
166 if (lhs.d == rhs.d)
167 return true;
168 return compare_internal(lhs, rhs) == 0;
169 }
170 friend bool operator!=(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept
171 {
172 return !(lhs == rhs);
173 }
174
175 Q_CORE_EXPORT void copy_internal(const QNativeIpcKey &other);
176 Q_CORE_EXPORT void move_internal(QNativeIpcKey &&other) noexcept;
177 Q_CORE_EXPORT QNativeIpcKey &assign_internal(const QNativeIpcKey &other);
178 Q_CORE_EXPORT void destroy_internal() noexcept;
179 Q_CORE_EXPORT void setType_internal(Type);
180 Q_CORE_EXPORT void setNativeKey_internal(const QString &);
181 Q_DECL_PURE_FUNCTION Q_CORE_EXPORT static int
182 compare_internal(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept;
183
184#ifdef Q_OS_DARWIN
185 Q_DECL_CONST_FUNCTION Q_CORE_EXPORT static Type defaultTypeForOs_internal() noexcept;
186#endif
187};
188
189// not a shared type, exactly, but this works too
190Q_DECLARE_SHARED(QNativeIpcKey)
191
192inline auto QNativeIpcKey::legacyDefaultTypeForOs() noexcept -> Type
193{
194#if defined(Q_OS_WIN)
195 return Type::Windows;
196#elif defined(QT_POSIX_IPC)
197 return Type::PosixRealtime;
198#elif defined(Q_OS_DARWIN)
199 return defaultTypeForOs_internal();
200#else
201 return Type::SystemV;
202#endif
203}
204
205QT_END_NAMESPACE
206
207#endif // QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
208
209
210#endif // QNATIVEIPCKEY_H
211

source code of qtbase/src/corelib/ipc/qtipccommon.h