1 | // Copyright (C) 2016 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 QSHAREDMEMORY_P_H |
5 | #define QSHAREDMEMORY_P_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists purely as an |
12 | // implementation detail. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include "qsharedmemory.h" |
19 | |
20 | #include <QtCore/qstring.h> |
21 | |
22 | #if QT_CONFIG(sharedmemory) |
23 | #include "qsystemsemaphore.h" |
24 | #include "qtipccommon_p.h" |
25 | #include "private/qobject_p.h" |
26 | |
27 | #if QT_CONFIG(posix_shm) |
28 | # include <sys/mman.h> |
29 | #endif |
30 | #if QT_CONFIG(sysv_shm) |
31 | # include <sys/shm.h> |
32 | #endif |
33 | |
34 | QT_BEGIN_NAMESPACE |
35 | |
36 | class QSharedMemoryPrivate; |
37 | |
38 | #if QT_CONFIG(systemsemaphore) |
39 | /*! |
40 | Helper class |
41 | */ |
42 | class QSharedMemoryLocker |
43 | { |
44 | Q_DISABLE_COPY(QSharedMemoryLocker) |
45 | public: |
46 | Q_NODISCARD_CTOR explicit QSharedMemoryLocker(QSharedMemory *sharedMemory) |
47 | : q_sm(sharedMemory) |
48 | { |
49 | Q_ASSERT(q_sm); |
50 | } |
51 | |
52 | Q_NODISCARD_CTOR QSharedMemoryLocker(QSharedMemoryLocker &&other) noexcept |
53 | : q_sm{std::exchange(obj&: other.q_sm, new_val: nullptr)} |
54 | {} |
55 | |
56 | QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSharedMemoryLocker) |
57 | |
58 | void swap(QSharedMemoryLocker &other) noexcept |
59 | { qt_ptr_swap(lhs&: q_sm, rhs&: other.q_sm); } |
60 | |
61 | inline ~QSharedMemoryLocker() |
62 | { |
63 | if (q_sm) |
64 | q_sm->unlock(); |
65 | } |
66 | |
67 | inline bool lock() |
68 | { |
69 | if (q_sm && q_sm->lock()) |
70 | return true; |
71 | q_sm = nullptr; |
72 | return false; |
73 | } |
74 | |
75 | private: |
76 | friend void swap(QSharedMemoryLocker &lhs, QSharedMemoryLocker &rhs) noexcept |
77 | { lhs.swap(other&: rhs); } |
78 | |
79 | QSharedMemory *q_sm; |
80 | }; |
81 | #endif // QT_CONFIG(systemsemaphore) |
82 | |
83 | class QSharedMemoryPosix |
84 | { |
85 | public: |
86 | static constexpr bool Enabled = QT_CONFIG(posix_shm); |
87 | static bool supports(QNativeIpcKey::Type type) |
88 | { return type == QNativeIpcKey::Type::PosixRealtime; } |
89 | static bool runtimeSupportCheck(); |
90 | |
91 | bool handle(QSharedMemoryPrivate *self); |
92 | bool cleanHandle(QSharedMemoryPrivate *self); |
93 | bool create(QSharedMemoryPrivate *self, qsizetype size); |
94 | bool attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode); |
95 | bool detach(QSharedMemoryPrivate *self); |
96 | |
97 | int hand = -1; |
98 | }; |
99 | |
100 | class QSharedMemorySystemV |
101 | { |
102 | public: |
103 | static constexpr bool Enabled = QT_CONFIG(sysv_shm); |
104 | static bool supports(QNativeIpcKey::Type type) |
105 | { return quint16(type) <= 0xff; } |
106 | static bool runtimeSupportCheck(); |
107 | |
108 | #if QT_CONFIG(sysv_sem) |
109 | key_t handle(QSharedMemoryPrivate *self); |
110 | bool cleanHandle(QSharedMemoryPrivate *self); |
111 | bool create(QSharedMemoryPrivate *self, qsizetype size); |
112 | bool attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode); |
113 | bool detach(QSharedMemoryPrivate *self); |
114 | |
115 | private: |
116 | void updateNativeKeyFile(const QNativeIpcKey &nativeKey); |
117 | |
118 | QByteArray nativeKeyFile; |
119 | key_t unix_key = 0; |
120 | #endif |
121 | }; |
122 | |
123 | class QSharedMemoryWin32 |
124 | { |
125 | public: |
126 | #ifdef Q_OS_WIN32 |
127 | static constexpr bool Enabled = true; |
128 | #else |
129 | static constexpr bool Enabled = false; |
130 | #endif |
131 | static bool runtimeSupportCheck() { return Enabled; } |
132 | static bool supports(QNativeIpcKey::Type type) |
133 | { return type == QNativeIpcKey::Type::Windows; } |
134 | |
135 | Qt::HANDLE handle(QSharedMemoryPrivate *self); |
136 | bool cleanHandle(QSharedMemoryPrivate *self); |
137 | bool create(QSharedMemoryPrivate *self, qsizetype size); |
138 | bool attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode); |
139 | bool detach(QSharedMemoryPrivate *self); |
140 | |
141 | Qt::HANDLE hand = nullptr; |
142 | }; |
143 | |
144 | class Q_AUTOTEST_EXPORT QSharedMemoryPrivate : public QObjectPrivate |
145 | { |
146 | Q_DECLARE_PUBLIC(QSharedMemory) |
147 | |
148 | public: |
149 | QSharedMemoryPrivate(QNativeIpcKey::Type type) : nativeKey(type) |
150 | { constructBackend(); } |
151 | ~QSharedMemoryPrivate(); |
152 | |
153 | void *memory = nullptr; |
154 | qsizetype size = 0; |
155 | QNativeIpcKey nativeKey; |
156 | QString errorString; |
157 | #if QT_CONFIG(systemsemaphore) |
158 | using SemaphoreAccessMode = QSystemSemaphore::AccessMode; |
159 | QSystemSemaphore systemSemaphore{ QNativeIpcKey() }; |
160 | bool lockedByMe = false; |
161 | #else |
162 | enum SemaphoreAccessMode {}; |
163 | #endif |
164 | QSharedMemory::SharedMemoryError error = QSharedMemory::NoError; |
165 | |
166 | union Backend { |
167 | Backend() {} |
168 | ~Backend() {} |
169 | QSharedMemoryPosix posix; |
170 | QSharedMemorySystemV sysv; |
171 | QSharedMemoryWin32 win32; |
172 | }; |
173 | QtIpcCommon::IpcStorageVariant<&Backend::posix, &Backend::sysv, &Backend::win32> backend; |
174 | |
175 | void constructBackend(); |
176 | void destructBackend(); |
177 | bool initKey(SemaphoreAccessMode mode); |
178 | |
179 | template <typename Lambda> auto visit(const Lambda &lambda) |
180 | { |
181 | return backend.visit(nativeKey.type(), lambda); |
182 | } |
183 | |
184 | bool handle() |
185 | { |
186 | return visit(lambda: [&](auto p) { return !!p->handle(this); }); |
187 | } |
188 | bool cleanHandle() |
189 | { |
190 | return visit(lambda: [&](auto p) { return p->cleanHandle(this); }); |
191 | } |
192 | bool create(qsizetype sz) |
193 | { |
194 | return visit(lambda: [&](auto p) { return p->create(this, sz); }); |
195 | } |
196 | bool attach(QSharedMemory::AccessMode mode) |
197 | { |
198 | return visit(lambda: [&](auto p) { return p->attach(this, mode); }); |
199 | } |
200 | bool detach() |
201 | { |
202 | return visit(lambda: [&](auto p) { return p->detach(this); }); |
203 | } |
204 | |
205 | inline void setError(QSharedMemory::SharedMemoryError e, const QString &message) |
206 | { error = e; errorString = message; } |
207 | void setUnixErrorString(QLatin1StringView function); |
208 | void setWindowsErrorString(QLatin1StringView function); |
209 | |
210 | #if QT_CONFIG(systemsemaphore) |
211 | bool tryLocker(QSharedMemoryLocker *locker, const QString &function) { |
212 | if (!locker->lock()) { |
213 | errorString = QSharedMemory::tr(s: "%1: unable to lock").arg(a: function); |
214 | error = QSharedMemory::LockError; |
215 | return false; |
216 | } |
217 | return true; |
218 | } |
219 | QNativeIpcKey semaphoreNativeKey() const; |
220 | #endif // QT_CONFIG(systemsemaphore) |
221 | }; |
222 | |
223 | QT_END_NAMESPACE |
224 | |
225 | #endif // QT_CONFIG(sharedmemory) |
226 | |
227 | #endif // QSHAREDMEMORY_P_H |
228 | |
229 |
Definitions
- QSharedMemoryLocker
- QSharedMemoryLocker
- QSharedMemoryLocker
- QSharedMemoryLocker
- swap
- ~QSharedMemoryLocker
- lock
- swap
- QSharedMemoryPosix
- Enabled
- supports
- QSharedMemorySystemV
- Enabled
- supports
- QSharedMemoryWin32
- Enabled
- runtimeSupportCheck
- supports
- QSharedMemoryPrivate
- QSharedMemoryPrivate
- Backend
- Backend
- ~Backend
- visit
- handle
- cleanHandle
- create
- attach
- detach
- setError
Learn to use CMake with our Intro Training
Find out more