From 1f7335fde34abdb9889e0c7b437fc02870570fcf Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 3 Dec 2019 20:44:26 -0500 Subject: DRTVWR-494: Extract LockStatic as a standalone template class. The pattern of requiring a lock to permit *any* access to a static instance of something seems generally useful. Break out lockstatic.h; recast LLInstanceTracker to use it. Moving LockStatic to an external template class instead of a nested class in LLInstanceTrackerBase leaves LLInstanceTrackerBase pretty empty. Get rid of it. And *that* means we can move the definition of the StaticData used by each LLInstanceTracker specialization into the class itself, rather than having to define it beforehand in namespace LLInstanceTrackerStuff. --- indra/llcommon/CMakeLists.txt | 1 + indra/llcommon/llinstancetracker.h | 98 +++++++------------------------------- indra/llcommon/lockstatic.h | 56 ++++++++++++++++++++++ 3 files changed, 75 insertions(+), 80 deletions(-) create mode 100644 indra/llcommon/lockstatic.h (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index af41b9e460..98e1c00ce3 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -247,6 +247,7 @@ set(llcommon_HEADER_FILES llwin32headers.h llwin32headerslean.h llworkerthread.h + lockstatic.h stdtypes.h stringize.h timer.h diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 272ad8086e..cfb40c25f0 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -41,64 +41,20 @@ #include #include +#include "lockstatic.h" + /***************************************************************************** -* LLInstanceTrackerBase +* StaticBase *****************************************************************************/ -/** - * Base class manages "class-static" data that must actually have singleton - * semantics: one instance per process, rather than one instance per module as - * sometimes happens with data simply declared static. - */ namespace LLInstanceTrackerStuff { struct StaticBase { // We need to be able to lock static data while manipulating it. - typedef std::mutex mutex_t; - mutex_t mMutex; + std::mutex mMutex; }; } // namespace LLInstanceTrackerStuff -template -class LL_COMMON_API LLInstanceTrackerBase -{ -protected: - typedef Static StaticData; - - // Instantiate this class to obtain a pointer to the canonical static - // instance of class Static while holding a lock on that instance. Use of - // Static::mMutex presumes either that Static is derived from StaticBase, - // or that Static declares some other suitable mMutex. - class LockStatic - { - typedef std::unique_lock lock_t; - public: - LockStatic(): - mData(getStatic()), - mLock(mData->mMutex) - {} - Static* get() const { return mData; } - operator Static*() const { return get(); } - Static* operator->() const { return get(); } - // sometimes we must explicitly unlock... - void unlock() - { - // but once we do, access is no longer permitted - mData = nullptr; - mLock.unlock(); - } - protected: - Static* mData; - lock_t mLock; - private: - Static* getStatic() - { - static Static sData; - return &sData; - } - }; -}; - /***************************************************************************** * LLInstanceTracker with key *****************************************************************************/ @@ -108,29 +64,20 @@ enum EInstanceTrackerAllowKeyCollisions LLInstanceTrackerReplaceOnCollision }; -namespace LLInstanceTrackerStuff -{ - template - struct StaticMap: public StaticBase - { - typedef std::map InstanceMap; - InstanceMap mMap; - }; -} // LLInstanceTrackerStuff - /// This mix-in class adds support for tracking all instances of the specified class parameter T /// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup /// If KEY is not provided, then instances are stored in a simple set /// @NOTE: see explicit specialization below for default KEY==void case template -class LLInstanceTracker : - public LLInstanceTrackerBase>> +class LLInstanceTracker { - typedef LLInstanceTrackerBase>> super; - using typename super::StaticData; - using typename super::LockStatic; - typedef typename StaticData::InstanceMap InstanceMap; + typedef std::map> InstanceMap; + struct StaticData: public LLInstanceTrackerStuff::StaticBase + { + InstanceMap mMap; + }; + typedef llthread::LockStatic LockStatic; public: // snapshot of std::pair> pairs @@ -334,16 +281,6 @@ private: /***************************************************************************** * LLInstanceTracker without key *****************************************************************************/ -namespace LLInstanceTrackerStuff -{ - template - struct StaticSet: public StaticBase - { - typedef std::set InstanceSet; - InstanceSet mSet; - }; -} // LLInstanceTrackerStuff - // TODO: // - For the case of omitted KEY template parameter, consider storing // std::map> instead of std::set>. @@ -359,13 +296,14 @@ namespace LLInstanceTrackerStuff /// explicit specialization for default case where KEY is void /// use a simple std::set template -class LLInstanceTracker : - public LLInstanceTrackerBase>> +class LLInstanceTracker { - typedef LLInstanceTrackerBase>> super; - using typename super::StaticData; - using typename super::LockStatic; - typedef typename StaticData::InstanceSet InstanceSet; + typedef std::set> InstanceSet; + struct StaticData: public LLInstanceTrackerStuff::StaticBase + { + InstanceSet mSet; + }; + typedef llthread::LockStatic LockStatic; public: /** diff --git a/indra/llcommon/lockstatic.h b/indra/llcommon/lockstatic.h new file mode 100644 index 0000000000..5f08742cae --- /dev/null +++ b/indra/llcommon/lockstatic.h @@ -0,0 +1,56 @@ +/** + * @file lockstatic.h + * @author Nat Goodspeed + * @date 2019-12-03 + * @brief LockStatic class provides mutex-guarded access to the specified + * static data. + * + * $LicenseInfo:firstyear=2019&license=viewerlgpl$ + * Copyright (c) 2019, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LOCKSTATIC_H) +#define LL_LOCKSTATIC_H + +#include "mutex.h" // std::unique_lock + +namespace llthread +{ + +// Instantiate this template to obtain a pointer to the canonical static +// instance of Static while holding a lock on that instance. Use of +// Static::mMutex presumes that Static declares some suitable mMutex. +template +class LockStatic +{ + typedef std::unique_lock lock_t; +public: + LockStatic(): + mData(getStatic()), + mLock(mData->mMutex) + {} + Static* get() const { return mData; } + operator Static*() const { return get(); } + Static* operator->() const { return get(); } + // sometimes we must explicitly unlock... + void unlock() + { + // but once we do, access is no longer permitted + mData = nullptr; + mLock.unlock(); + } +protected: + Static* mData; + lock_t mLock; +private: + Static* getStatic() + { + static Static sData; + return &sData; + } +}; + +} // llthread namespace + +#endif /* ! defined(LL_LOCKSTATIC_H) */ -- cgit v1.2.3