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 | |
14 | QT_BEGIN_NAMESPACE |
15 | |
16 | class QNativeIpcKeyPrivate; |
17 | class QNativeIpcKey |
18 | { |
19 | Q_GADGET_EXPORT(Q_CORE_EXPORT) |
20 | public: |
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 | |
127 | private: |
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 |
190 | Q_DECLARE_SHARED(QNativeIpcKey) |
191 | |
192 | inline 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 | |
205 | QT_END_NAMESPACE |
206 | |
207 | #endif // QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore) |
208 | |
209 | |
210 | #endif // QNATIVEIPCKEY_H |
211 | |