diff options
Diffstat (limited to 'src/corelib/ipc/qsharedmemory_p.h')
-rw-r--r-- | src/corelib/ipc/qsharedmemory_p.h | 228 |
1 files changed, 228 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..9ee4c49e6c --- /dev/null +++ b/src/corelib/ipc/qsharedmemory_p.h @@ -0,0 +1,228 @@ +// 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 +{ + Q_DISABLE_COPY(QSharedMemoryLocker) +public: + Q_NODISCARD_CTOR explicit QSharedMemoryLocker(QSharedMemory *sharedMemory) + : q_sm(sharedMemory) + { + Q_ASSERT(q_sm); + } + + Q_NODISCARD_CTOR QSharedMemoryLocker(QSharedMemoryLocker &&other) noexcept + : q_sm{std::exchange(other.q_sm, nullptr)} + {} + + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSharedMemoryLocker) + + void swap(QSharedMemoryLocker &other) noexcept + { qt_ptr_swap(q_sm, other.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: + friend void swap(QSharedMemoryLocker &lhs, QSharedMemoryLocker &rhs) noexcept + { lhs.swap(rhs); } + + 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 + |