summaryrefslogtreecommitdiffstats
path: root/src/corelib/ipc/qsharedmemory_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/ipc/qsharedmemory_p.h')
-rw-r--r--src/corelib/ipc/qsharedmemory_p.h215
1 files changed, 215 insertions, 0 deletions
diff --git a/src/corelib/ipc/qsharedmemory_p.h b/src/corelib/ipc/qsharedmemory_p.h
new file mode 100644
index 0000000000..987bb38642
--- /dev/null
+++ b/src/corelib/ipc/qsharedmemory_p.h
@@ -0,0 +1,215 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QSHAREDMEMORY_P_H
+#define QSHAREDMEMORY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qsharedmemory.h"
+
+#include <QtCore/qstring.h>
+
+#if QT_CONFIG(sharedmemory)
+#include "qsystemsemaphore.h"
+#include "qtipccommon_p.h"
+#include "private/qobject_p.h"
+
+#if QT_CONFIG(posix_shm)
+# include <sys/mman.h>
+#endif
+#if QT_CONFIG(sysv_shm)
+# include <sys/shm.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QSharedMemoryPrivate;
+
+#if QT_CONFIG(systemsemaphore)
+/*!
+ Helper class
+ */
+class QSharedMemoryLocker
+{
+
+public:
+ Q_NODISCARD_CTOR QSharedMemoryLocker(QSharedMemory *sharedMemory) : q_sm(sharedMemory)
+ {
+ Q_ASSERT(q_sm);
+ }
+
+ inline ~QSharedMemoryLocker()
+ {
+ if (q_sm)
+ q_sm->unlock();
+ }
+
+ inline bool lock()
+ {
+ if (q_sm && q_sm->lock())
+ return true;
+ q_sm = nullptr;
+ return false;
+ }
+
+private:
+ QSharedMemory *q_sm;
+};
+#endif // QT_CONFIG(systemsemaphore)
+
+class QSharedMemoryPosix
+{
+public:
+ static constexpr bool Enabled = QT_CONFIG(posix_shm);
+ static bool supports(QNativeIpcKey::Type type)
+ { return type == QNativeIpcKey::Type::PosixRealtime; }
+ static bool runtimeSupportCheck();
+
+ bool handle(QSharedMemoryPrivate *self);
+ bool cleanHandle(QSharedMemoryPrivate *self);
+ bool create(QSharedMemoryPrivate *self, qsizetype size);
+ bool attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode);
+ bool detach(QSharedMemoryPrivate *self);
+
+ int hand = -1;
+};
+
+class QSharedMemorySystemV
+{
+public:
+ static constexpr bool Enabled = QT_CONFIG(sysv_shm);
+ static bool supports(QNativeIpcKey::Type type)
+ { return quint16(type) <= 0xff; }
+ static bool runtimeSupportCheck();
+
+#if QT_CONFIG(sysv_sem)
+ key_t handle(QSharedMemoryPrivate *self);
+ bool cleanHandle(QSharedMemoryPrivate *self);
+ bool create(QSharedMemoryPrivate *self, qsizetype size);
+ bool attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode);
+ bool detach(QSharedMemoryPrivate *self);
+
+private:
+ void updateNativeKeyFile(const QNativeIpcKey &nativeKey);
+
+ QByteArray nativeKeyFile;
+ key_t unix_key = 0;
+#endif
+};
+
+class QSharedMemoryWin32
+{
+public:
+#ifdef Q_OS_WIN32
+ static constexpr bool Enabled = true;
+#else
+ static constexpr bool Enabled = false;
+#endif
+ static bool runtimeSupportCheck() { return Enabled; }
+ static bool supports(QNativeIpcKey::Type type)
+ { return type == QNativeIpcKey::Type::Windows; }
+
+ Qt::HANDLE handle(QSharedMemoryPrivate *self);
+ bool cleanHandle(QSharedMemoryPrivate *self);
+ bool create(QSharedMemoryPrivate *self, qsizetype size);
+ bool attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode);
+ bool detach(QSharedMemoryPrivate *self);
+
+ Qt::HANDLE hand = nullptr;
+};
+
+class Q_AUTOTEST_EXPORT QSharedMemoryPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSharedMemory)
+
+public:
+ QSharedMemoryPrivate(QNativeIpcKey::Type type) : nativeKey(type)
+ { constructBackend(); }
+ ~QSharedMemoryPrivate();
+
+ void *memory = nullptr;
+ qsizetype size = 0;
+ QNativeIpcKey nativeKey;
+ QString errorString;
+#if QT_CONFIG(systemsemaphore)
+ using SemaphoreAccessMode = QSystemSemaphore::AccessMode;
+ QSystemSemaphore systemSemaphore{ QNativeIpcKey() };
+ bool lockedByMe = false;
+#else
+ enum SemaphoreAccessMode {};
+#endif
+ QSharedMemory::SharedMemoryError error = QSharedMemory::NoError;
+
+ union Backend {
+ Backend() {}
+ ~Backend() {}
+ QSharedMemoryPosix posix;
+ QSharedMemorySystemV sysv;
+ QSharedMemoryWin32 win32;
+ };
+ QtIpcCommon::IpcStorageVariant<&Backend::posix, &Backend::sysv, &Backend::win32> backend;
+
+ void constructBackend();
+ void destructBackend();
+ bool initKey(SemaphoreAccessMode mode);
+
+ template <typename Lambda> auto visit(const Lambda &lambda)
+ {
+ return backend.visit(nativeKey.type(), lambda);
+ }
+
+ bool handle()
+ {
+ return visit([&](auto p) { return !!p->handle(this); });
+ }
+ bool cleanHandle()
+ {
+ return visit([&](auto p) { return p->cleanHandle(this); });
+ }
+ bool create(qsizetype size)
+ {
+ return visit([&](auto p) { return p->create(this, size); });
+ }
+ bool attach(QSharedMemory::AccessMode mode)
+ {
+ return visit([&](auto p) { return p->attach(this, mode); });
+ }
+ bool detach()
+ {
+ return visit([&](auto p) { return p->detach(this); });
+ }
+
+ inline void setError(QSharedMemory::SharedMemoryError e, const QString &message)
+ { error = e; errorString = message; }
+ void setUnixErrorString(QLatin1StringView function);
+ void setWindowsErrorString(QLatin1StringView function);
+
+#if QT_CONFIG(systemsemaphore)
+ bool tryLocker(QSharedMemoryLocker *locker, const QString &function) {
+ if (!locker->lock()) {
+ errorString = QSharedMemory::tr("%1: unable to lock").arg(function);
+ error = QSharedMemory::LockError;
+ return false;
+ }
+ return true;
+ }
+ QNativeIpcKey semaphoreNativeKey() const;
+#endif // QT_CONFIG(systemsemaphore)
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(sharedmemory)
+
+#endif // QSHAREDMEMORY_P_H
+