diff options
Diffstat (limited to 'indra/llcommon')
-rw-r--r-- | indra/llcommon/llassettype.cpp | 3 | ||||
-rw-r--r-- | indra/llcommon/llcoros.h | 3 | ||||
-rw-r--r-- | indra/llcommon/llerror.cpp | 9 | ||||
-rw-r--r-- | indra/llcommon/llevents.h | 3 | ||||
-rw-r--r-- | indra/llcommon/llinitdestroyclass.h | 8 | ||||
-rw-r--r-- | indra/llcommon/llpounceable.h | 3 | ||||
-rw-r--r-- | indra/llcommon/llregistry.h | 5 | ||||
-rw-r--r-- | indra/llcommon/llsingleton.cpp | 3 | ||||
-rw-r--r-- | indra/llcommon/llsingleton.h | 68 | ||||
-rw-r--r-- | indra/llcommon/tests/llsingleton_test.cpp | 31 |
10 files changed, 98 insertions, 38 deletions
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 5ae2df3994..4304db36be 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -63,8 +63,7 @@ struct AssetEntry : public LLDictionaryEntry class LLAssetDictionary : public LLSingleton<LLAssetDictionary>, public LLDictionary<LLAssetType::EType, AssetEntry> { -public: - LLAssetDictionary(); + LLSINGLETON(LLAssetDictionary); }; LLAssetDictionary::LLAssetDictionary() diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 0da7a3a6e4..bbe2d22af4 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -85,6 +85,7 @@ class Suspending; */ class LL_COMMON_API LLCoros: public LLSingleton<LLCoros> { + LLSINGLETON(LLCoros); public: /// Canonical boost::dcoroutines::coroutine signature we use typedef boost::dcoroutines::coroutine<void()> coro; @@ -175,8 +176,6 @@ public: class Future; private: - LLCoros(); - friend class LLSingleton<LLCoros>; friend class llcoro::Suspending; friend llcoro::id llcoro::get_id(); std::string generateDistinctName(const std::string& prefix) const; diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index a34b50f816..2ef748e3e4 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -374,9 +374,8 @@ namespace class Globals : public LLSingleton<Globals> { + LLSINGLETON(Globals); public: - Globals(); - std::ostringstream messageStream; bool messageStreamInUse; @@ -449,9 +448,8 @@ namespace LLError class Settings : public LLSingleton<Settings> { + LLSINGLETON(Settings); public: - Settings(); - SettingsConfigPtr getSettingsConfig(); void reset(); @@ -486,8 +484,7 @@ namespace LLError mRecorders.clear(); } - Settings::Settings() - : LLSingleton<Settings>(), + Settings::Settings(): mSettingsConfig(new SettingsConfig()) { } diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index ba4fcd766e..6c8b66f596 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -209,7 +209,7 @@ class LLEventPump; */ class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps> { - friend class LLSingleton<LLEventPumps>; + LLSINGLETON(LLEventPumps); public: /** * Find or create an LLEventPump instance with a specific name. We return @@ -252,7 +252,6 @@ private: void unregister(const LLEventPump&); private: - LLEventPumps(); ~LLEventPumps(); testable: diff --git a/indra/llcommon/llinitdestroyclass.h b/indra/llcommon/llinitdestroyclass.h index 9c66211475..5f979614fe 100644 --- a/indra/llcommon/llinitdestroyclass.h +++ b/indra/llcommon/llinitdestroyclass.h @@ -78,9 +78,7 @@ class LLInitClassList : public LLCallbackRegistry, public LLSingleton<LLInitClassList> { - friend class LLSingleton<LLInitClassList>; -private: - LLInitClassList() {} + LLSINGLETON_EMPTY_CTOR(LLInitClassList); }; /** @@ -94,9 +92,7 @@ class LLDestroyClassList : public LLCallbackRegistry, public LLSingleton<LLDestroyClassList> { - friend class LLSingleton<LLDestroyClassList>; -private: - LLDestroyClassList() {} + LLSINGLETON_EMPTY_CTOR(LLDestroyClassList); }; /** diff --git a/indra/llcommon/llpounceable.h b/indra/llcommon/llpounceable.h index 77b711bdc6..0421ce966a 100644 --- a/indra/llcommon/llpounceable.h +++ b/indra/llcommon/llpounceable.h @@ -76,7 +76,8 @@ template <typename T> class LLPounceableQueueSingleton: public LLSingleton<LLPounceableQueueSingleton<T> > { -private: + LLSINGLETON_EMPTY_CTOR(LLPounceableQueueSingleton); + typedef LLPounceableTraits<T, LLPounceableStatic> traits; typedef typename traits::owner_ptr owner_ptr; typedef typename traits::signal_t signal_t; diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h index fde729f8f9..750fe9fdc8 100644 --- a/indra/llcommon/llregistry.h +++ b/indra/llcommon/llregistry.h @@ -247,7 +247,10 @@ class LLRegistrySingleton : public LLRegistry<KEY, VALUE, COMPARATOR>, public LLSingleton<DERIVED_TYPE> { - friend class LLSingleton<DERIVED_TYPE>; + // This LLRegistrySingleton doesn't use LLSINGLETON(LLRegistrySingleton) + // because the concrete class is actually DERIVED_TYPE, not + // LLRegistrySingleton. So each concrete subclass needs + // LLSINGLETON(whatever) -- not this intermediate base class. public: typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t; typedef const KEY& ref_const_key_t; diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp index 24ccc8ddb4..9025e53bb2 100644 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -57,8 +57,7 @@ bool oktolog(); class LLSingletonBase::MasterList: public LLSingleton<LLSingletonBase::MasterList> { -private: - friend class LLSingleton<LLSingletonBase::MasterList>; + LLSINGLETON_EMPTY_CTOR(MasterList); public: // No need to make this private with accessors; nobody outside this source diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 92fba4c1a8..1b915dfd6e 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -223,7 +223,13 @@ LLSingletonBase::LLSingletonBase(tag<DERIVED_TYPE>): * Derive your class from LLSingleton, passing your subclass name as * LLSingleton's template parameter, like so: * - * class Foo: public LLSingleton<Foo>{}; + * class Foo: public LLSingleton<Foo> + * { + * // use this macro at start of every LLSingleton subclass + * LLSINGLETON(Foo); + * public: + * // ... + * }; * * Foo& instance = Foo::instance(); * @@ -279,6 +285,16 @@ private: return new DERIVED_TYPE(); } + // We know of no way to instruct the compiler that every subclass + // constructor MUST be private. However, we can make the LLSINGLETON() + // macro both declare a private constructor and provide the required + // friend declaration. How can we ensure that every subclass uses + // LLSINGLETON()? By making that macro provide a definition for this pure + // virtual method. If you get "can't instantiate class due to missing pure + // virtual method" for this method, then add LLSINGLETON(yourclass) in the + // subclass body. + virtual void you_must_use_LLSINGLETON_macro() = 0; + // stores pointer to singleton instance struct SingletonLifetimeManager { @@ -450,4 +466,54 @@ private: template<typename T> typename LLSingleton<T>::SingletonData LLSingleton<T>::sData; +/** + * Use LLSINGLETON(Foo); at the start of an LLSingleton<Foo> subclass body + * when you want to declare an out-of-line constructor: + * + * @code + * class Foo: public LLSingleton<Foo> + * { + * // use this macro at start of every LLSingleton subclass + * LLSINGLETON(Foo); + * public: + * // ... + * }; + * // ... + * [inline] + * Foo::Foo() { ... } + * @endcode + * + * Unfortunately, this mechanism does not permit you to define even a simple + * (but nontrivial) constructor within the class body. If it's literally + * trivial, use LLSINGLETON_EMPTY_CTOR(); if not, use LLSINGLETON() and define + * the constructor outside the class body. If you must define it in a header + * file, use 'inline' (unless it's a template class) to avoid duplicate-symbol + * errors at link time. + */ +#define LLSINGLETON(DERIVED_CLASS) \ +private: \ + /* implement LLSingleton pure virtual method whose sole purpose */ \ + /* is to remind people to use this macro */ \ + virtual void you_must_use_LLSINGLETON_macro() {} \ + friend class LLSingleton<DERIVED_CLASS>; \ + DERIVED_CLASS() + +/** + * Use LLSINGLETON_EMPTY_CTOR(Foo); at the start of an LLSingleton<Foo> + * subclass body when the constructor is trivial: + * + * @code + * class Foo: public LLSingleton<Foo> + * { + * // use this macro at start of every LLSingleton subclass + * LLSINGLETON_EMPTY_CTOR(Foo); + * public: + * // ... + * }; + * @endcode + */ +#define LLSINGLETON_EMPTY_CTOR(DERIVED_CLASS) \ + /* LLSINGLETON() is carefully implemented to permit exactly this */ \ + LLSINGLETON(DERIVED_CLASS) {} + #endif diff --git a/indra/llcommon/tests/llsingleton_test.cpp b/indra/llcommon/tests/llsingleton_test.cpp index a05f650f25..56886bc73f 100644 --- a/indra/llcommon/tests/llsingleton_test.cpp +++ b/indra/llcommon/tests/llsingleton_test.cpp @@ -34,21 +34,22 @@ // Capture execution sequence by appending to log string. std::string sLog; -#define DECLARE_CLASS(CLS) \ -struct CLS: public LLSingleton<CLS> \ -{ \ - static enum dep_flag { \ - DEP_NONE, /* no dependency */ \ - DEP_CTOR, /* dependency in ctor */ \ +#define DECLARE_CLASS(CLS) \ +struct CLS: public LLSingleton<CLS> \ +{ \ + LLSINGLETON(CLS); \ + ~CLS(); \ +public: \ + static enum dep_flag { \ + DEP_NONE, /* no dependency */ \ + DEP_CTOR, /* dependency in ctor */ \ DEP_INIT /* dependency in initSingleton */ \ - } sDepFlag; \ - \ - CLS(); \ - void initSingleton(); \ - void cleanupSingleton(); \ - ~CLS(); \ -}; \ - \ + } sDepFlag; \ + \ + void initSingleton(); \ + void cleanupSingleton(); \ +}; \ + \ CLS::dep_flag CLS::sDepFlag = DEP_NONE DECLARE_CLASS(A); @@ -93,7 +94,7 @@ namespace tut // We need a class created with the LLSingleton template to test with. class LLSingletonTest: public LLSingleton<LLSingletonTest> { - + LLSINGLETON_EMPTY_CTOR(LLSingletonTest); }; }; |