summaryrefslogtreecommitdiffstats
path: root/src/Runtime/Source/foundation/Qt3DSMutex.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/Runtime/Source/foundation/Qt3DSMutex.h')
-rw-r--r--src/Runtime/Source/foundation/Qt3DSMutex.h376
1 files changed, 376 insertions, 0 deletions
diff --git a/src/Runtime/Source/foundation/Qt3DSMutex.h b/src/Runtime/Source/foundation/Qt3DSMutex.h
new file mode 100644
index 00000000..5b717e5c
--- /dev/null
+++ b/src/Runtime/Source/foundation/Qt3DSMutex.h
@@ -0,0 +1,376 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_PSMUTEX_H
+#define QT3DS_FOUNDATION_PSMUTEX_H
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSNoCopy.h"
+
+/*
+ * This <new> inclusion is a best known fix for gcc 4.4.1 error:
+ * Creating object file for apex/src/NVAllocator.cpp ...
+ * In file included from apex/include/Qt3DSFoundation.h:30,
+ * from apex/src/NVAllocator.cpp:26:
+ * apex/include/Qt3DSMutex.h: In constructor 'nv::foundation::MutexT<Alloc>::MutexT(const Alloc&)':
+ * apex/include/Qt3DSMutex.h:92: error: no matching function for call to 'operator new(unsigned int,
+ * qt3ds::foundation::MutexImpl*&)'
+ * <built-in>:0: note: candidates are: void* operator new(unsigned int)
+ */
+#include <new>
+
+namespace qt3ds {
+namespace foundation {
+#ifdef QT3DS_FOUNDATION_NO_EXPORTS
+ class QT3DS_AUTOTEST_EXPORT MutexImpl
+#else
+ class QT3DS_FOUNDATION_API MutexImpl
+#endif
+ {
+ public:
+ /**
+ The constructor for Mutex creates a mutex. It is initially unlocked.
+ */
+ MutexImpl();
+
+ /**
+ The destructor for Mutex deletes the mutex.
+ */
+ ~MutexImpl();
+
+ /**
+ Acquire (lock) the mutex. If the mutex is already locked
+ by another thread, this method blocks until the mutex is
+ unlocked.
+ */
+ bool lock();
+
+ /**
+ Acquire (lock) the mutex. If the mutex is already locked
+ by another thread, this method returns false without blocking.
+ */
+ bool trylock();
+
+ /**
+ Release (unlock) the mutex.
+ */
+ bool unlock();
+
+ /**
+ Size of this class.
+ */
+ static const QT3DSU32 size;
+ };
+
+ class Mutex
+ {
+ public:
+ class ScopedLock : private NoCopy
+ {
+ Mutex &mMutex;
+
+ public:
+ QT3DS_INLINE ScopedLock(Mutex &mutex)
+ : mMutex(mutex)
+ {
+ mMutex.lock();
+ }
+ QT3DS_INLINE ~ScopedLock() { mMutex.unlock(); }
+ };
+
+ /**
+ The constructor for Mutex creates a mutex. It is initially unlocked.
+ */
+ Mutex(NVAllocatorCallback &alloc)
+ : mAllocator(alloc)
+ {
+ mImpl = (MutexImpl *)QT3DS_ALLOC(alloc, MutexImpl::size, "MutexImpl");
+ QT3DS_PLACEMENT_NEW(mImpl, MutexImpl)();
+ }
+
+ /**
+ The destructor for Mutex deletes the mutex.
+ */
+ ~Mutex()
+ {
+ mImpl->~MutexImpl();
+ QT3DS_FREE(mAllocator, mImpl);
+ }
+
+ /**
+ Acquire (lock) the mutex. If the mutex is already locked
+ by another thread, this method blocks until the mutex is
+ unlocked.
+ */
+ bool lock() const { return mImpl->lock(); }
+
+ /**
+ Acquire (lock) the mutex. If the mutex is already locked
+ by another thread, this method returns false without blocking.
+ */
+ bool trylock() const { return mImpl->trylock(); }
+
+ /**
+ Release (unlock) the mutex.
+ */
+ bool unlock() const { return mImpl->unlock(); }
+
+ private:
+ NVAllocatorCallback &mAllocator;
+ MutexImpl *mImpl;
+ };
+
+ class QT3DS_FOUNDATION_API ReadWriteLock : private NoCopy
+ {
+ public:
+ ReadWriteLock(NVAllocatorCallback &alloc);
+ ~ReadWriteLock();
+
+ void lockReader();
+ void lockWriter();
+
+ void unlockReader();
+ void unlockWriter();
+
+ private:
+ class ReadWriteLockImpl *mImpl;
+ };
+
+ class ScopedReadLock : private NoCopy
+ {
+ public:
+ QT3DS_INLINE ScopedReadLock(ReadWriteLock &lock)
+ : mLock(lock)
+ {
+ mLock.lockReader();
+ }
+ QT3DS_INLINE ~ScopedReadLock() { mLock.unlockReader(); }
+
+ private:
+ ReadWriteLock &mLock;
+ };
+
+ class ScopedWriteLock : private NoCopy
+ {
+ public:
+ QT3DS_INLINE ScopedWriteLock(ReadWriteLock &lock)
+ : mLock(lock)
+ {
+ mLock.lockWriter();
+ }
+ QT3DS_INLINE ~ScopedWriteLock() { mLock.unlockWriter(); }
+
+ private:
+ ReadWriteLock &mLock;
+ };
+
+/*
+ * Use this type of lock for mutex behaviour that must operate on SPU and PPU
+ * On non-PS3 platforms, it is implemented using Mutex
+ */
+#ifndef QT3DS_PS3
+
+ class AtomicLock : private NoCopy
+ {
+ Mutex mMutex;
+
+ public:
+ AtomicLock(NVAllocatorCallback &alloc)
+ : mMutex(alloc)
+ {
+ }
+
+ bool lock() { return mMutex.lock(); }
+
+ bool trylock() { return mMutex.trylock(); }
+
+ bool unlock() { return mMutex.unlock(); }
+ };
+
+ class AtomicLockCopy
+ {
+ AtomicLock *pLock;
+
+ public:
+ AtomicLockCopy()
+ : pLock(NULL)
+ {
+ }
+
+ AtomicLockCopy &operator=(AtomicLock &lock)
+ {
+ pLock = &lock;
+ return *this;
+ }
+
+ bool lock() { return pLock->lock(); }
+
+ bool trylock() { return pLock->trylock(); }
+
+ bool unlock() { return pLock->unlock(); }
+ };
+#else
+ struct AtomicLockImpl
+ {
+ QT3DS_ALIGN(128, QT3DSU32 m_Lock);
+ QT3DSI32 m_LockId;
+ QT3DSU32 m_LockCount;
+
+ AtomicLockImpl();
+ };
+ class AtomicLock //: private NoCopy
+ {
+ friend class AtomicLockCopy;
+ AtomicLockImpl *m_pImpl;
+
+ public:
+ AtomicLock();
+
+ ~AtomicLock();
+
+ bool lock();
+
+ bool trylock();
+
+ bool unlock();
+ };
+
+ // if an AtomicLock is copied and then the copy goes out of scope, it'll delete the atomic
+ // primitive
+ // (just a 128-byte aligned int) and cause a crash when it tries to delete it again
+ // This class just uses the atomic primitive without releasing it in the end.
+
+ class AtomicLockCopy
+ {
+ AtomicLockImpl *m_pImpl;
+
+ public:
+ AtomicLockCopy()
+ : m_pImpl(NULL)
+ {
+ }
+
+ AtomicLockCopy(const AtomicLock &lock)
+ : m_pImpl(lock.m_pImpl)
+ {
+ }
+
+ ~AtomicLockCopy() {}
+
+ AtomicLockCopy &operator=(const AtomicLock &lock)
+ {
+ m_pImpl = lock.m_pImpl;
+ return *this;
+ }
+
+ bool lock();
+
+ bool trylock();
+
+ bool unlock();
+ };
+#endif
+
+#ifndef QT3DS_PS3
+
+ class AtomicRwLock : private NoCopy
+ {
+ ReadWriteLock m_Lock;
+
+ public:
+ AtomicRwLock(NVAllocatorCallback &alloc)
+ : m_Lock(alloc)
+ {
+ }
+
+ void lockReader() { m_Lock.lockReader(); }
+ void lockWriter() { m_Lock.lockWriter(); }
+
+ bool tryLockReader()
+ {
+ // Todo - implement this
+ m_Lock.lockReader();
+ return true;
+ }
+
+ void unlockReader() { m_Lock.unlockReader(); }
+ void unlockWriter() { m_Lock.unlockWriter(); }
+ };
+#else
+
+ struct AtomicRwLockImpl
+ {
+ QT3DS_ALIGN(128, volatile QT3DSU32 m_Lock);
+ QT3DS_ALIGN(128, volatile QT3DSU32 m_ReadCounter);
+ QT3DSI32 m_LockId;
+ QT3DSU32 m_LockCount;
+
+ AtomicRwLockImpl();
+ };
+
+ class AtomicRwLock : private NoCopy
+ {
+ AtomicRwLockImpl *m_pImpl;
+
+ public:
+ AtomicRwLock();
+
+ ~AtomicRwLock();
+
+ void lockReader();
+
+ bool tryLockReader();
+
+ void lockWriter();
+
+ void unlockReader();
+
+ void unlockWriter();
+ };
+
+#endif
+
+ class ScopedAtomicLock : private NoCopy
+ {
+ QT3DS_INLINE ScopedAtomicLock(AtomicLock &lock)
+ : mLock(lock)
+ {
+ mLock.lock();
+ }
+ QT3DS_INLINE ~ScopedAtomicLock() { mLock.unlock(); }
+
+ private:
+ AtomicLock &mLock;
+ };
+
+} // namespace foundation
+} // namespace qt3ds
+
+#endif