diff options
Diffstat (limited to 'indra/llcommon/llmutex.h')
-rw-r--r-- | indra/llcommon/llmutex.h | 542 |
1 files changed, 271 insertions, 271 deletions
diff --git a/indra/llcommon/llmutex.h b/indra/llcommon/llmutex.h index 2b2435da4d..898ddab284 100644 --- a/indra/llcommon/llmutex.h +++ b/indra/llcommon/llmutex.h @@ -1,271 +1,271 @@ -/** - * @file llmutex.h - * @brief Base classes for mutex and condition handling. - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLMUTEX_H -#define LL_LLMUTEX_H - -#include "stdtypes.h" -#include "llthread.h" -#include <boost/noncopyable.hpp> - -#include "mutex.h" -#include <shared_mutex> -#include <unordered_map> -#include <condition_variable> - -//============================================================================ - -//#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO) -#define MUTEX_DEBUG 0 //disable mutex debugging as it's interfering with profiles - -#if MUTEX_DEBUG -#include <map> -#endif - -class LL_COMMON_API LLMutex -{ -public: - LLMutex(); - virtual ~LLMutex(); - - void lock(); // blocks - bool trylock(); // non-blocking, returns true if lock held. - void unlock(); // undefined behavior when called on mutex not being held - bool isLocked(); // non-blocking, but does do a lock/unlock so not free - bool isSelfLocked(); //return true if locked in a same thread - LLThread::id_t lockingThread() const; //get ID of locking thread - -protected: - std::mutex mMutex; - mutable U32 mCount; - mutable LLThread::id_t mLockingThread; - -#if MUTEX_DEBUG - std::unordered_map<LLThread::id_t, bool> mIsLocked; -#endif -}; - -//============================================================================ - -class LL_COMMON_API LLSharedMutex -{ -public: - LLSharedMutex(); - - bool isLocked() const; - bool isThreadLocked() const; - bool isShared() const { return mIsShared; } - - void lockShared(); - void lockExclusive(); - template<bool SHARED> void lock(); - - bool trylockShared(); - bool trylockExclusive(); - template<bool SHARED> bool trylock(); - - void unlockShared(); - void unlockExclusive(); - template<bool SHARED> void unlock(); - -private: - std::shared_mutex mSharedMutex; - mutable std::mutex mLockMutex; - std::unordered_map<LLThread::id_t, U32> mLockingThreads; - bool mIsShared; - - using iterator = std::unordered_map<LLThread::id_t, U32>::iterator; - using const_iterator = std::unordered_map<LLThread::id_t, U32>::const_iterator; -}; - -template<> -inline void LLSharedMutex::lock<true>() -{ - lockShared(); -} - -template<> -inline void LLSharedMutex::lock<false>() -{ - lockExclusive(); -} - -template<> -inline bool LLSharedMutex::trylock<true>() -{ - return trylockShared(); -} - -template<> -inline bool LLSharedMutex::trylock<false>() -{ - return trylockExclusive(); -} - -template<> -inline void LLSharedMutex::unlock<true>() -{ - unlockShared(); -} - -template<> -inline void LLSharedMutex::unlock<false>() -{ - unlockExclusive(); -} - -// Actually a condition/mutex pair (since each condition needs to be associated with a mutex). -class LL_COMMON_API LLCondition : public LLMutex -{ -public: - LLCondition(); - ~LLCondition(); - - void wait(); // blocks - void signal(); - void broadcast(); - -protected: - std::condition_variable mCond; -}; - -//============================================================================ - -class LLMutexLock -{ -public: - LLMutexLock(LLMutex* mutex) - { - mMutex = mutex; - - if (mMutex) - mMutex->lock(); - } - - ~LLMutexLock() - { - if (mMutex) - mMutex->unlock(); - } - -private: - LLMutex* mMutex; -}; - -//============================================================================ - -template<bool SHARED> -class LLSharedMutexLockTemplate -{ -public: - LLSharedMutexLockTemplate(LLSharedMutex* mutex) - : mSharedMutex(mutex) - { - if (mSharedMutex) - mSharedMutex->lock<SHARED>(); - } - - ~LLSharedMutexLockTemplate() - { - if (mSharedMutex) - mSharedMutex->unlock<SHARED>(); - } - -private: - LLSharedMutex* mSharedMutex; -}; - -using LLSharedMutexLock = LLSharedMutexLockTemplate<true>; -using LLExclusiveMutexLock = LLSharedMutexLockTemplate<false>; - -//============================================================================ - -// Scoped locking class similar in function to LLMutexLock but uses -// the trylock() method to conditionally acquire lock without -// blocking. Caller resolves the resulting condition by calling -// the isLocked() method and either punts or continues as indicated. -// -// Mostly of interest to callers needing to avoid stalls who can -// guarantee another attempt at a later time. - -class LLMutexTrylock -{ -public: - LLMutexTrylock(LLMutex* mutex); - LLMutexTrylock(LLMutex* mutex, U32 aTries, U32 delay_ms = 10); - ~LLMutexTrylock(); - - bool isLocked() const - { - return mLocked; - } - -private: - LLMutex* mMutex; - bool mLocked; -}; - -//============================================================================ - -/** -* @class LLScopedLock -* @brief Small class to help lock and unlock mutexes. -* -* The constructor handles the lock, and the destructor handles -* the unlock. Instances of this class are <b>not</b> thread safe. -*/ -class LL_COMMON_API LLScopedLock : private boost::noncopyable -{ -public: - /** - * @brief Constructor which accepts a mutex, and locks it. - * - * @param mutex An allocated mutex. If you pass in NULL, - * this wrapper will not lock. - */ - LLScopedLock(std::mutex* mutex); - - /** - * @brief Destructor which unlocks the mutex if still locked. - */ - ~LLScopedLock(); - - /** - * @brief Check lock. - */ - bool isLocked() const { return mLocked; } - - /** - * @brief This method unlocks the mutex. - */ - void unlock(); - -protected: - bool mLocked; - std::mutex* mMutex; -}; - -#endif // LL_LLMUTEX_H +/**
+ * @file llmutex.h
+ * @brief Base classes for mutex and condition handling.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMUTEX_H
+#define LL_LLMUTEX_H
+
+#include "stdtypes.h"
+#include "llthread.h"
+#include <boost/noncopyable.hpp>
+
+#include "mutex.h"
+#include <shared_mutex>
+#include <unordered_map>
+#include <condition_variable>
+
+//============================================================================
+
+//#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
+#define MUTEX_DEBUG 0 //disable mutex debugging as it's interfering with profiles
+
+#if MUTEX_DEBUG
+#include <map>
+#endif
+
+class LL_COMMON_API LLMutex
+{
+public:
+ LLMutex();
+ virtual ~LLMutex();
+
+ void lock(); // blocks
+ bool trylock(); // non-blocking, returns true if lock held.
+ void unlock(); // undefined behavior when called on mutex not being held
+ bool isLocked(); // non-blocking, but does do a lock/unlock so not free
+ bool isSelfLocked(); //return true if locked in a same thread
+ LLThread::id_t lockingThread() const; //get ID of locking thread
+
+protected:
+ std::mutex mMutex;
+ mutable U32 mCount;
+ mutable LLThread::id_t mLockingThread;
+
+#if MUTEX_DEBUG
+ std::unordered_map<LLThread::id_t, bool> mIsLocked;
+#endif
+};
+
+//============================================================================
+
+class LL_COMMON_API LLSharedMutex
+{
+public:
+ LLSharedMutex();
+
+ bool isLocked() const;
+ bool isThreadLocked() const;
+ bool isShared() const { return mIsShared; }
+
+ void lockShared();
+ void lockExclusive();
+ template<bool SHARED> void lock();
+
+ bool trylockShared();
+ bool trylockExclusive();
+ template<bool SHARED> bool trylock();
+
+ void unlockShared();
+ void unlockExclusive();
+ template<bool SHARED> void unlock();
+
+private:
+ std::shared_mutex mSharedMutex;
+ mutable std::mutex mLockMutex;
+ std::unordered_map<LLThread::id_t, U32> mLockingThreads;
+ bool mIsShared;
+
+ using iterator = std::unordered_map<LLThread::id_t, U32>::iterator;
+ using const_iterator = std::unordered_map<LLThread::id_t, U32>::const_iterator;
+};
+
+template<>
+inline void LLSharedMutex::lock<true>()
+{
+ lockShared();
+}
+
+template<>
+inline void LLSharedMutex::lock<false>()
+{
+ lockExclusive();
+}
+
+template<>
+inline bool LLSharedMutex::trylock<true>()
+{
+ return trylockShared();
+}
+
+template<>
+inline bool LLSharedMutex::trylock<false>()
+{
+ return trylockExclusive();
+}
+
+template<>
+inline void LLSharedMutex::unlock<true>()
+{
+ unlockShared();
+}
+
+template<>
+inline void LLSharedMutex::unlock<false>()
+{
+ unlockExclusive();
+}
+
+// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
+class LL_COMMON_API LLCondition : public LLMutex
+{
+public:
+ LLCondition();
+ ~LLCondition();
+
+ void wait(); // blocks
+ void signal();
+ void broadcast();
+
+protected:
+ std::condition_variable mCond;
+};
+
+//============================================================================
+
+class LLMutexLock
+{
+public:
+ LLMutexLock(LLMutex* mutex)
+ {
+ mMutex = mutex;
+
+ if (mMutex)
+ mMutex->lock();
+ }
+
+ ~LLMutexLock()
+ {
+ if (mMutex)
+ mMutex->unlock();
+ }
+
+private:
+ LLMutex* mMutex;
+};
+
+//============================================================================
+
+template<bool SHARED>
+class LLSharedMutexLockTemplate
+{
+public:
+ LLSharedMutexLockTemplate(LLSharedMutex* mutex)
+ : mSharedMutex(mutex)
+ {
+ if (mSharedMutex)
+ mSharedMutex->lock<SHARED>();
+ }
+
+ ~LLSharedMutexLockTemplate()
+ {
+ if (mSharedMutex)
+ mSharedMutex->unlock<SHARED>();
+ }
+
+private:
+ LLSharedMutex* mSharedMutex;
+};
+
+using LLSharedMutexLock = LLSharedMutexLockTemplate<true>;
+using LLExclusiveMutexLock = LLSharedMutexLockTemplate<false>;
+
+//============================================================================
+
+// Scoped locking class similar in function to LLMutexLock but uses
+// the trylock() method to conditionally acquire lock without
+// blocking. Caller resolves the resulting condition by calling
+// the isLocked() method and either punts or continues as indicated.
+//
+// Mostly of interest to callers needing to avoid stalls who can
+// guarantee another attempt at a later time.
+
+class LLMutexTrylock
+{
+public:
+ LLMutexTrylock(LLMutex* mutex);
+ LLMutexTrylock(LLMutex* mutex, U32 aTries, U32 delay_ms = 10);
+ ~LLMutexTrylock();
+
+ bool isLocked() const
+ {
+ return mLocked;
+ }
+
+private:
+ LLMutex* mMutex;
+ bool mLocked;
+};
+
+//============================================================================
+
+/**
+* @class LLScopedLock
+* @brief Small class to help lock and unlock mutexes.
+*
+* The constructor handles the lock, and the destructor handles
+* the unlock. Instances of this class are <b>not</b> thread safe.
+*/
+class LL_COMMON_API LLScopedLock : private boost::noncopyable
+{
+public:
+ /**
+ * @brief Constructor which accepts a mutex, and locks it.
+ *
+ * @param mutex An allocated mutex. If you pass in NULL,
+ * this wrapper will not lock.
+ */
+ LLScopedLock(std::mutex* mutex);
+
+ /**
+ * @brief Destructor which unlocks the mutex if still locked.
+ */
+ ~LLScopedLock();
+
+ /**
+ * @brief Check lock.
+ */
+ bool isLocked() const { return mLocked; }
+
+ /**
+ * @brief This method unlocks the mutex.
+ */
+ void unlock();
+
+protected:
+ bool mLocked;
+ std::mutex* mMutex;
+};
+
+#endif // LL_LLMUTEX_H
|