summaryrefslogtreecommitdiff
path: root/indra/llcommon/llmutex.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/llmutex.h')
-rw-r--r--indra/llcommon/llmutex.h79
1 files changed, 76 insertions, 3 deletions
diff --git a/indra/llcommon/llmutex.h b/indra/llcommon/llmutex.h
index 0d70da6178..077f810d61 100644
--- a/indra/llcommon/llmutex.h
+++ b/indra/llcommon/llmutex.h
@@ -32,6 +32,8 @@
#include <boost/noncopyable.hpp>
#include "mutex.h"
+#include <shared_mutex>
+#include <unordered_map>
#include <condition_variable>
//============================================================================
@@ -66,6 +68,45 @@ protected:
#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();
+ template<> void lock<true>() { lockShared(); }
+ template<> void lock<false>() { lockExclusive(); }
+
+ bool trylockShared();
+ bool trylockExclusive();
+ template<bool SHARED> bool trylock();
+ template<> bool trylock<true>() { return trylockShared(); }
+ template<> bool trylock<false>() { return trylockExclusive(); }
+
+ void unlockShared();
+ void unlockExclusive();
+ template<bool SHARED> void unlock();
+ template<> void unlock<true>() { unlockShared(); }
+ template<> void unlock<false>() { unlockExclusive(); }
+
+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;
+};
+
// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
class LL_COMMON_API LLCondition : public LLMutex
{
@@ -81,27 +122,57 @@ protected:
std::condition_variable mCond;
};
+//============================================================================
+
class LLMutexLock
{
public:
LLMutexLock(LLMutex* mutex)
{
mMutex = mutex;
-
- if(mMutex)
+
+ if (mMutex)
mMutex->lock();
}
+
~LLMutexLock()
{
- if(mMutex)
+ 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
@@ -127,6 +198,8 @@ private:
bool mLocked;
};
+//============================================================================
+
/**
* @class LLScopedLock
* @brief Small class to help lock and unlock mutexes.