// 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 #if QT_CONFIG(sharedmemory) #include "qsystemsemaphore.h" #include "qtipccommon_p.h" #include "private/qobject_p.h" #if QT_CONFIG(posix_shm) # include #endif #if QT_CONFIG(sysv_shm) # include #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 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