diff options
| author | AndreyL ProductEngine <alihatskiy@productengine.com> | 2016-11-14 22:04:37 +0200 | 
|---|---|---|
| committer | AndreyL ProductEngine <alihatskiy@productengine.com> | 2016-11-14 22:04:37 +0200 | 
| commit | 7fceb3a63f0157c7075c77e6d8516079ff4d217a (patch) | |
| tree | 19f23fe6dc1c2d396de32b32608352091ebda332 | |
| parent | 6c7fabdec76eda60fa27640d115e06e2bbfc12e4 (diff) | |
| parent | c52f621e20737b553a9a9e7f1c961f5d5fbc6f89 (diff) | |
Merged in lindenlab/viewer-cleanup
217 files changed, 3054 insertions, 1075 deletions
| diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 3d27b4a5b5..f4dba16a94 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -42,6 +42,7 @@  #include "lldiriterator.h"  #include "v4coloru.h"  #include "llsdserialize.h" +#include "llcleanup.h"  // system libraries  #include <iostream> @@ -634,7 +635,7 @@ int main(int argc, char** argv)  	}  	// Cleanup and exit -	LLImage::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLImage);  	if (fast_timer_log_thread)  	{  		fast_timer_log_thread->shutdown(); diff --git a/indra/llappearance/llavatarappearancedefines.h b/indra/llappearance/llavatarappearancedefines.h index 8a1d2c4707..d6223bb4d2 100644 --- a/indra/llappearance/llavatarappearancedefines.h +++ b/indra/llappearance/llavatarappearancedefines.h @@ -127,8 +127,7 @@ class LLAvatarAppearanceDictionary : public LLSingleton<LLAvatarAppearanceDictio  	//--------------------------------------------------------------------  	// Constructors and Destructors  	//-------------------------------------------------------------------- -public: -	LLAvatarAppearanceDictionary(); +	LLSINGLETON(LLAvatarAppearanceDictionary);  	virtual ~LLAvatarAppearanceDictionary();  private:  	void createAssociations(); diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index 959d6e499a..9318b23fd1 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -293,9 +293,9 @@ protected:  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  class LLTexLayerStaticImageList : public LLSingleton<LLTexLayerStaticImageList>  { -public: -	LLTexLayerStaticImageList(); +	LLSINGLETON(LLTexLayerStaticImageList);  	~LLTexLayerStaticImageList(); +public:  	LLGLTexture*		getTexture(const std::string& file_name, BOOL is_mask);  	LLImageTGA*			getImageTGA(const std::string& file_name);  	void				deleteCachedImages(); diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp index 87109a5906..207e0c4011 100644 --- a/indra/llappearance/llwearabletype.cpp +++ b/indra/llappearance/llwearabletype.cpp @@ -71,8 +71,7 @@ struct WearableEntry : public LLDictionaryEntry  class LLWearableDictionary : public LLSingleton<LLWearableDictionary>,  							 public LLDictionary<LLWearableType::EType, WearableEntry>  { -public: -	LLWearableDictionary(); +	LLSINGLETON(LLWearableDictionary);  };  LLWearableDictionary::LLWearableDictionary() diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 410a5819b3..d9ab7c1b38 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -40,8 +40,10 @@ set(llcommon_SOURCE_FILES      llbase64.cpp      llbitpack.cpp      llcallbacklist.cpp +    llcleanup.cpp      llcommon.cpp      llcommonutils.cpp +    llcoro_get_id.cpp      llcoros.cpp      llcrc.cpp      llcriticaldamp.cpp @@ -66,7 +68,9 @@ set(llcommon_SOURCE_FILES      llformat.cpp      llframetimer.cpp      llheartbeat.cpp +    llheteromap.cpp      llinitparam.cpp +    llinitdestroyclass.cpp      llinstancetracker.cpp      llleap.cpp      llleaplistener.cpp @@ -135,8 +139,10 @@ set(llcommon_HEADER_FILES      llbitpack.h      llboost.h      llcallbacklist.h +    llcleanup.h      llcommon.h      llcommonutils.h +    llcoro_get_id.h      llcoros.h      llcrc.h      llcriticaldamp.h @@ -168,7 +174,9 @@ set(llcommon_HEADER_FILES      llhandle.h      llhash.h      llheartbeat.h +    llheteromap.h      llindexedvector.h +    llinitdestroyclass.h      llinitparam.h      llinstancetracker.h      llkeythrottle.h @@ -185,6 +193,7 @@ set(llcommon_HEADER_FILES      llmortician.h      llnametable.h      llpointer.h +    llpounceable.h      llpredicate.h      llpreprocessor.h      llpriqueuemap.h @@ -329,6 +338,8 @@ if (LL_TESTS)    LL_ADD_INTEGRATION_TEST(llprocess "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}") +  LL_ADD_INTEGRATION_TEST(llpounceable "" "${test_libs}") +  LL_ADD_INTEGRATION_TEST(llheteromap "" "${test_libs}")  ## llexception_test.cpp isn't a regression test, and doesn't need to be run  ## every build. It's to help a developer make implementation choices about diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index eb0699ad41..2c76f29020 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -48,6 +48,7 @@  #include "lleventtimer.h"  #include "google_breakpad/exception_handler.h"  #include "stringize.h" +#include "llcleanup.h"  //  // Signal handling @@ -177,7 +178,7 @@ LLApp::~LLApp()  	if(mExceptionHandler != 0) delete mExceptionHandler; -	LLCommon::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLCommon);  }  // static 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/llcleanup.cpp b/indra/llcommon/llcleanup.cpp new file mode 100644 index 0000000000..c5283507bf --- /dev/null +++ b/indra/llcommon/llcleanup.cpp @@ -0,0 +1,29 @@ +/** + * @file   llcleanup.cpp + * @author Nat Goodspeed + * @date   2016-08-30 + * @brief  Implementation for llcleanup. + *  + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llcleanup.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llerror.h" +#include "llerrorcontrol.h" + +void log_subsystem_cleanup(const char* file, int line, const char* function, +                           const char* classname) +{ +    LL_INFOS("Cleanup") << LLError::abbreviateFile(file) << "(" << line << "): " +                        << "calling " << classname << "::cleanupClass() in " +                        << function << LL_ENDL; +} diff --git a/indra/llcommon/llcleanup.h b/indra/llcommon/llcleanup.h new file mode 100644 index 0000000000..a319171b5f --- /dev/null +++ b/indra/llcommon/llcleanup.h @@ -0,0 +1,33 @@ +/** + * @file   llcleanup.h + * @author Nat Goodspeed + * @date   2015-05-20 + * @brief  Mechanism for cleaning up subsystem resources + *  + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Copyright (c) 2015, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLCLEANUP_H) +#define LL_LLCLEANUP_H + +#include <boost/current_function.hpp> + +// Instead of directly calling SomeClass::cleanupClass(), use +// SUBSYSTEM_CLEANUP(SomeClass); +// This logs the call as well as performing it. That gives us a baseline +// subsystem shutdown order against which to compare subsequent dynamic +// shutdown schemes. +#define SUBSYSTEM_CLEANUP(CLASSNAME)                                    \ +    do {                                                                \ +        log_subsystem_cleanup(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, #CLASSNAME); \ +        CLASSNAME::cleanupClass();                                      \ +    } while (0) +// Use ancient do { ... } while (0) macro trick to permit a block of +// statements with the same syntax as a single statement. + +void log_subsystem_cleanup(const char* file, int line, const char* function, +                           const char* classname); + +#endif /* ! defined(LL_LLCLEANUP_H) */ diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 19642b0982..439ff4e628 100644 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -31,6 +31,7 @@  #include "llthread.h"  #include "lltrace.h"  #include "lltracethreadrecorder.h" +#include "llcleanup.h"  //static  BOOL LLCommon::sAprInitialized = FALSE; @@ -63,11 +64,11 @@ void LLCommon::cleanupClass()  	sMasterThreadRecorder = NULL;  	LLTrace::set_master_thread_recorder(NULL);  	LLThreadSafeRefCount::cleanupThreadSafeRefCount(); -	LLTimer::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLTimer);  	if (sAprInitialized)  	{  		ll_cleanup_apr();  		sAprInitialized = FALSE;  	} -	LLMemory::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLMemory);  } diff --git a/indra/llcommon/llcoro_get_id.cpp b/indra/llcommon/llcoro_get_id.cpp new file mode 100644 index 0000000000..24ed1fe0c9 --- /dev/null +++ b/indra/llcommon/llcoro_get_id.cpp @@ -0,0 +1,32 @@ +/** + * @file   llcoro_get_id.cpp + * @author Nat Goodspeed + * @date   2016-09-03 + * @brief  Implementation for llcoro_get_id. + *  + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llcoro_get_id.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llcoros.h" + +namespace llcoro +{ + +id get_id() +{ +    // An instance of Current can convert to LLCoros::CoroData*, which can +    // implicitly convert to void*, which is an llcoro::id. +    return LLCoros::Current(); +} + +} // llcoro diff --git a/indra/llcommon/llcoro_get_id.h b/indra/llcommon/llcoro_get_id.h new file mode 100644 index 0000000000..4c1dca6f19 --- /dev/null +++ b/indra/llcommon/llcoro_get_id.h @@ -0,0 +1,30 @@ +/** + * @file   llcoro_get_id.h + * @author Nat Goodspeed + * @date   2016-09-03 + * @brief  Supplement the functionality in llcoro.h. + * + *         This is broken out as a separate header file to resolve + *         circularity: LLCoros isa LLSingleton, yet LLSingleton machinery + *         requires llcoro::get_id(). + * + *         Be very suspicious of anyone else #including this header. + *  + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLCORO_GET_ID_H) +#define LL_LLCORO_GET_ID_H + +namespace llcoro +{ + +/// Get an opaque, distinct token for the running coroutine (or main). +typedef void* id; +id get_id(); + +} // llcoro + +#endif /* ! defined(LL_LLCORO_GET_ID_H) */ diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 8e516d8beb..3ffce4810a 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -40,32 +40,79 @@  #include "stringize.h"  #include "llexception.h" -// do nothing, when we need nothing done +namespace { +void no_op() {} +} // anonymous namespace + +// Do nothing, when we need nothing done. This is a static member of LLCoros +// because CoroData is a private nested class.  void LLCoros::no_cleanup(CoroData*) {}  // CoroData for the currently-running coroutine. Use a thread_specific_ptr  // because each thread potentially has its own distinct pool of coroutines. -// This thread_specific_ptr does NOT own the CoroData object! That's owned by -// LLCoros::mCoros. It merely identifies it. For this reason we instantiate -// it with a no-op cleanup function. -boost::thread_specific_ptr<LLCoros::CoroData> -LLCoros::sCurrentCoro(LLCoros::no_cleanup); +LLCoros::Current::Current() +{ +    // Use a function-static instance so this thread_specific_ptr is +    // instantiated on demand. Since we happen to know it's consumed by +    // LLSingleton, this is likely to happen before the runtime has finished +    // initializing module-static data. For the same reason, we can't package +    // this pointer in an LLSingleton. + +    // This thread_specific_ptr does NOT own the CoroData object! That's owned +    // by LLCoros::mCoros. It merely identifies it. For this reason we +    // instantiate it with a no-op cleanup function. +    static boost::thread_specific_ptr<LLCoros::CoroData> sCurrent(LLCoros::no_cleanup); + +    // If this is the first time we're accessing sCurrent for the running +    // thread, its get() will be NULL. This could be a problem, in that +    // llcoro::get_id() would return the same (NULL) token value for the "main +    // coroutine" in every thread, whereas what we really want is a distinct +    // value for every distinct stack in the process. So if get() is NULL, +    // give it a heap CoroData: this ensures that llcoro::get_id() will return +    // distinct values. +    // This tactic is "leaky": sCurrent explicitly does not destroy any +    // CoroData to which it points, and we do NOT enter these "main coroutine" +    // CoroData instances in the LLCoros::mCoros map. They are dummy entries, +    // and they will leak at process shutdown: one CoroData per thread. +    if (! sCurrent.get()) +    { +        // It's tempting to provide a distinct name for each thread's "main +        // coroutine." But as getName() has always returned the empty string +        // to mean "not in a coroutine," empty string should suffice here -- +        // and truthfully the additional (thread-safe!) machinery to ensure +        // uniqueness just doesn't feel worth the trouble. +        // We use a no-op callable and a minimal stack size because, although +        // CoroData's constructor in fact initializes its mCoro with a +        // coroutine with that stack size, no one ever actually enters it by +        // calling mCoro(). +        sCurrent.reset(new CoroData(0,  // no prev +                                    "", // not a named coroutine +                                    no_op,  // no-op callable +                                    1024)); // stacksize moot +    } + +    mCurrent = &sCurrent; +}  //static  LLCoros::CoroData& LLCoros::get_CoroData(const std::string& caller)  { -    CoroData* current = sCurrentCoro.get(); -    if (! current) -    { -        LL_ERRS("LLCoros") << "Calling " << caller << " from non-coroutine context!" << LL_ENDL; -    } +    CoroData* current = Current(); +    // With the dummy CoroData set in LLCoros::Current::Current(), this +    // pointer should never be NULL. +    llassert_always(current);      return *current;  }  //static  LLCoros::coro::self& LLCoros::get_self()  { -    return *get_CoroData("get_self()").mSelf; +    CoroData& current = get_CoroData("get_self()"); +    if (! current.mSelf) +    { +        LL_ERRS("LLCoros") << "Calling get_self() from non-coroutine context!" << LL_ENDL; +    } +    return *current.mSelf;  }  //static @@ -80,20 +127,23 @@ bool LLCoros::get_consuming()      return get_CoroData("get_consuming()").mConsuming;  } -llcoro::Suspending::Suspending(): -    mSuspended(LLCoros::sCurrentCoro.get()) +llcoro::Suspending::Suspending()  { -    // Revert mCurrentCoro to the value it had at the moment we last switched +    LLCoros::Current current; +    // Remember currently-running coroutine: we're about to suspend it. +    mSuspended = current; +    // Revert Current to the value it had at the moment we last switched      // into this coroutine. -    LLCoros::sCurrentCoro.reset(mSuspended->mPrev); +    current.reset(mSuspended->mPrev);  }  llcoro::Suspending::~Suspending()  { +    LLCoros::Current current;      // Okay, we're back, update our mPrev -    mSuspended->mPrev = LLCoros::sCurrentCoro.get(); -    // and reinstate our sCurrentCoro. -    LLCoros::sCurrentCoro.reset(mSuspended); +    mSuspended->mPrev = current; +    // and reinstate our Current. +    current.reset(mSuspended);  }  LLCoros::LLCoros(): @@ -213,13 +263,7 @@ bool LLCoros::kill(const std::string& name)  std::string LLCoros::getName() const  { -    CoroData* current = sCurrentCoro.get(); -    if (! current) -    { -        // not in a coroutine -        return ""; -    } -    return current->mName; +    return Current()->mName;  }  void LLCoros::setStackSize(S32 stacksize) @@ -229,8 +273,8 @@ void LLCoros::setStackSize(S32 stacksize)  }  // Top-level wrapper around caller's coroutine callable. This function accepts -// the coroutine library's implicit coro::self& parameter and sets sCurrentSelf -// but does not pass it down to the caller's callable. +// the coroutine library's implicit coro::self& parameter and saves it, but +// does not pass it down to the caller's callable.  void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& callable)  {      // capture the 'self' param in CoroData @@ -254,8 +298,8 @@ void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& calla          CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << data->mName));      }      // This cleanup isn't perfectly symmetrical with the way we initially set -    // data->mPrev, but this is our last chance to reset mCurrentCoro. -    sCurrentCoro.reset(data->mPrev); +    // data->mPrev, but this is our last chance to reset Current. +    Current().reset(data->mPrev);  }  /***************************************************************************** @@ -278,7 +322,7 @@ LLCoros::CoroData::CoroData(CoroData* prev, const std::string& name,      mPrev(prev),      mName(name),      // Wrap the caller's callable in our toplevel() function so we can manage -    // sCurrentCoro appropriately at startup and shutdown of each coroutine. +    // Current appropriately at startup and shutdown of each coroutine.      mCoro(boost::bind(toplevel, _1, this, callable), stacksize),      // don't consume events unless specifically directed      mConsuming(false), @@ -289,13 +333,13 @@ LLCoros::CoroData::CoroData(CoroData* prev, const std::string& name,  std::string LLCoros::launch(const std::string& prefix, const callable_t& callable)  {      std::string name(generateDistinctName(prefix)); -    // pass the current value of sCurrentCoro as previous context -    CoroData* newCoro = new CoroData(sCurrentCoro.get(), name, -                                     callable, mStackSize); +    Current current; +    // pass the current value of Current as previous context +    CoroData* newCoro = new CoroData(current, name, callable, mStackSize);      // Store it in our pointer map      mCoros.insert(name, newCoro);      // also set it as current -    sCurrentCoro.reset(newCoro); +    current.reset(newCoro);      /* Run the coroutine until its first wait, then return here */      (newCoro->mCoro)(std::nothrow);      return name; diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 39316ed0e6..bbe2d22af4 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -35,8 +35,10 @@  #include <boost/ptr_container/ptr_map.hpp>  #include <boost/function.hpp>  #include <boost/thread/tss.hpp> +#include <boost/noncopyable.hpp>  #include <string>  #include <stdexcept> +#include "llcoro_get_id.h"          // for friend declaration  // forward-declare helper class  namespace llcoro @@ -83,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; @@ -173,9 +176,8 @@ 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;      bool cleanup(const LLSD&);      struct CoroData; @@ -222,8 +224,22 @@ private:      typedef boost::ptr_map<std::string, CoroData> CoroMap;      CoroMap mCoros; -    // identify the current coroutine's CoroData -    static boost::thread_specific_ptr<LLCoros::CoroData> sCurrentCoro; +    // Identify the current coroutine's CoroData. Use a little helper class so +    // a caller can either use a temporary instance, or instantiate a named +    // variable and access it multiple times. +    class Current +    { +    public: +        Current(); + +        operator LLCoros::CoroData*() { return get(); } +        LLCoros::CoroData* operator->() { return get(); } +        LLCoros::CoroData* get() { return mCurrent->get(); } +        void reset(LLCoros::CoroData* ptr) { mCurrent->reset(ptr); } + +    private: +        boost::thread_specific_ptr<LLCoros::CoroData>* mCurrent; +    };  };  namespace llcoro @@ -231,7 +247,7 @@ namespace llcoro  /// Instantiate one of these in a block surrounding any leaf point when  /// control literally switches away from this coroutine. -class Suspending +class Suspending: boost::noncopyable  {  public:      Suspending(); diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 6a62860c3f..229442cec1 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -239,6 +239,14 @@ namespace  {  	std::string className(const std::type_info& type)  	{ +		return LLError::Log::demangle(type.name()); +	} +} // anonymous + +namespace LLError +{ +	std::string Log::demangle(const char* mangled) +	{  #ifdef __GNUC__  		// GCC: type_info::name() returns a mangled class name,st demangle @@ -252,31 +260,34 @@ namespace  			// but gcc 3.3 libstc++'s implementation of demangling is broken  			// and fails without. -		char* name = abi::__cxa_demangle(type.name(), +		char* name = abi::__cxa_demangle(mangled,  										abi_name_buf, &abi_name_len, &status);  			// this call can realloc the abi_name_buf pointer (!) -		return name ? name : type.name(); +		return name ? name : mangled;  #elif LL_WINDOWS  		// DevStudio: type_info::name() includes the text "class " at the start  		static const std::string class_prefix = "class "; - -		std::string name = type.name(); -		std::string::size_type p = name.find(class_prefix); -		if (p == std::string::npos) +		std::string name = mangled; +		if (0 != name.compare(0, class_prefix.length(), class_prefix))  		{ +			LL_DEBUGS() << "Did not see '" << class_prefix << "' prefix on '" +					   << name << "'" << LL_ENDL;  			return name;  		} -		return name.substr(p + class_prefix.size()); +		return name.substr(class_prefix.length()); -#else		 -		return type.name(); +#else +		return mangled;  #endif  	} +} // LLError +namespace +{  	std::string functionName(const std::string& preprocessor_name)  	{  #if LL_WINDOWS @@ -363,9 +374,8 @@ namespace  	class Globals : public LLSingleton<Globals>  	{ +		LLSINGLETON(Globals);  	public: -		Globals(); -  		std::ostringstream messageStream;  		bool messageStreamInUse; @@ -438,11 +448,10 @@ namespace LLError  	class Settings : public LLSingleton<Settings>  	{ +		LLSINGLETON(Settings);  	public: -		Settings(); -  		SettingsConfigPtr getSettingsConfig(); -	 +  		void reset();  		SettingsStoragePtr saveAndReset();  		void restore(SettingsStoragePtr pSettingsStorage); @@ -450,7 +459,7 @@ namespace LLError  	private:  		SettingsConfigPtr mSettingsConfig;  	}; -	 +  	SettingsConfig::SettingsConfig()  		: LLRefCount(),  		mPrintLocation(false), @@ -475,8 +484,7 @@ namespace LLError  		mRecorders.clear();  	} -	Settings::Settings() -		: LLSingleton<Settings>(), +	Settings::Settings():  		mSettingsConfig(new SettingsConfig())  	{  	} @@ -485,26 +493,31 @@ namespace LLError  	{  		return mSettingsConfig;  	} -	 +  	void Settings::reset()  	{  		Globals::getInstance()->invalidateCallSites();  		mSettingsConfig = new SettingsConfig();  	} -	 +  	SettingsStoragePtr Settings::saveAndReset()  	{  		SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get());  		reset();  		return oldSettingsConfig;  	} -	 +  	void Settings::restore(SettingsStoragePtr pSettingsStorage)  	{  		Globals::getInstance()->invalidateCallSites();  		SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get()));  		mSettingsConfig = newSettingsConfig;  	} + +	bool is_available() +	{ +		return Settings::instanceExists() && Globals::instanceExists(); +	}  }  namespace LLError diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 7cbe4334b3..ce4d4552df 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -190,6 +190,7 @@ namespace LLError  		static std::ostringstream* out();  		static void flush(std::ostringstream* out, char* message);  		static void flush(std::ostringstream*, const CallSite&); +		static std::string demangle(const char* mangled);  	};  	struct LL_COMMON_API CallSite diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index 56ac52e5de..56e84f7172 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -189,6 +189,11 @@ namespace LLError  	LL_COMMON_API std::string abbreviateFile(const std::string& filePath);  	LL_COMMON_API int shouldLogCallCount(); + +	// Check whether Globals exists. This should only be used by LLSingleton +	// infrastructure to avoid trying to log when our internal LLSingleton is +	// unavailable -- circularity ensues. +	LL_COMMON_API bool is_available();  };  #endif // LL_LLERRORCONTROL_H diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index a3b9ec02e0..7cff7dfd45 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -229,7 +229,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 @@ -272,7 +272,6 @@ private:      void unregister(const LLEventPump&);  private: -    LLEventPumps();      ~LLEventPumps();  testable: diff --git a/indra/llcommon/llheteromap.cpp b/indra/llcommon/llheteromap.cpp new file mode 100644 index 0000000000..7c19196e0c --- /dev/null +++ b/indra/llcommon/llheteromap.cpp @@ -0,0 +1,32 @@ +/** + * @file   llheteromap.cpp + * @author Nat Goodspeed + * @date   2016-10-12 + * @brief  Implementation for llheteromap. + *  + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llheteromap.h" +// STL headers +// std headers +// external library headers +// other Linden headers + +LLHeteroMap::~LLHeteroMap() +{ +    // For each entry in our map, we must call its deleter, which is the only +    // record we have of its original type. +    for (TypeMap::iterator mi(mMap.begin()), me(mMap.end()); mi != me; ++mi) +    { +        // mi->second is the std::pair; mi->second.first is the void*; +        // mi->second.second points to the deleter function +        (mi->second.second)(mi->second.first); +        mi->second.first = NULL; +    } +} diff --git a/indra/llcommon/llheteromap.h b/indra/llcommon/llheteromap.h new file mode 100644 index 0000000000..9d6f303d08 --- /dev/null +++ b/indra/llcommon/llheteromap.h @@ -0,0 +1,95 @@ +/** + * @file   llheteromap.h + * @author Nat Goodspeed + * @date   2016-10-12 + * @brief  Map capable of storing objects of diverse types, looked up by type. + *  + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLHETEROMAP_H) +#define LL_LLHETEROMAP_H + +#include <typeinfo> +#include <utility>                  // std::pair +#include <map> + +/** + * LLHeteroMap addresses an odd requirement. Usually when you want to put + * objects of different classes into a runtime collection of any kind, you + * derive them all from a common base class and store pointers to that common + * base class. + * + * LLInitParam::BaseBlock uses disturbing raw-pointer arithmetic to find data + * members in its subclasses. It seems that no BaseBlock subclass can be + * stored in a polymorphic class of any kind: the presence of a vtbl pointer + * in the layout silently throws off the reinterpret_cast arithmetic. Bad + * Things result. (Many thanks to Nicky D for this analysis!) + * + * LLHeteroMap collects objects WITHOUT a common base class, retrieves them by + * object type and destroys them when the LLHeteroMap is destroyed. + */ +class LLHeteroMap +{ +public: +    ~LLHeteroMap(); + +    /// find or create +    template <class T> +    T& obtain() +    { +        // Look up map entry by typeid(T). We don't simply use mMap[typeid(T)] +        // because that requires default-constructing T on every lookup. For +        // some kinds of T, that could be expensive. +        TypeMap::iterator found = mMap.find(&typeid(T)); +        if (found == mMap.end()) +        { +            // Didn't find typeid(T). Create an entry. Because we're storing +            // only a void* in the map, discarding type information, make sure +            // we capture that type information in our deleter. +            void* ptr = new T(); +            void (*dlfn)(void*) = &deleter<T>; +            std::pair<TypeMap::iterator, bool> inserted = +                mMap.insert(TypeMap::value_type(&typeid(T), +                    TypeMap::mapped_type(ptr, dlfn))); +            // Okay, now that we have an entry, claim we found it. +            found = inserted.first; +        } +        // found->second is the std::pair; second.first is the void* +        // pointer to the object in question. Cast it to correct type and +        // dereference it. +        return *(static_cast<T*>(found->second.first)); +    } + +private: +    template <class T> +    static +    void deleter(void* p) +    { +        delete static_cast<T*>(p); +    } + +    // Comparing two std::type_info* values is tricky, because the standard +    // does not guarantee that there will be only one type_info instance for a +    // given type. In other words, &typeid(A) in one part of the program may +    // not always equal &typeid(A) in some other part. Use special comparator. +    struct type_info_ptr_comp +    { +        bool operator()(const std::type_info* lhs, const std::type_info* rhs) +        { +            return lhs->before(*rhs); +        } +    }; + +    // What we actually store is a map from std::type_info (permitting lookup +    // by object type) to a void* pointer to the object PLUS its deleter. +    typedef std::map< +        const std::type_info*, std::pair<void*, void (*)(void*)>, +        type_info_ptr_comp> +    TypeMap; +    TypeMap mMap; +}; + +#endif /* ! defined(LL_LLHETEROMAP_H) */ diff --git a/indra/llcommon/llinitdestroyclass.cpp b/indra/llcommon/llinitdestroyclass.cpp new file mode 100644 index 0000000000..e6382a7924 --- /dev/null +++ b/indra/llcommon/llinitdestroyclass.cpp @@ -0,0 +1,30 @@ +/** + * @file   llinitdestroyclass.cpp + * @author Nat Goodspeed + * @date   2016-08-30 + * @brief  Implementation for llinitdestroyclass. + *  + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llinitdestroyclass.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llerror.h" + +void LLCallbackRegistry::fireCallbacks() const +{ +	for (FuncList::const_iterator fi = mCallbacks.begin(), fe = mCallbacks.end(); +		 fi != fe; ++fi) +	{ +		LL_INFOS("LLInitDestroyClass") << "calling " << fi->first << "()" << LL_ENDL; +		fi->second(); +	} +} diff --git a/indra/llcommon/llinitdestroyclass.h b/indra/llcommon/llinitdestroyclass.h new file mode 100644 index 0000000000..5f979614fe --- /dev/null +++ b/indra/llcommon/llinitdestroyclass.h @@ -0,0 +1,175 @@ +/** + * @file   llinitdestroyclass.h + * @author Nat Goodspeed + * @date   2015-05-27 + * @brief  LLInitClass / LLDestroyClass mechanism + * + * The LLInitClass template, extracted from llui.h, ensures that control will + * reach a static initClass() method. LLDestroyClass does the same for a + * static destroyClass() method. + * + * The distinguishing characteristics of these templates are: + * + * - All LLInitClass<T>::initClass() methods are triggered by an explicit call + *   to LLInitClassList::instance().fireCallbacks(). Presumably this call + *   happens sometime after all static objects in the program have been + *   initialized. In other words, each LLInitClass<T>::initClass() method + *   should be able to make some assumptions about global program state. + * + * - Similarly, LLDestroyClass<T>::destroyClass() methods are triggered by + *   LLDestroyClassList::instance().fireCallbacks(). Again, presumably this + *   happens at a well-defined moment in the program's shutdown sequence. + * + * - The initClass() calls happen in an unspecified sequence. You may not rely + *   on the relative ordering of LLInitClass<T>::initClass() versus another + *   LLInitClass<U>::initClass() method. If you need such a guarantee, use + *   LLSingleton instead and make the dependency explicit. + * + * - Similarly, LLDestroyClass<T>::destroyClass() may happen either before or + *   after LLDestroyClass<U>::destroyClass(). You cannot rely on that order. + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Copyright (c) 2015, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLINITDESTROYCLASS_H) +#define LL_LLINITDESTROYCLASS_H + +#include "llsingleton.h" +#include <boost/function.hpp> +#include <typeinfo> +#include <vector> +#include <utility>                  // std::pair + +/** + * LLCallbackRegistry is an implementation detail base class for + * LLInitClassList and LLDestroyClassList. It accumulates the initClass() or + * destroyClass() callbacks for registered classes. + */ +class LLCallbackRegistry +{ +public: +	typedef boost::function<void()> func_t; + +	void registerCallback(const std::string& name, const func_t& func) +	{ +		mCallbacks.push_back(FuncList::value_type(name, func)); +	} + +	void fireCallbacks() const; + +private: +	// Arguably this should be a boost::signals2::signal, which is, after all, +	// a sequence of callables. We manage it by hand so we can log a name for +	// each registered function we call. +	typedef std::vector< std::pair<std::string, func_t> > FuncList; +	FuncList mCallbacks; +}; + +/** + * LLInitClassList is the LLCallbackRegistry for LLInitClass. It stores the + * registered initClass() methods. It must be an LLSingleton because + * LLInitClass registers its initClass() method at static construction time + * (before main()), requiring LLInitClassList to be fully constructed on + * demand regardless of module initialization order. + */ +class LLInitClassList :  +	public LLCallbackRegistry,  +	public LLSingleton<LLInitClassList> +{ +	LLSINGLETON_EMPTY_CTOR(LLInitClassList); +}; + +/** + * LLDestroyClassList is the LLCallbackRegistry for LLDestroyClass. It stores + * the registered destroyClass() methods. It must be an LLSingleton because + * LLDestroyClass registers its destroyClass() method at static construction + * time (before main()), requiring LLDestroyClassList to be fully constructed + * on demand regardless of module initialization order. + */ +class LLDestroyClassList :  +	public LLCallbackRegistry,  +	public LLSingleton<LLDestroyClassList> +{ +	LLSINGLETON_EMPTY_CTOR(LLDestroyClassList); +}; + +/** + * LLRegisterWith is an implementation detail for LLInitClass and + * LLDestroyClass. It is intended to be used as a static class member whose + * constructor registers the specified callback with the LLMumbleClassList + * singleton registry specified as the template argument. + */ +template<typename T> +class LLRegisterWith +{ +public: +	LLRegisterWith(const std::string& name, const LLCallbackRegistry::func_t& func) +	{ +		T::instance().registerCallback(name, func); +	} + +	// this avoids a MSVC bug where non-referenced static members are "optimized" away +	// even if their constructors have side effects +	S32 reference() +	{ +		S32 dummy; +		dummy = 0; +		return dummy; +	} +}; + +/** + * Derive MyClass from LLInitClass<MyClass> (the Curiously Recurring Template + * Pattern) to ensure that the static method MyClass::initClass() will be + * called (along with all other LLInitClass<T> subclass initClass() methods) + * when someone calls LLInitClassList::instance().fireCallbacks(). This gives + * the application specific control over the timing of all such + * initializations, without having to insert calls for every such class into + * generic application code. + */ +template<typename T> +class LLInitClass +{ +public: +	LLInitClass() { sRegister.reference(); } + +	// When this static member is initialized, the subclass initClass() method +	// is registered on LLInitClassList. See sRegister definition below. +	static LLRegisterWith<LLInitClassList> sRegister; +}; + +/** + * Derive MyClass from LLDestroyClass<MyClass> (the Curiously Recurring + * Template Pattern) to ensure that the static method MyClass::destroyClass() + * will be called (along with other LLDestroyClass<T> subclass destroyClass() + * methods) when someone calls LLDestroyClassList::instance().fireCallbacks(). + * This gives the application specific control over the timing of all such + * cleanup calls, without having to insert calls for every such class into + * generic application code. + */ +template<typename T> +class LLDestroyClass +{ +public: +	LLDestroyClass() { sRegister.reference(); } + +	// When this static member is initialized, the subclass destroyClass() +	// method is registered on LLInitClassList. See sRegister definition +	// below. +	static LLRegisterWith<LLDestroyClassList> sRegister; +}; + +// Here's where LLInitClass<T> specifies the subclass initClass() method. +template <typename T> +LLRegisterWith<LLInitClassList> +LLInitClass<T>::sRegister(std::string(typeid(T).name()) + "::initClass", +						  &T::initClass); +// Here's where LLDestroyClass<T> specifies the subclass destroyClass() method. +template <typename T> +LLRegisterWith<LLDestroyClassList> +LLDestroyClass<T>::sRegister(std::string(typeid(T).name()) + "::destroyClass", +							 &T::destroyClass); + +#endif /* ! defined(LL_LLINITDESTROYCLASS_H) */ diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp index 1fc821d9a9..16fc365da1 100644 --- a/indra/llcommon/llmetricperformancetester.cpp +++ b/indra/llcommon/llmetricperformancetester.cpp @@ -40,7 +40,7 @@  LLMetricPerformanceTesterBasic::name_tester_map_t LLMetricPerformanceTesterBasic::sTesterMap ;  /*static*/  -void LLMetricPerformanceTesterBasic::cleanClass()  +void LLMetricPerformanceTesterBasic::cleanupClass()   {  	for (name_tester_map_t::iterator iter = sTesterMap.begin() ; iter != sTesterMap.end() ; ++iter)  	{ diff --git a/indra/llcommon/llmetricperformancetester.h b/indra/llcommon/llmetricperformancetester.h index 1a18cdf36f..e6b46be1cf 100644 --- a/indra/llcommon/llmetricperformancetester.h +++ b/indra/llcommon/llmetricperformancetester.h @@ -156,7 +156,7 @@ public:  	/**  	 * @brief Delete all testers and reset the tester map  	 */ -	static void cleanClass() ; +	static void cleanupClass() ;  private:  	// Add a tester to the map. Returns false if adding fails. diff --git a/indra/llcommon/llpounceable.h b/indra/llcommon/llpounceable.h new file mode 100644 index 0000000000..0421ce966a --- /dev/null +++ b/indra/llcommon/llpounceable.h @@ -0,0 +1,216 @@ +/** + * @file   llpounceable.h + * @author Nat Goodspeed + * @date   2015-05-22 + * @brief  LLPounceable is tangentially related to a future: it's a holder for + *         a value that may or may not exist yet. Unlike a future, though, + *         LLPounceable freely allows reading the held value. (If the held + *         type T does not have a distinguished "empty" value, consider using + *         LLPounceable<boost::optional<T>>.) + * + *         LLPounceable::callWhenReady() is this template's claim to fame. It + *         allows its caller to "pounce" on the held value as soon as it + *         becomes non-empty. Call callWhenReady() with any C++ callable + *         accepting T. If the held value is already non-empty, callWhenReady() + *         will immediately call the callable with the held value. If the held + *         value is empty, though, callWhenReady() will enqueue the callable + *         for later. As soon as LLPounceable is assigned a non-empty held + *         value, it will flush the queue of deferred callables. + * + *         Consider a global LLMessageSystem* gMessageSystem. Message system + *         initialization happens at a very specific point during viewer + *         initialization. Other subsystems want to register callbacks on the + *         LLMessageSystem instance as soon as it's initialized, but their own + *         initialization may precede that. If we define gMessageSystem to be + *         an LLPounceable<LLMessageSystem*>, a subsystem can use + *         callWhenReady() to either register immediately (if gMessageSystem + *         is already up and runnning) or register as soon as gMessageSystem + *         is set with a new, initialized instance. + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Copyright (c) 2015, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLPOUNCEABLE_H) +#define LL_LLPOUNCEABLE_H + +#include "llsingleton.h" +#include <boost/noncopyable.hpp> +#include <boost/call_traits.hpp> +#include <boost/type_traits/remove_pointer.hpp> +#include <boost/utility/value_init.hpp> +#include <boost/unordered_map.hpp> +#include <boost/signals2/signal.hpp> + +// Forward declare the user template, since we want to be able to point to it +// in some of its implementation classes. +template <typename T, class TAG> +class LLPounceable; + +template <typename T, typename TAG> +struct LLPounceableTraits +{ +    // Our "queue" is a signal object with correct signature. +    typedef boost::signals2::signal<void (typename boost::call_traits<T>::param_type)> signal_t; +    // Call callWhenReady() with any callable accepting T. +    typedef typename signal_t::slot_type func_t; +    // owner pointer type +    typedef LLPounceable<T, TAG>* owner_ptr; +}; + +// Tag types distinguish the two different implementations of LLPounceable's +// queue. +struct LLPounceableQueue {}; +struct LLPounceableStatic {}; + +// generic LLPounceableQueueImpl deliberately omitted: only the above tags are +// legal +template <typename T, class TAG> +class LLPounceableQueueImpl; + +// The implementation selected by LLPounceableStatic uses an LLSingleton +// because we can't count on a data member queue being initialized at the time +// we start getting callWhenReady() calls. This is that LLSingleton. +template <typename T> +class LLPounceableQueueSingleton: +    public LLSingleton<LLPounceableQueueSingleton<T> > +{ +    LLSINGLETON_EMPTY_CTOR(LLPounceableQueueSingleton); + +    typedef LLPounceableTraits<T, LLPounceableStatic> traits; +    typedef typename traits::owner_ptr owner_ptr; +    typedef typename traits::signal_t signal_t; + +    // For a given held type T, every LLPounceable<T, LLPounceableStatic> +    // instance will call on the SAME LLPounceableQueueSingleton instance -- +    // given how class statics work. We must keep a separate queue for each +    // LLPounceable instance. Use a hash map for that. +    typedef boost::unordered_map<owner_ptr, signal_t> map_t; + +public: +    // Disambiguate queues belonging to different LLPounceables. +    signal_t& get(owner_ptr owner) +    { +        // operator[] has find-or-create semantics -- just what we want! +        return mMap[owner]; +    } + +private: +    map_t mMap; +}; + +// LLPounceableQueueImpl that uses the above LLSingleton +template <typename T> +class LLPounceableQueueImpl<T, LLPounceableStatic> +{ +public: +    typedef LLPounceableTraits<T, LLPounceableStatic> traits; +    typedef typename traits::owner_ptr owner_ptr; +    typedef typename traits::signal_t signal_t; + +    signal_t& get(owner_ptr owner) const +    { +        // this Impl contains nothing; it delegates to the Singleton +        return LLPounceableQueueSingleton<T>::instance().get(owner); +    } +}; + +// The implementation selected by LLPounceableQueue directly contains the +// queue of interest, suitable for an LLPounceable we can trust to be fully +// initialized when it starts getting callWhenReady() calls. +template <typename T> +class LLPounceableQueueImpl<T, LLPounceableQueue> +{ +public: +    typedef LLPounceableTraits<T, LLPounceableQueue> traits; +    typedef typename traits::owner_ptr owner_ptr; +    typedef typename traits::signal_t signal_t; + +    signal_t& get(owner_ptr) +    { +        return mQueue; +    } + +private: +    signal_t mQueue; +}; + +// LLPounceable<T> is for an LLPounceable instance on the heap or the stack. +// LLPounceable<T, LLPounceableStatic> is for a static LLPounceable instance. +template <typename T, class TAG=LLPounceableQueue> +class LLPounceable: public boost::noncopyable +{ +private: +    typedef LLPounceableTraits<T, TAG> traits; +    typedef typename traits::owner_ptr owner_ptr; +    typedef typename traits::signal_t signal_t; + +public: +    typedef typename traits::func_t func_t; + +    // By default, both the initial value and the distinguished empty value +    // are a default-constructed T instance. However you can explicitly +    // specify each. +    LLPounceable(typename boost::call_traits<T>::value_type init =boost::value_initialized<T>(), +                 typename boost::call_traits<T>::param_type empty=boost::value_initialized<T>()): +        mHeld(init), +        mEmpty(empty) +    {} + +    // make read access to mHeld as cheap and transparent as possible +    operator T () const { return mHeld; } +    typename boost::remove_pointer<T>::type operator*() const { return *mHeld; } +    typename boost::call_traits<T>::value_type operator->() const { return mHeld; } +    // uncomment 'explicit' as soon as we allow C++11 compilation +    /*explicit*/ operator bool() const { return bool(mHeld); } +    bool operator!() const { return ! mHeld; } + +    // support both assignment (dumb ptr idiom) and reset() (smart ptr) +    void operator=(typename boost::call_traits<T>::param_type value) +    { +        reset(value); +    } + +    void reset(typename boost::call_traits<T>::param_type value) +    { +        mHeld = value; +        // If this new value is non-empty, flush anything pending in the queue. +        if (mHeld != mEmpty) +        { +            signal_t& signal(get_signal()); +            signal(mHeld); +            signal.disconnect_all_slots(); +        } +    } + +    // our claim to fame +    void callWhenReady(const func_t& func) +    { +        if (mHeld != mEmpty) +        { +            // If the held value is already non-empty, immediately call func() +            func(mHeld); +        } +        else +        { +            // Held value still empty, queue func() for later. By default, +            // connect() enqueues slots in FIFO order. +            get_signal().connect(func); +        } +    } + +private: +    signal_t& get_signal() { return mQueue.get(this); } + +    // Store both the current and the empty value. +    // MAYBE: Might be useful to delegate to LLPounceableTraits the meaning of +    // testing for "empty." For some types we want operator!(); for others we +    // want to compare to a distinguished value. +    typename boost::call_traits<T>::value_type mHeld, mEmpty; +    // This might either contain the queue (LLPounceableQueue) or delegate to +    // an LLSingleton (LLPounceableStatic). +    LLPounceableQueueImpl<T, TAG> mQueue; +}; + +#endif /* ! defined(LL_LLPOUNCEABLE_H) */ diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h index 29950c108d..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; @@ -269,7 +272,7 @@ public:  		~ScopedRegistrar()  		{ -			if (!singleton_t::destroyed()) +			if (singleton_t::instanceExists())  			{  				popScope();  			} diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp index 9b49e52377..9025e53bb2 100644 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -25,7 +25,445 @@   */  #include "linden_common.h" -  #include "llsingleton.h" +#include "llerror.h" +#include "llerrorcontrol.h"         // LLError::is_available() +#include "lldependencies.h" +#include "llcoro_get_id.h" +#include <boost/foreach.hpp> +#include <boost/unordered_map.hpp> +#include <algorithm> +#include <iostream>                 // std::cerr in dire emergency +#include <sstream> +#include <stdexcept> + +namespace { +void log(LLError::ELevel level, +         const char* p1, const char* p2, const char* p3, const char* p4); + +void logdebugs(const char* p1="", const char* p2="", const char* p3="", const char* p4=""); + +bool oktolog(); +} // anonymous namespace + +// Our master list of all LLSingletons is itself an LLSingleton. We used to +// store it in a function-local static, but that could get destroyed before +// the last of the LLSingletons -- and ~LLSingletonBase() definitely wants to +// remove itself from the master list. Since the whole point of this master +// list is to help track inter-LLSingleton dependencies, and since we have +// this implicit dependency from every LLSingleton to the master list, make it +// an LLSingleton. +class LLSingletonBase::MasterList: +    public LLSingleton<LLSingletonBase::MasterList> +{ +    LLSINGLETON_EMPTY_CTOR(MasterList); + +public: +    // No need to make this private with accessors; nobody outside this source +    // file can see it. + +    // This is the master list of all instantiated LLSingletons (save the +    // MasterList itself) in arbitrary order. You MUST call dep_sort() before +    // traversing this list. +    LLSingletonBase::list_t mMaster; + +    // We need to maintain a stack of LLSingletons currently being +    // initialized, either in the constructor or in initSingleton(). However, +    // managing that as a stack depends on having a DISTINCT 'initializing' +    // stack for every C++ stack in the process! And we have a distinct C++ +    // stack for every running coroutine. It would be interesting and cool to +    // implement a generic coroutine-local-storage mechanism and use that +    // here. The trouble is that LLCoros is itself an LLSingleton, so +    // depending on LLCoros functionality could dig us into infinite +    // recursion. (Moreover, when we reimplement LLCoros on top of +    // Boost.Fiber, that library already provides fiber_specific_ptr -- so +    // it's not worth a great deal of time and energy implementing a generic +    // equivalent on top of boost::dcoroutine, which is on its way out.) +    // Instead, use a map of llcoro::id to select the appropriate +    // coro-specific 'initializing' stack. llcoro::get_id() is carefully +    // implemented to avoid requiring LLCoros. +    typedef boost::unordered_map<llcoro::id, LLSingletonBase::list_t> InitializingMap; +    InitializingMap mInitializing; + +    // non-static method, cf. LLSingletonBase::get_initializing() +    list_t& get_initializing_() +    { +        // map::operator[] has find-or-create semantics, exactly what we need +        // here. It returns a reference to the selected mapped_type instance. +        return mInitializing[llcoro::get_id()]; +    } + +    void cleanup_initializing_() +    { +        InitializingMap::iterator found = mInitializing.find(llcoro::get_id()); +        if (found != mInitializing.end()) +        { +            mInitializing.erase(found); +        } +    } +}; + +//static +LLSingletonBase::list_t& LLSingletonBase::get_master() +{ +    return LLSingletonBase::MasterList::instance().mMaster; +} + +void LLSingletonBase::add_master() +{ +    // As each new LLSingleton is constructed, add to the master list. +    get_master().push_back(this); +} + +void LLSingletonBase::remove_master() +{ +    // When an LLSingleton is destroyed, remove from master list. +    // add_master() used to capture the iterator to the newly-added list item +    // so we could directly erase() it from the master list. Unfortunately +    // that runs afoul of destruction-dependency order problems. So search the +    // master list, and remove this item IF FOUND. We have few enough +    // LLSingletons, and they are so rarely destroyed (once per run), that the +    // cost of a linear search should not be an issue. +    get_master().remove(this); +} + +//static +LLSingletonBase::list_t& LLSingletonBase::get_initializing() +{ +    return LLSingletonBase::MasterList::instance().get_initializing_(); +} + +//static +LLSingletonBase::list_t& LLSingletonBase::get_initializing_from(MasterList* master) +{ +    return master->get_initializing_(); +} + +LLSingletonBase::~LLSingletonBase() {} + +void LLSingletonBase::push_initializing(const char* name) +{ +    // log BEFORE pushing so logging singletons don't cry circularity +    log_initializing("Pushing", name); +    get_initializing().push_back(this); +} + +void LLSingletonBase::pop_initializing() +{ +    list_t& list(get_initializing()); + +    if (list.empty()) +    { +        logerrs("Underflow in stack of currently-initializing LLSingletons at ", +                demangle(typeid(*this).name()).c_str(), "::getInstance()"); +    } + +    // Now we know list.back() exists: capture it +    LLSingletonBase* back(list.back()); +    // and pop it +    list.pop_back(); + +    // The viewer launches an open-ended number of coroutines. While we don't +    // expect most of them to initialize LLSingleton instances, our present +    // get_initializing() logic could lead to an open-ended number of map +    // entries. So every time we pop the stack back to empty, delete the entry +    // entirely. +    if (list.empty()) +    { +        MasterList::instance().cleanup_initializing_(); +    } + +    // Now validate the newly-popped LLSingleton. +    if (back != this) +    { +        logerrs("Push/pop mismatch in stack of currently-initializing LLSingletons: ", +                demangle(typeid(*this).name()).c_str(), "::getInstance() trying to pop ", +                demangle(typeid(*back).name()).c_str()); +    } + +    // log AFTER popping so logging singletons don't cry circularity +    log_initializing("Popping", typeid(*back).name()); +} + +//static +void LLSingletonBase::log_initializing(const char* verb, const char* name) +{ +    if (oktolog()) +    { +        LL_DEBUGS("LLSingleton") << verb << ' ' << demangle(name) << ';'; +        list_t& list(get_initializing()); +        for (list_t::const_reverse_iterator ri(list.rbegin()), rend(list.rend()); +             ri != rend; ++ri) +        { +            LLSingletonBase* sb(*ri); +            LL_CONT << ' ' << demangle(typeid(*sb).name()); +        } +        LL_ENDL; +    } +} + +void LLSingletonBase::capture_dependency(list_t& initializing, EInitState initState) +{ +    // Did this getInstance() call come from another LLSingleton, or from +    // vanilla application code? Note that although this is a nontrivial +    // method, the vast majority of its calls arrive here with initializing +    // empty(). +    if (! initializing.empty()) +    { +        // getInstance() is being called by some other LLSingleton. But -- is +        // this a circularity? That is, does 'this' already appear in the +        // initializing stack? +        // For what it's worth, normally 'initializing' should contain very +        // few elements. +        list_t::const_iterator found = +            std::find(initializing.begin(), initializing.end(), this); +        if (found != initializing.end()) +        { +            // Report the circularity. Requiring the coder to dig through the +            // logic to diagnose exactly how we got here is less than helpful. +            std::ostringstream out; +            for ( ; found != initializing.end(); ++found) +            { +                // 'found' is an iterator; *found is an LLSingletonBase*; **found +                // is the actual LLSingletonBase instance. +                LLSingletonBase* foundp(*found); +                out << demangle(typeid(*foundp).name()) << " -> "; +            } +            // We promise to capture dependencies from both the constructor +            // and the initSingleton() method, so an LLSingleton's instance +            // pointer is on the initializing list during both. Now that we've +            // detected circularity, though, we must distinguish the two. If +            // the recursive call is from the constructor, we CAN'T honor it: +            // otherwise we'd be returning a pointer to a partially- +            // constructed object! But from initSingleton() is okay: that +            // method exists specifically to support circularity. +            // Decide which log helper to call based on initState. They have +            // identical signatures. +            ((initState == CONSTRUCTING)? logerrs : logwarns) +                ("LLSingleton circularity: ", out.str().c_str(), +                 demangle(typeid(*this).name()).c_str(), ""); +        } +        else +        { +            // Here 'this' is NOT already in the 'initializing' stack. Great! +            // Record the dependency. +            // initializing.back() is the LLSingletonBase* currently being +            // initialized. Store 'this' in its mDepends set. +            LLSingletonBase* current(initializing.back()); +            if (current->mDepends.insert(this).second) +            { +                // only log the FIRST time we hit this dependency! +                logdebugs(demangle(typeid(*current).name()).c_str(), +                          " depends on ", demangle(typeid(*this).name()).c_str()); +            } +        } +    } +} + +//static +LLSingletonBase::vec_t LLSingletonBase::dep_sort() +{ +    // While it would theoretically be possible to maintain a static +    // SingletonDeps through the life of the program, dynamically adding and +    // removing LLSingletons as they are created and destroyed, in practice +    // it's less messy to construct it on demand. The overhead of doing so +    // should happen basically twice: once for cleanupAll(), once for +    // deleteAll(). +    typedef LLDependencies<LLSingletonBase*> SingletonDeps; +    SingletonDeps sdeps; +    list_t& master(get_master()); +    BOOST_FOREACH(LLSingletonBase* sp, master) +    { +        // Build the SingletonDeps structure by adding, for each +        // LLSingletonBase* sp in the master list, sp itself. It has no +        // associated value type in our SingletonDeps, hence the 0. We don't +        // record the LLSingletons it must follow; rather, we record the ones +        // it must precede. Copy its mDepends to a KeyList to express that. +        sdeps.add(sp, 0, +                  SingletonDeps::KeyList(), +                  SingletonDeps::KeyList(sp->mDepends.begin(), sp->mDepends.end())); +    } +    vec_t ret; +    ret.reserve(master.size()); +    // We should be able to effect this with a transform_iterator that +    // extracts just the first (key) element from each sorted_iterator, then +    // uses vec_t's range constructor... but frankly this is more +    // straightforward, as long as we remember the above reserve() call! +    BOOST_FOREACH(SingletonDeps::sorted_iterator::value_type pair, sdeps.sort()) +    { +        ret.push_back(pair.first); +    } +    // The master list is not itself pushed onto the master list. Add it as +    // the very last entry -- it is the LLSingleton on which ALL others +    // depend! -- so our caller will process it. +    ret.push_back(MasterList::getInstance()); +    return ret; +} + +//static +void LLSingletonBase::cleanupAll() +{ +    // It's essential to traverse these in dependency order. +    BOOST_FOREACH(LLSingletonBase* sp, dep_sort()) +    { +        // Call cleanupSingleton() only if we haven't already done so for this +        // instance. +        if (! sp->mCleaned) +        { +            sp->mCleaned = true; + +            logdebugs("calling ", +                      demangle(typeid(*sp).name()).c_str(), "::cleanupSingleton()"); +            try +            { +                sp->cleanupSingleton(); +            } +            catch (const std::exception& e) +            { +                logwarns("Exception in ", demangle(typeid(*sp).name()).c_str(), +                         "::cleanupSingleton(): ", e.what()); +            } +            catch (...) +            { +                logwarns("Unknown exception in ", demangle(typeid(*sp).name()).c_str(), +                         "::cleanupSingleton()"); +            } +        } +    } +} + +//static +void LLSingletonBase::deleteAll() +{ +    // It's essential to traverse these in dependency order. +    BOOST_FOREACH(LLSingletonBase* sp, dep_sort()) +    { +        // Capture the class name first: in case of exception, don't count on +        // being able to extract it later. +        const std::string name = demangle(typeid(*sp).name()); +        try +        { +            // Call static method through instance function pointer. +            if (! sp->mDeleteSingleton) +            { +                // This Should Not Happen... but carry on. +                logwarns(name.c_str(), "::mDeleteSingleton not initialized!"); +            } +            else +            { +                // properly initialized: call it. +                logdebugs("calling ", name.c_str(), "::deleteSingleton()"); +                // From this point on, DO NOT DEREFERENCE sp! +                sp->mDeleteSingleton(); +            } +        } +        catch (const std::exception& e) +        { +            logwarns("Exception in ", name.c_str(), "::deleteSingleton(): ", e.what()); +        } +        catch (...) +        { +            logwarns("Unknown exception in ", name.c_str(), "::deleteSingleton()"); +        } +    } +} + +/*------------------------ Final cleanup management ------------------------*/ +class LLSingletonBase::MasterRefcount +{ +public: +    // store a POD int so it will be statically initialized to 0 +    int refcount; +}; +static LLSingletonBase::MasterRefcount sMasterRefcount; + +LLSingletonBase::ref_ptr_t LLSingletonBase::get_master_refcount() +{ +    // Calling this method constructs a new ref_ptr_t, which implicitly calls +    // intrusive_ptr_add_ref(MasterRefcount*). +    return &sMasterRefcount; +} + +void intrusive_ptr_add_ref(LLSingletonBase::MasterRefcount* mrc) +{ +    // Count outstanding SingletonLifetimeManager instances. +    ++mrc->refcount; +} + +void intrusive_ptr_release(LLSingletonBase::MasterRefcount* mrc) +{ +    // Notice when each SingletonLifetimeManager instance is destroyed. +    if (! --mrc->refcount) +    { +        // The last instance was destroyed. Time to kill any remaining +        // LLSingletons -- but in dependency order. +        LLSingletonBase::deleteAll(); +    } +} + +/*---------------------------- Logging helpers -----------------------------*/ +namespace { +bool oktolog() +{ +    // See comments in log() below. +    return sMasterRefcount.refcount && LLError::is_available(); +} + +void log(LLError::ELevel level, +         const char* p1, const char* p2, const char* p3, const char* p4) +{ +    // Check whether we're in the implicit final LLSingletonBase::deleteAll() +    // call. We've carefully arranged for deleteAll() to be called when the +    // last SingletonLifetimeManager instance is destroyed -- in other words, +    // when the last translation unit containing an LLSingleton instance +    // cleans up static data. That could happen after std::cerr is destroyed! +    // The is_available() test below ensures that we'll stop logging once +    // LLError has been cleaned up. If we had a similar portable test for +    // std::cerr, this would be a good place to use it. As we do not, just +    // don't log anything during implicit final deleteAll(). Detect that by +    // the master refcount having gone to zero. +    if (sMasterRefcount.refcount == 0) +        return; + +    // Check LLError::is_available() because some of LLError's infrastructure +    // is itself an LLSingleton. If that LLSingleton has not yet been +    // initialized, trying to log will engage LLSingleton machinery... and +    // around and around we go. +    if (LLError::is_available()) +    { +        LL_VLOGS(level, "LLSingleton") << p1 << p2 << p3 << p4 << LL_ENDL; +    } +    else +    { +        // Caller may be a test program, or something else whose stderr is +        // visible to the user. +        std::cerr << p1 << p2 << p3 << p4 << std::endl; +    } +} + +void logdebugs(const char* p1, const char* p2, const char* p3, const char* p4) +{ +    log(LLError::LEVEL_DEBUG, p1, p2, p3, p4); +} +} // anonymous namespace         + +//static +void LLSingletonBase::logwarns(const char* p1, const char* p2, const char* p3, const char* p4) +{ +    log(LLError::LEVEL_WARN, p1, p2, p3, p4); +} + +//static +void LLSingletonBase::logerrs(const char* p1, const char* p2, const char* p3, const char* p4) +{ +    log(LLError::LEVEL_ERROR, p1, p2, p3, p4); +    // The other important side effect of LL_ERRS() is +    // https://www.youtube.com/watch?v=OMG7paGJqhQ (emphasis on OMG) +    LLError::crashAndLoop(std::string()); +} +std::string LLSingletonBase::demangle(const char* mangled) +{ +    return LLError::Log::demangle(mangled); +} diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 6e6291a165..1b915dfd6e 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -25,188 +25,495 @@  #ifndef LLSINGLETON_H  #define LLSINGLETON_H -#include "llerror.h"	// *TODO: eliminate this - -#include <typeinfo>  #include <boost/noncopyable.hpp> +#include <boost/unordered_set.hpp> +#include <boost/intrusive_ptr.hpp> +#include <list> +#include <vector> +#include <typeinfo> + +class LLSingletonBase: private boost::noncopyable +{ +public: +    class MasterList; +    class MasterRefcount; +    typedef boost::intrusive_ptr<MasterRefcount> ref_ptr_t; + +private: +    // All existing LLSingleton instances are tracked in this master list. +    typedef std::list<LLSingletonBase*> list_t; +    static list_t& get_master(); +    // This, on the other hand, is a stack whose top indicates the LLSingleton +    // currently being initialized. +    static list_t& get_initializing(); +    static list_t& get_initializing_from(MasterList*); +    // Produce a vector<LLSingletonBase*> of master list, in dependency order. +    typedef std::vector<LLSingletonBase*> vec_t; +    static vec_t dep_sort(); + +    bool mCleaned;                  // cleanupSingleton() has been called +    // we directly depend on these other LLSingletons +    typedef boost::unordered_set<LLSingletonBase*> set_t; +    set_t mDepends; + +protected: +    typedef enum e_init_state +    { +        UNINITIALIZED = 0,          // must be default-initialized state +        CONSTRUCTING, +        INITIALIZING, +        INITIALIZED, +        DELETED +    } EInitState; + +    // Define tag<T> to pass to our template constructor. You can't explicitly +    // invoke a template constructor with ordinary template syntax: +    // http://stackoverflow.com/a/3960925/5533635 +    template <typename T> +    struct tag +    { +        typedef T type; +    }; + +    // Base-class constructor should only be invoked by the DERIVED_TYPE +    // constructor, which passes tag<DERIVED_TYPE> for various purposes. +    template <typename DERIVED_TYPE> +    LLSingletonBase(tag<DERIVED_TYPE>); +    virtual ~LLSingletonBase(); + +    // Every new LLSingleton should be added to/removed from the master list +    void add_master(); +    void remove_master(); +    // with a little help from our friends. +    template <class T> friend struct LLSingleton_manage_master; + +    // Maintain a stack of the LLSingleton subclass instance currently being +    // initialized. We use this to notice direct dependencies: we want to know +    // if A requires B. We deduce a dependency if while initializing A, +    // control reaches B::getInstance(). +    // We want &A to be at the top of that stack during both A::A() and +    // A::initSingleton(), since a call to B::getInstance() might occur during +    // either. +    // Unfortunately the desired timespan does not correspond neatly with a +    // single C++ scope, else we'd use RAII to track it. But we do know that +    // LLSingletonBase's constructor definitely runs just before +    // LLSingleton's, which runs just before the specific subclass's. +    void push_initializing(const char*); +    // LLSingleton is, and must remain, the only caller to initSingleton(). +    // That being the case, we control exactly when it happens -- and we can +    // pop the stack immediately thereafter. +    void pop_initializing(); +private: +    // logging +    static void log_initializing(const char* verb, const char* name); +protected: +    // If a given call to B::getInstance() happens during either A::A() or +    // A::initSingleton(), record that A directly depends on B. +    void capture_dependency(list_t& initializing, EInitState); + +    // delegate LL_ERRS() logging to llsingleton.cpp +    static void logerrs(const char* p1, const char* p2="", +                        const char* p3="", const char* p4=""); +    // delegate LL_WARNS() logging to llsingleton.cpp +    static void logwarns(const char* p1, const char* p2="", +                         const char* p3="", const char* p4=""); +    static std::string demangle(const char* mangled); + +    // obtain canonical ref_ptr_t +    static ref_ptr_t get_master_refcount(); + +    // Default methods in case subclass doesn't declare them. +    virtual void initSingleton() {} +    virtual void cleanupSingleton() {} + +    // deleteSingleton() isn't -- and shouldn't be -- a virtual method. It's a +    // class static. However, given only Foo*, deleteAll() does need to be +    // able to reach Foo::deleteSingleton(). Make LLSingleton (which declares +    // deleteSingleton()) store a pointer here. Since we know it's a static +    // class method, a classic-C function pointer will do. +    void (*mDeleteSingleton)(); + +public: +    /** +     * Call this to call the cleanupSingleton() method for every LLSingleton +     * constructed since the start of the last cleanupAll() call. (Any +     * LLSingleton constructed DURING a cleanupAll() call won't be cleaned up +     * until the next cleanupAll() call.) cleanupSingleton() neither deletes +     * nor destroys its LLSingleton; therefore it's safe to include logic that +     * might take significant realtime or even throw an exception. +     * +     * The most important property of cleanupAll() is that cleanupSingleton() +     * methods are called in dependency order, leaf classes last. Thus, given +     * two LLSingleton subclasses A and B, if A's dependency on B is properly +     * expressed as a B::getInstance() or B::instance() call during either +     * A::A() or A::initSingleton(), B will be cleaned up after A. +     * +     * If a cleanupSingleton() method throws an exception, the exception is +     * logged, but cleanupAll() attempts to continue calling the rest of the +     * cleanupSingleton() methods. +     */ +    static void cleanupAll(); +    /** +     * Call this to call the deleteSingleton() method for every LLSingleton +     * constructed since the start of the last deleteAll() call. (Any +     * LLSingleton constructed DURING a deleteAll() call won't be cleaned up +     * until the next deleteAll() call.) deleteSingleton() deletes and +     * destroys its LLSingleton. Any cleanup logic that might take significant +     * realtime -- or throw an exception -- must not be placed in your +     * LLSingleton's destructor, but rather in its cleanupSingleton() method. +     * +     * The most important property of deleteAll() is that deleteSingleton() +     * methods are called in dependency order, leaf classes last. Thus, given +     * two LLSingleton subclasses A and B, if A's dependency on B is properly +     * expressed as a B::getInstance() or B::instance() call during either +     * A::A() or A::initSingleton(), B will be cleaned up after A. +     * +     * If a deleteSingleton() method throws an exception, the exception is +     * logged, but deleteAll() attempts to continue calling the rest of the +     * deleteSingleton() methods. +     */ +    static void deleteAll(); +}; + +// support ref_ptr_t +void intrusive_ptr_add_ref(LLSingletonBase::MasterRefcount*); +void intrusive_ptr_release(LLSingletonBase::MasterRefcount*); -// LLSingleton implements the getInstance() method part of the Singleton -// pattern. It can't make the derived class constructors protected, though, so -// you have to do that yourself. -// -// There are two ways to use LLSingleton. The first way is to inherit from it -// while using the typename that you'd like to be static as the template -// parameter, like so: -// -//   class Foo: public LLSingleton<Foo>{}; -// -//   Foo& instance = Foo::instance(); -// -// The second way is to use the singleton class directly, without inheritance: -// -//   typedef LLSingleton<Foo> FooSingleton; -// -//   Foo& instance = FooSingleton::instance(); -// -// In this case, the class being managed as a singleton needs to provide an -// initSingleton() method since the LLSingleton virtual method won't be -// available -// -// As currently written, it is not thread-safe. +// Most of the time, we want LLSingleton_manage_master() to forward its +// methods to real LLSingletonBase methods. +template <class T> +struct LLSingleton_manage_master +{ +    void add(LLSingletonBase* sb) { sb->add_master(); } +    void remove(LLSingletonBase* sb) { sb->remove_master(); } +    void push_initializing(LLSingletonBase* sb) { sb->push_initializing(typeid(T).name()); } +    void pop_initializing (LLSingletonBase* sb) { sb->pop_initializing(); } +    LLSingletonBase::list_t& get_initializing(T*) { return LLSingletonBase::get_initializing(); } +}; +// But for the specific case of LLSingletonBase::MasterList, don't. +template <> +struct LLSingleton_manage_master<LLSingletonBase::MasterList> +{ +    void add(LLSingletonBase*) {} +    void remove(LLSingletonBase*) {} +    void push_initializing(LLSingletonBase*) {} +    void pop_initializing (LLSingletonBase*) {} +    LLSingletonBase::list_t& get_initializing(LLSingletonBase::MasterList* instance) +    { +        return LLSingletonBase::get_initializing_from(instance); +    } +}; + +// Now we can implement LLSingletonBase's template constructor.  template <typename DERIVED_TYPE> -class LLSingleton : private boost::noncopyable +LLSingletonBase::LLSingletonBase(tag<DERIVED_TYPE>): +    mCleaned(false), +    mDeleteSingleton(NULL) +{ +    // Make this the currently-initializing LLSingleton. +    LLSingleton_manage_master<DERIVED_TYPE>().push_initializing(this); +} + +/** + * LLSingleton implements the getInstance() method part of the Singleton + * pattern. It can't make the derived class constructors protected, though, so + * you have to do that yourself. + * + * Derive your class from LLSingleton, passing your subclass name as + * LLSingleton's template parameter, like so: + * + *   class Foo: public LLSingleton<Foo> + *   { + *       // use this macro at start of every LLSingleton subclass + *       LLSINGLETON(Foo); + *   public: + *       // ... + *   }; + * + *   Foo& instance = Foo::instance(); + * + * LLSingleton recognizes a couple special methods in your derived class. + * + * If you override LLSingleton<T>::initSingleton(), your method will be called + * immediately after the instance is constructed. This is useful for breaking + * circular dependencies: if you find that your LLSingleton subclass + * constructor references other LLSingleton subclass instances in a chain + * leading back to yours, move the instance reference from your constructor to + * your initSingleton() method. + * + * If you override LLSingleton<T>::cleanupSingleton(), your method will be + * called if someone calls LLSingletonBase::cleanupAll(). The significant part + * of this promise is that cleanupAll() will call individual + * cleanupSingleton() methods in reverse dependency order. + * + * That is, consider LLSingleton subclasses C, B and A. A depends on B, which + * in turn depends on C. These dependencies are expressed as calls to + * B::instance() or B::getInstance(), and C::instance() or C::getInstance(). + * It shouldn't matter whether these calls appear in A::A() or + * A::initSingleton(), likewise B::B() or B::initSingleton(). + * + * We promise that if you later call LLSingletonBase::cleanupAll(): + * 1. A::cleanupSingleton() will be called before + * 2. B::cleanupSingleton(), which will be called before + * 3. C::cleanupSingleton(). + * Put differently, if your LLSingleton subclass constructor or + * initSingleton() method explicitly depends on some other LLSingleton + * subclass, you may continue to rely on that other subclass in your + * cleanupSingleton() method. + * + * We introduce a special cleanupSingleton() method because cleanupSingleton() + * operations can involve nontrivial realtime, or might throw an exception. A + * destructor should do neither! + * + * If your cleanupSingleton() method throws an exception, we log that + * exception but proceed with the remaining cleanupSingleton() calls. + * + * Similarly, if at some point you call LLSingletonBase::deleteAll(), all + * remaining LLSingleton instances will be destroyed in dependency order. (Or + * call MySubclass::deleteSingleton() to specifically destroy the canonical + * MySubclass instance.) + * + * As currently written, LLSingleton is not thread-safe. + */ +template <typename DERIVED_TYPE> +class LLSingleton : public LLSingletonBase  { -	  private: -	typedef enum e_init_state -	{ -		UNINITIALIZED, -		CONSTRUCTING, -		INITIALIZING, -		INITIALIZED, -		DELETED -	} EInitState; -          static DERIVED_TYPE* constructSingleton()      {          return new DERIVED_TYPE();      } -	 -	// stores pointer to singleton instance -	struct SingletonLifetimeManager -	{ -		SingletonLifetimeManager() -		{ -			construct(); -		} - -		static void construct() -		{ -			sData.mInitState = CONSTRUCTING; -			sData.mInstance = constructSingleton(); -			sData.mInitState = INITIALIZING; -		} - -		~SingletonLifetimeManager() -		{ -			if (sData.mInitState != DELETED) -			{ -				deleteSingleton(); -			} -		} -	}; -	 + +    // 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 +    { +        SingletonLifetimeManager(): +            mMasterRefcount(LLSingletonBase::get_master_refcount()) +        { +            construct(); +        } + +        static void construct() +        { +            sData.mInitState = CONSTRUCTING; +            sData.mInstance = constructSingleton(); +            sData.mInitState = INITIALIZING; +        } + +        ~SingletonLifetimeManager() +        { +            // The dependencies between LLSingletons, and the arbitrary order +            // of static-object destruction, mean that we DO NOT WANT this +            // destructor to delete this LLSingleton. This destructor will run +            // without regard to any other LLSingleton whose cleanup might +            // depend on its existence. What we really want is to count the +            // runtime's attempts to cleanup LLSingleton static data -- and on +            // the very last one, call LLSingletonBase::deleteAll(). That +            // method will properly honor cross-LLSingleton dependencies. This +            // is why we store an intrusive_ptr to a MasterRefcount: our +            // ref_ptr_t member counts SingletonLifetimeManager instances. +            // Once the runtime destroys the last of these, THEN we can delete +            // every remaining LLSingleton. +        } + +        LLSingletonBase::ref_ptr_t mMasterRefcount; +    }; + +protected: +    // Pass DERIVED_TYPE explicitly to LLSingletonBase's constructor because, +    // until our subclass constructor completes, *this isn't yet a +    // full-fledged DERIVED_TYPE. +    LLSingleton(): LLSingletonBase(LLSingletonBase::tag<DERIVED_TYPE>()) +    { +        // populate base-class function pointer with the static +        // deleteSingleton() function for this particular specialization +        mDeleteSingleton = &deleteSingleton; + +        // add this new instance to the master list +        LLSingleton_manage_master<DERIVED_TYPE>().add(this); +    } +  public: -	virtual ~LLSingleton() -	{ -		sData.mInstance = NULL; -		sData.mInitState = DELETED; -	} - -	/** -	 * @brief Immediately delete the singleton. -	 * -	 * A subsequent call to LLProxy::getInstance() will construct a new -	 * instance of the class. -	 * -	 * LLSingletons are normally destroyed after main() has exited and the C++ -	 * runtime is cleaning up statically-constructed objects. Some classes -	 * derived from LLSingleton have objects that are part of a runtime system -	 * that is terminated before main() exits. Calling the destructor of those -	 * objects after the termination of their respective systems can cause -	 * crashes and other problems during termination of the project. Using this -	 * method to destroy the singleton early can prevent these crashes. -	 * -	 * An example where this is needed is for a LLSingleton that has an APR -	 * object as a member that makes APR calls on destruction. The APR system is -	 * shut down explicitly before main() exits. This causes a crash on exit. -	 * Using this method before the call to apr_terminate() and NOT calling -	 * getInstance() again will prevent the crash. -	 */ -	static void deleteSingleton() -	{ -		delete sData.mInstance; -		sData.mInstance = NULL; -		sData.mInitState = DELETED; -	} - - -	static DERIVED_TYPE* getInstance() -	{ -		static SingletonLifetimeManager sLifeTimeMgr; - -		switch (sData.mInitState) -		{ -		case UNINITIALIZED: -			// should never be uninitialized at this point -			llassert(false); -			return NULL; -		case CONSTRUCTING: -			LL_ERRS() << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << LL_ENDL; -			return NULL; -		case INITIALIZING: -			// go ahead and flag ourselves as initialized so we can be reentrant during initialization -			sData.mInitState = INITIALIZED;	 -			// initialize singleton after constructing it so that it can reference other singletons which in turn depend on it, -			// thus breaking cyclic dependencies -			sData.mInstance->initSingleton();  -			return sData.mInstance; -		case INITIALIZED: -			return sData.mInstance; -		case DELETED: -			LL_WARNS() << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << LL_ENDL; -			SingletonLifetimeManager::construct(); -			// same as first time construction -			sData.mInitState = INITIALIZED;	 -			sData.mInstance->initSingleton();  -			return sData.mInstance; -		} - -		return NULL; -	} - -	static DERIVED_TYPE* getIfExists() -	{ -		return sData.mInstance; -	} - -	// Reference version of getInstance() -	// Preferred over getInstance() as it disallows checking for NULL -	static DERIVED_TYPE& instance() -	{ -		return *getInstance(); -	} -	 -	// Has this singleton been created uet? -	// Use this to avoid accessing singletons before the can safely be constructed -	static bool instanceExists() -	{ -		return sData.mInitState == INITIALIZED; -	} -	 -	// Has this singleton already been deleted? -	// Use this to avoid accessing singletons from a static object's destructor -	static bool destroyed() -	{ -		return sData.mInitState == DELETED; -	} +    virtual ~LLSingleton() +    { +        // remove this instance from the master list +        LLSingleton_manage_master<DERIVED_TYPE>().remove(this); +        sData.mInstance = NULL; +        sData.mInitState = DELETED; +    } -private: +    /** +     * @brief Immediately delete the singleton. +     * +     * A subsequent call to LLProxy::getInstance() will construct a new +     * instance of the class. +     * +     * Without an explicit call to LLSingletonBase::deleteAll(), LLSingletons +     * are implicitly destroyed after main() has exited and the C++ runtime is +     * cleaning up statically-constructed objects. Some classes derived from +     * LLSingleton have objects that are part of a runtime system that is +     * terminated before main() exits. Calling the destructor of those objects +     * after the termination of their respective systems can cause crashes and +     * other problems during termination of the project. Using this method to +     * destroy the singleton early can prevent these crashes. +     * +     * An example where this is needed is for a LLSingleton that has an APR +     * object as a member that makes APR calls on destruction. The APR system is +     * shut down explicitly before main() exits. This causes a crash on exit. +     * Using this method before the call to apr_terminate() and NOT calling +     * getInstance() again will prevent the crash. +     */ +    static void deleteSingleton() +    { +        delete sData.mInstance; +        sData.mInstance = NULL; +        sData.mInitState = DELETED; +    } + +    static DERIVED_TYPE* getInstance() +    { +        static SingletonLifetimeManager sLifeTimeMgr; -	virtual void initSingleton() {} +        switch (sData.mInitState) +        { +        case UNINITIALIZED: +            // should never be uninitialized at this point +            logerrs("Uninitialized singleton ", +                    demangle(typeid(DERIVED_TYPE).name()).c_str()); +            return NULL; -	struct SingletonData -	{ -		// explicitly has a default constructor so that member variables are zero initialized in BSS -		// and only changed by singleton logic, not constructor running during startup -		EInitState		mInitState; -		DERIVED_TYPE*	mInstance; -	}; -	static SingletonData sData; +        case CONSTRUCTING: +            logerrs("Tried to access singleton ", +                    demangle(typeid(DERIVED_TYPE).name()).c_str(), +                    " from singleton constructor!"); +            return NULL; + +        case INITIALIZING: +            // go ahead and flag ourselves as initialized so we can be +            // reentrant during initialization +            sData.mInitState = INITIALIZED;  +            // initialize singleton after constructing it so that it can +            // reference other singletons which in turn depend on it, thus +            // breaking cyclic dependencies +            sData.mInstance->initSingleton(); +            // pop this off stack of initializing singletons +            LLSingleton_manage_master<DERIVED_TYPE>().pop_initializing(sData.mInstance); +            break; + +        case INITIALIZED: +            break; + +        case DELETED: +            logwarns("Trying to access deleted singleton ", +                     demangle(typeid(DERIVED_TYPE).name()).c_str(), +                     " -- creating new instance"); +            SingletonLifetimeManager::construct(); +            // same as first time construction +            sData.mInitState = INITIALIZED;  +            sData.mInstance->initSingleton();  +            // pop this off stack of initializing singletons +            LLSingleton_manage_master<DERIVED_TYPE>().pop_initializing(sData.mInstance); +            break; +        } + +        // By this point, if DERIVED_TYPE was pushed onto the initializing +        // stack, it has been popped off. So the top of that stack, if any, is +        // an LLSingleton that directly depends on DERIVED_TYPE. If this call +        // came from another LLSingleton, rather than from vanilla application +        // code, record the dependency. +        sData.mInstance->capture_dependency( +            LLSingleton_manage_master<DERIVED_TYPE>().get_initializing(sData.mInstance), +            sData.mInitState); +        return sData.mInstance; +    } + +    // Reference version of getInstance() +    // Preferred over getInstance() as it disallows checking for NULL +    static DERIVED_TYPE& instance() +    { +        return *getInstance(); +    } + +    // Has this singleton been created yet? +    // Use this to avoid accessing singletons before they can safely be constructed. +    static bool instanceExists() +    { +        return sData.mInitState == INITIALIZED; +    } + +private: +    struct SingletonData +    { +        // explicitly has a default constructor so that member variables are zero initialized in BSS +        // and only changed by singleton logic, not constructor running during startup +        EInitState      mInitState; +        DERIVED_TYPE*   mInstance; +    }; +    static SingletonData sData;  };  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/llheteromap_test.cpp b/indra/llcommon/tests/llheteromap_test.cpp new file mode 100644 index 0000000000..686bffb878 --- /dev/null +++ b/indra/llcommon/tests/llheteromap_test.cpp @@ -0,0 +1,163 @@ +/** + * @file   llheteromap_test.cpp + * @author Nat Goodspeed + * @date   2016-10-12 + * @brief  Test for llheteromap. + *  + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llheteromap.h" +// STL headers +#include <set> +// std headers +// external library headers + +// (pacify clang) +std::ostream& operator<<(std::ostream& out, const std::set<std::string>& strset); +// other Linden headers +#include "../test/lltut.h" + +static std::string clog; +static std::set<std::string> dlog; + +// want to be able to use ensure_equals() on a set<string> +std::ostream& operator<<(std::ostream& out, const std::set<std::string>& strset) +{ +    out << '{'; +    const char* delim = ""; +    for (std::set<std::string>::const_iterator si(strset.begin()), se(strset.end()); +         si != se; ++si) +    { +        out << delim << '"' << *si << '"'; +        delim = ", "; +    } +    out << '}'; +    return out; +} + +// unrelated test classes +struct Chalk +{ +    int dummy; +    std::string name; + +    Chalk(): +        dummy(0) +    { +        clog.append("a"); +    } + +    ~Chalk() +    { +        dlog.insert("a"); +    } + +private: +    Chalk(const Chalk&);            // no implementation +}; + +struct Cheese +{ +    std::string name; + +    Cheese() +    { +        clog.append("e"); +    } + +    ~Cheese() +    { +        dlog.insert("e"); +    } + +private: +    Cheese(const Cheese&);          // no implementation +}; + +struct Chowdah +{ +    char displace[17]; +    std::string name; + +    Chowdah() +    { +        displace[0] = '\0'; +        clog.append("o"); +    } + +    ~Chowdah() +    { +        dlog.insert("o"); +    } + +private: +    Chowdah(const Chowdah&);        // no implementation +}; + +/***************************************************************************** +*   TUT +*****************************************************************************/ +namespace tut +{ +    struct llheteromap_data +    { +        llheteromap_data() +        { +            clog.erase(); +            dlog.clear(); +        } +    }; +    typedef test_group<llheteromap_data> llheteromap_group; +    typedef llheteromap_group::object object; +    llheteromap_group llheteromapgrp("llheteromap"); + +    template<> template<> +    void object::test<1>() +    { +        set_test_name("create, get, delete"); + +        { +            LLHeteroMap map; + +            { +                // create each instance +                Chalk& chalk = map.obtain<Chalk>(); +                chalk.name = "Chalk"; + +                Cheese& cheese = map.obtain<Cheese>(); +                cheese.name = "Cheese"; + +                Chowdah& chowdah = map.obtain<Chowdah>(); +                chowdah.name = "Chowdah"; +            } // refs go out of scope + +            { +                // verify each instance +                Chalk& chalk = map.obtain<Chalk>(); +                ensure_equals(chalk.name, "Chalk"); + +                Cheese& cheese = map.obtain<Cheese>(); +                ensure_equals(cheese.name, "Cheese"); + +                Chowdah& chowdah = map.obtain<Chowdah>(); +                ensure_equals(chowdah.name, "Chowdah"); +            } +        } // destroy map + +        // Chalk, Cheese and Chowdah should have been created in specific order +        ensure_equals(clog, "aeo"); + +        // We don't care what order they're destroyed in, as long as each is +        // appropriately destroyed. +        std::set<std::string> dtorset; +        for (const char* cp = "aeo"; *cp; ++cp) +            dtorset.insert(std::string(1, *cp)); +        ensure_equals(dlog, dtorset); +    } +} // namespace tut diff --git a/indra/llcommon/tests/llpounceable_test.cpp b/indra/llcommon/tests/llpounceable_test.cpp new file mode 100644 index 0000000000..2f4915ce11 --- /dev/null +++ b/indra/llcommon/tests/llpounceable_test.cpp @@ -0,0 +1,230 @@ +/** + * @file   llpounceable_test.cpp + * @author Nat Goodspeed + * @date   2015-05-22 + * @brief  Test for llpounceable. + *  + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Copyright (c) 2015, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llpounceable.h" +// STL headers +// std headers +// external library headers +#include <boost/bind.hpp> +// other Linden headers +#include "../test/lltut.h" + +/*----------------------------- string testing -----------------------------*/ +void append(std::string* dest, const std::string& src) +{ +    dest->append(src); +} + +/*-------------------------- Data-struct testing ---------------------------*/ +struct Data +{ +    Data(const std::string& data): +        mData(data) +    {} +    const std::string mData; +}; + +void setter(Data** dest, Data* ptr) +{ +    *dest = ptr; +} + +static Data* static_check = 0; + +// Set up an extern pointer to an LLPounceableStatic so the linker will fill +// in the forward reference from below, before runtime. +extern LLPounceable<Data*, LLPounceableStatic> gForward; + +struct EnqueueCall +{ +    EnqueueCall() +    { +        // Intentionally use a forward reference to an LLPounceableStatic that +        // we believe is NOT YET CONSTRUCTED. This models the scenario in +        // which a constructor in another translation unit runs before +        // constructors in this one. We very specifically want callWhenReady() +        // to work even in that case: we need the LLPounceableQueueImpl to be +        // initialized even if the LLPounceable itself is not. +        gForward.callWhenReady(boost::bind(setter, &static_check, _1)); +    } +} nqcall; +// When this declaration is processed, we should enqueue the +// setter(&static_check, _1) call for when gForward is set non-NULL. Needless +// to remark, we want this call not to crash. + +// Now declare gForward. Its constructor should not run until after nqcall's. +LLPounceable<Data*, LLPounceableStatic> gForward; + +/***************************************************************************** +*   TUT +*****************************************************************************/ +namespace tut +{ +    struct llpounceable_data +    { +    }; +    typedef test_group<llpounceable_data> llpounceable_group; +    typedef llpounceable_group::object object; +    llpounceable_group llpounceablegrp("llpounceable"); + +    template<> template<> +    void object::test<1>() +    { +        set_test_name("LLPounceableStatic out-of-order test"); +        // LLPounceable<T, LLPounceableStatic>::callWhenReady() must work even +        // before LLPounceable's constructor runs. That's the whole point of +        // implementing it with an LLSingleton queue. This models (say) +        // LLPounceableStatic<LLMessageSystem*, LLPounceableStatic>. +        ensure("static_check should still be null", ! static_check); +        Data myData("test<1>"); +        gForward = &myData;         // should run setter +        ensure_equals("static_check should be &myData", static_check, &myData); +    } + +    template<> template<> +    void object::test<2>() +    { +        set_test_name("LLPounceableQueue different queues"); +        // We expect that LLPounceable<T, LLPounceableQueue> should have +        // different queues because that specialization stores the queue +        // directly in the LLPounceable instance. +        Data *aptr = 0, *bptr = 0; +        LLPounceable<Data*> a, b; +        a.callWhenReady(boost::bind(setter, &aptr, _1)); +        b.callWhenReady(boost::bind(setter, &bptr, _1)); +        ensure("aptr should be null", ! aptr); +        ensure("bptr should be null", ! bptr); +        Data adata("a"), bdata("b"); +        a = &adata; +        ensure_equals("aptr should be &adata", aptr, &adata); +        // but we haven't yet set b +        ensure("bptr should still be null", !bptr); +        b = &bdata; +        ensure_equals("bptr should be &bdata", bptr, &bdata); +    } + +    template<> template<> +    void object::test<3>() +    { +        set_test_name("LLPounceableStatic different queues"); +        // LLPounceable<T, LLPounceableStatic> should also have a distinct +        // queue for each instance, but that engages an additional map lookup +        // because there's only one LLSingleton for each T. +        Data *aptr = 0, *bptr = 0; +        LLPounceable<Data*, LLPounceableStatic> a, b; +        a.callWhenReady(boost::bind(setter, &aptr, _1)); +        b.callWhenReady(boost::bind(setter, &bptr, _1)); +        ensure("aptr should be null", ! aptr); +        ensure("bptr should be null", ! bptr); +        Data adata("a"), bdata("b"); +        a = &adata; +        ensure_equals("aptr should be &adata", aptr, &adata); +        // but we haven't yet set b +        ensure("bptr should still be null", !bptr); +        b = &bdata; +        ensure_equals("bptr should be &bdata", bptr, &bdata); +    } + +    template<> template<> +    void object::test<4>() +    { +        set_test_name("LLPounceable<T> looks like T"); +        // We want LLPounceable<T, TAG> to be drop-in replaceable for a plain +        // T for read constructs. In particular, it should behave like a dumb +        // pointer -- and with zero abstraction cost for such usage. +        Data* aptr = 0; +        Data a("a"); +        // should be able to initialize a pounceable (when its constructor +        // runs) +        LLPounceable<Data*> pounceable(&a); +        // should be able to pass LLPounceable<T> to function accepting T +        setter(&aptr, pounceable); +        ensure_equals("aptr should be &a", aptr, &a); +        // should be able to dereference with * +        ensure_equals("deref with *", (*pounceable).mData, "a"); +        // should be able to dereference with -> +        ensure_equals("deref with ->", pounceable->mData, "a"); +        // bool operations +        ensure("test with operator bool()", pounceable); +        ensure("test with operator !()", ! (! pounceable)); +    } + +    template<> template<> +    void object::test<5>() +    { +        set_test_name("Multiple callWhenReady() queue items"); +        Data *p1 = 0, *p2 = 0, *p3 = 0; +        Data a("a"); +        LLPounceable<Data*> pounceable; +        // queue up a couple setter() calls for later +        pounceable.callWhenReady(boost::bind(setter, &p1, _1)); +        pounceable.callWhenReady(boost::bind(setter, &p2, _1)); +        // should still be pending +        ensure("p1 should be null", !p1); +        ensure("p2 should be null", !p2); +        ensure("p3 should be null", !p3); +        pounceable = 0; +        // assigning a new empty value shouldn't flush the queue +        ensure("p1 should still be null", !p1); +        ensure("p2 should still be null", !p2); +        ensure("p3 should still be null", !p3); +        // using whichever syntax +        pounceable.reset(0); +        // try to make ensure messages distinct... tough to pin down which +        // ensure() failed if multiple ensure() calls in the same test<n> have +        // the same message! +        ensure("p1 should again be null", !p1); +        ensure("p2 should again be null", !p2); +        ensure("p3 should again be null", !p3); +        pounceable.reset(&a);       // should flush queue +        ensure_equals("p1 should be &a", p1, &a); +        ensure_equals("p2 should be &a", p2, &a); +        ensure("p3 still not set", !p3); +        // immediate call +        pounceable.callWhenReady(boost::bind(setter, &p3, _1)); +        ensure_equals("p3 should be &a", p3, &a); +    } + +    template<> template<> +    void object::test<6>() +    { +        set_test_name("queue order"); +        std::string data; +        LLPounceable<std::string*> pounceable; +        pounceable.callWhenReady(boost::bind(append, _1, "a")); +        pounceable.callWhenReady(boost::bind(append, _1, "b")); +        pounceable.callWhenReady(boost::bind(append, _1, "c")); +        pounceable = &data; +        ensure_equals("callWhenReady() must preserve chronological order", +                      data, "abc"); + +        std::string data2; +        pounceable = NULL; +        pounceable.callWhenReady(boost::bind(append, _1, "d")); +        pounceable.callWhenReady(boost::bind(append, _1, "e")); +        pounceable.callWhenReady(boost::bind(append, _1, "f")); +        pounceable = &data2; +        ensure_equals("LLPounceable must reset queue when fired", +                      data2, "def"); +    } + +    template<> template<> +    void object::test<7>() +    { +        set_test_name("compile-fail test, uncomment to check"); +        // The following declaration should fail: only LLPounceableQueue and +        // LLPounceableStatic should work as tags. +//      LLPounceable<Data*, int> pounceable; +    } +} // namespace tut diff --git a/indra/llcommon/tests/llsingleton_test.cpp b/indra/llcommon/tests/llsingleton_test.cpp index 385289aefe..56886bc73f 100644 --- a/indra/llcommon/tests/llsingleton_test.cpp +++ b/indra/llcommon/tests/llsingleton_test.cpp @@ -30,47 +30,172 @@  #include "llsingleton.h"  #include "../test/lltut.h" + +// Capture execution sequence by appending to log string. +std::string sLog; + +#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;                                     \ +                                                    \ +    void initSingleton();                           \ +    void cleanupSingleton();                        \ +};                                                  \ +                                                    \ +CLS::dep_flag CLS::sDepFlag = DEP_NONE + +DECLARE_CLASS(A); +DECLARE_CLASS(B); + +#define DEFINE_MEMBERS(CLS, OTHER)              \ +CLS::CLS()                                      \ +{                                               \ +    sLog.append(#CLS);                          \ +    if (sDepFlag == DEP_CTOR)                   \ +    {                                           \ +        (void)OTHER::instance();                \ +    }                                           \ +}                                               \ +                                                \ +void CLS::initSingleton()                       \ +{                                               \ +    sLog.append("i" #CLS);                      \ +    if (sDepFlag == DEP_INIT)                   \ +    {                                           \ +        (void)OTHER::instance();                \ +    }                                           \ +}                                               \ +                                                \ +void CLS::cleanupSingleton()                    \ +{                                               \ +    sLog.append("x" #CLS);                      \ +}                                               \ +                                                \ +CLS::~CLS()                                     \ +{                                               \ +    sLog.append("~" #CLS);                      \ +} + +DEFINE_MEMBERS(A, B) +DEFINE_MEMBERS(B, A) +  namespace tut  { -	struct singleton -	{ -		// We need a class created with the LLSingleton template to test with. -		class LLSingletonTest: public LLSingleton<LLSingletonTest> -		{ - -		}; -	}; - -	typedef test_group<singleton> singleton_t; -	typedef singleton_t::object singleton_object_t; -	tut::singleton_t tut_singleton("LLSingleton"); - -	template<> template<> -	void singleton_object_t::test<1>() -	{ - -	} -	template<> template<> -	void singleton_object_t::test<2>() -	{ -		LLSingletonTest* singleton_test = LLSingletonTest::getInstance(); -		ensure(singleton_test); -	} -	template<> template<> -	void singleton_object_t::test<3>() -	{ -		//Construct the instance -		LLSingletonTest::getInstance(); -		ensure(LLSingletonTest::instanceExists()); - -		//Delete the instance -		LLSingletonTest::deleteSingleton(); -		ensure(LLSingletonTest::destroyed()); -		ensure(!LLSingletonTest::instanceExists()); - -		//Construct it again. -		LLSingletonTest* singleton_test = LLSingletonTest::getInstance(); -		ensure(singleton_test); -		ensure(LLSingletonTest::instanceExists()); -	} +    struct singleton +    { +        // We need a class created with the LLSingleton template to test with. +        class LLSingletonTest: public LLSingleton<LLSingletonTest> +        { +            LLSINGLETON_EMPTY_CTOR(LLSingletonTest); +        }; +    }; + +    typedef test_group<singleton> singleton_t; +    typedef singleton_t::object singleton_object_t; +    tut::singleton_t tut_singleton("LLSingleton"); + +    template<> template<> +    void singleton_object_t::test<1>() +    { + +    } +    template<> template<> +    void singleton_object_t::test<2>() +    { +        LLSingletonTest* singleton_test = LLSingletonTest::getInstance(); +        ensure(singleton_test); +    } + +    template<> template<> +    void singleton_object_t::test<3>() +    { +        //Construct the instance +        LLSingletonTest::getInstance(); +        ensure(LLSingletonTest::instanceExists()); + +        //Delete the instance +        LLSingletonTest::deleteSingleton(); +        ensure(!LLSingletonTest::instanceExists()); + +        //Construct it again. +        LLSingletonTest* singleton_test = LLSingletonTest::getInstance(); +        ensure(singleton_test); +        ensure(LLSingletonTest::instanceExists()); +    } + +#define TESTS(CLS, OTHER, N0, N1, N2, N3)                               \ +    template<> template<>                                               \ +    void singleton_object_t::test<N0>()                                 \ +    {                                                                   \ +        set_test_name("just " #CLS);                                    \ +        CLS::sDepFlag = CLS::DEP_NONE;                                  \ +        OTHER::sDepFlag = OTHER::DEP_NONE;                              \ +        sLog.clear();                                                   \ +                                                                        \ +        (void)CLS::instance();                                          \ +        ensure_equals(sLog, #CLS "i" #CLS);                             \ +        LLSingletonBase::cleanupAll();                                  \ +        ensure_equals(sLog, #CLS "i" #CLS "x" #CLS);                    \ +        LLSingletonBase::deleteAll();                                   \ +        ensure_equals(sLog, #CLS "i" #CLS "x" #CLS "~" #CLS);           \ +    }                                                                   \ +                                                                        \ +    template<> template<>                                               \ +    void singleton_object_t::test<N1>()                                 \ +    {                                                                   \ +        set_test_name(#CLS " ctor depends " #OTHER);                    \ +        CLS::sDepFlag = CLS::DEP_CTOR;                                  \ +        OTHER::sDepFlag = OTHER::DEP_NONE;                              \ +        sLog.clear();                                                   \ +                                                                        \ +        (void)CLS::instance();                                          \ +        ensure_equals(sLog, #CLS #OTHER "i" #OTHER "i" #CLS);           \ +        LLSingletonBase::cleanupAll();                                  \ +        ensure_equals(sLog, #CLS #OTHER "i" #OTHER "i" #CLS "x" #CLS "x" #OTHER); \ +        LLSingletonBase::deleteAll();                                   \ +        ensure_equals(sLog, #CLS #OTHER "i" #OTHER "i" #CLS "x" #CLS "x" #OTHER "~" #CLS "~" #OTHER); \ +    }                                                                   \ +                                                                        \ +    template<> template<>                                               \ +    void singleton_object_t::test<N2>()                                 \ +    {                                                                   \ +        set_test_name(#CLS " init depends " #OTHER);                    \ +        CLS::sDepFlag = CLS::DEP_INIT;                                  \ +        OTHER::sDepFlag = OTHER::DEP_NONE;                              \ +        sLog.clear();                                                   \ +                                                                        \ +        (void)CLS::instance();                                          \ +        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER);           \ +        LLSingletonBase::cleanupAll();                                  \ +        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER); \ +        LLSingletonBase::deleteAll();                                   \ +        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER "~" #CLS "~" #OTHER); \ +    }                                                                   \ +                                                                        \ +    template<> template<>                                               \ +    void singleton_object_t::test<N3>()                                 \ +    {                                                                   \ +        set_test_name(#CLS " circular init");                           \ +        CLS::sDepFlag = CLS::DEP_INIT;                                  \ +        OTHER::sDepFlag = OTHER::DEP_CTOR;                              \ +        sLog.clear();                                                   \ +                                                                        \ +        (void)CLS::instance();                                          \ +        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER);           \ +        LLSingletonBase::cleanupAll();                                  \ +        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER); \ +        LLSingletonBase::deleteAll();                                   \ +        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER "~" #CLS "~" #OTHER); \ +    } + +    TESTS(A, B, 4, 5, 6, 7) +    TESTS(B, A, 8, 9, 10, 11)  } diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt index 0bb0348d26..b03ee6eeda 100644 --- a/indra/llcorehttp/CMakeLists.txt +++ b/indra/llcorehttp/CMakeLists.txt @@ -93,6 +93,7 @@ target_link_libraries(    ${OPENSSL_LIBRARIES}    ${CRYPTO_LIBRARIES}    ${BOOST_THREAD_LIBRARY} +  ${BOOST_SYSTEM_LIBRARY}    )  # tests @@ -129,8 +130,8 @@ if (LL_TESTS)        ${CURL_LIBRARIES}        ${OPENSSL_LIBRARIES}        ${CRYPTO_LIBRARIES} -      ${BOOST_SYSTEM_LIBRARY}        ${BOOST_THREAD_LIBRARY} +      ${BOOST_SYSTEM_LIBRARY}        )    # If http_proxy is in the current environment (e.g. to fetch s3-proxy @@ -197,8 +198,8 @@ endif (DARWIN)        ${CURL_LIBRARIES}        ${OPENSSL_LIBRARIES}        ${CRYPTO_LIBRARIES} -      ${BOOST_SYSTEM_LIBRARY}        ${BOOST_THREAD_LIBRARY} +      ${BOOST_SYSTEM_LIBRARY}        )    add_executable(http_texture_load diff --git a/indra/llcorehttp/tests/llcorehttp_test.cpp b/indra/llcorehttp/tests/llcorehttp_test.cpp index bef762f5ce..a310fc0508 100644..100755 --- a/indra/llcorehttp/tests/llcorehttp_test.cpp +++ b/indra/llcorehttp/tests/llcorehttp_test.cpp @@ -46,6 +46,7 @@  #include "test_httprequestqueue.hpp"  #include "llproxy.h" +#include "llcleanup.h"  unsigned long ssl_thread_id_callback(void);  void ssl_locking_callback(int mode, int type, const char * file, int line); @@ -101,7 +102,7 @@ void init_curl()  void term_curl()  { -	LLProxy::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLProxy);  	CRYPTO_set_locking_callback(NULL);  	for (int i(0); i < ssl_mutex_count; ++i) diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp index 463e55dd7e..6cd7960ecd 100644 --- a/indra/llcorehttp/tests/test_httprequest.hpp +++ b/indra/llcorehttp/tests/test_httprequest.hpp @@ -729,7 +729,7 @@ void HttpRequestTestObjectType::test<7>()  #if 0 // defined(WIN32)  		// Can't do this on any platform anymore, the LL logging system holds  		// on to memory and produces what looks like memory leaks... -	 +  		// printf("Old mem:  %d, New mem:  %d\n", mMemTotal, GetMemTotal());  		ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal());  #endif @@ -1459,21 +1459,21 @@ void HttpRequestTestObjectType::test<14>()  	// references to it after completion of this method.  	// Create before memory record as the string copy will bump numbers.  	TestHandler2 handler(this, "handler"); -    LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor); -    std::string url_base(get_base_url() + "/sleep/");	// path to a 30-second sleep -		 +	LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor); +	std::string url_base(get_base_url() + "/sleep/");   // path to a 30-second sleep +  	// record the total amount of dynamically allocated memory  	mMemTotal = GetMemTotal();  	mHandlerCalls = 0;  	HttpRequest * req = NULL;  	HttpOptions::ptr_t opts; -	 +  	try  	{ -        // Get singletons created +		// Get singletons created  		HttpRequest::createService(); -		 +  		// Start threading early so that thread memory is invariant  		// over the test.  		HttpRequest::startThread(); @@ -1482,10 +1482,10 @@ void HttpRequestTestObjectType::test<14>()  		req = new HttpRequest();  		ensure("Memory allocated on construction", mMemTotal < GetMemTotal()); -        opts = HttpOptions::ptr_t(new HttpOptions); -		opts->setRetries(0);			// Don't retry +		opts = HttpOptions::ptr_t(new HttpOptions); +		opts->setRetries(0);            // Don't retry  		opts->setTimeout(2); -		 +  		// Issue a GET that sleeps  		mStatus = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT);  		HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, @@ -1494,8 +1494,8 @@ void HttpRequestTestObjectType::test<14>()  													 0,  													 0,  													 opts, -                                                     HttpHeaders::ptr_t(), -                                                     handlerp); +													 HttpHeaders::ptr_t(), +													 handlerp);  		ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);  		// Run the notification pump. @@ -1513,7 +1513,7 @@ void HttpRequestTestObjectType::test<14>()  		mStatus = HttpStatus();  		handle = req->requestStopThread(handlerp);  		ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID); -	 +  		// Run the notification pump again  		count = 0;  		limit = LOOP_COUNT_LONG; @@ -1535,30 +1535,29 @@ void HttpRequestTestObjectType::test<14>()  		ensure("Thread actually stopped running", HttpService::isStopped());  		// release options -        opts.reset(); -		 +		opts.reset(); +  		// release the request object  		delete req;  		req = NULL;  		// Shut down service  		HttpRequest::destroyService(); -	 +  		ensure("Two handler calls on the way out", 2 == mHandlerCalls); -#if defined(WIN32) -		// Can only do this memory test on Windows.  On other platforms, -		// the LL logging system holds on to memory and produces what looks -		// like memory leaks... -	 -		// printf("Old mem:  %d, New mem:  %d\n", mMemTotal, GetMemTotal()); +#if 0 // defined(WIN32) +		// Can't do this on any platform anymore, the LL logging system holds +		// on to memory and produces what looks like memory leaks... + +		// printf("Old mem:	 %d, New mem:  %d\n", mMemTotal, GetMemTotal());  		ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal());  #endif  	}  	catch (...)  	{  		stop_thread(req); -        opts.reset(); +		opts.reset();  		delete req;  		HttpRequest::destroyService();  		throw; @@ -3065,12 +3064,11 @@ void HttpRequestTestObjectType::test<22>()  		// Shut down service  		HttpRequest::destroyService(); -	 -#if defined(WIN32) -		// Can only do this memory test on Windows.  On other platforms, -		// the LL logging system holds on to memory and produces what looks -		// like memory leaks... -	 + +#if 0 // defined(WIN32) +		// Can't do this on any platform anymore, the LL logging system holds +		// on to memory and produces what looks like memory leaks... +  		// printf("Old mem:  %d, New mem:  %d\n", mMemTotal, GetMemTotal());  		ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal());  #endif @@ -3195,12 +3193,11 @@ void HttpRequestTestObjectType::test<23>()  		// Shut down service  		HttpRequest::destroyService(); -	 -#if defined(WIN32) -		// Can only do this memory test on Windows.  On other platforms, -		// the LL logging system holds on to memory and produces what looks -		// like memory leaks... -	 + +#if 0 // defined(WIN32) +		// Can't do this on any platform anymore, the LL logging system holds +		// on to memory and produces what looks like memory leaks... +  		// printf("Old mem:  %d, New mem:  %d\n", mMemTotal, GetMemTotal());  		ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal());  #endif diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index dfb344c908..dca49be051 100644 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -45,6 +45,7 @@  #include "llhttpsdhandler.h"  #include "httpcommon.h"  #include "httpresponse.h" +#include "llcleanup.h"  #include <curl/curl.h>  #include <openssl/crypto.h> @@ -623,7 +624,7 @@ void LLCrashLogger::commonCleanup()  {      term_curl();  	LLError::logToFile("");   //close crashreport.log -	LLProxy::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLProxy);  }  void LLCrashLogger::init_curl() diff --git a/indra/llinventory/lleconomy.cpp b/indra/llinventory/lleconomy.cpp index e10402196f..2a023d8c24 100644 --- a/indra/llinventory/lleconomy.cpp +++ b/indra/llinventory/lleconomy.cpp @@ -31,7 +31,7 @@  #include "v3math.h" -LLGlobalEconomy::LLGlobalEconomy() +LLBaseEconomy::LLBaseEconomy()  :	mObjectCount( -1 ),  	mObjectCapacity( -1 ),  	mPriceObjectClaim( -1 ), @@ -45,15 +45,15 @@ LLGlobalEconomy::LLGlobalEconomy()  	mPriceGroupCreate( -1 )  { } -LLGlobalEconomy::~LLGlobalEconomy() +LLBaseEconomy::~LLBaseEconomy()  { } -void LLGlobalEconomy::addObserver(LLEconomyObserver* observer) +void LLBaseEconomy::addObserver(LLEconomyObserver* observer)  {  	mObservers.push_back(observer);  } -void LLGlobalEconomy::removeObserver(LLEconomyObserver* observer) +void LLBaseEconomy::removeObserver(LLEconomyObserver* observer)  {  	std::list<LLEconomyObserver*>::iterator it =  		std::find(mObservers.begin(), mObservers.end(), observer); @@ -63,7 +63,7 @@ void LLGlobalEconomy::removeObserver(LLEconomyObserver* observer)  	}  } -void LLGlobalEconomy::notifyObservers() +void LLBaseEconomy::notifyObservers()  {  	for (std::list<LLEconomyObserver*>::iterator it = mObservers.begin();  		it != mObservers.end(); @@ -74,7 +74,7 @@ void LLGlobalEconomy::notifyObservers()  }  // static -void LLGlobalEconomy::processEconomyData(LLMessageSystem *msg, LLGlobalEconomy* econ_data) +void LLBaseEconomy::processEconomyData(LLMessageSystem *msg, LLBaseEconomy* econ_data)  {  	S32 i;  	F32 f; @@ -117,7 +117,7 @@ void LLGlobalEconomy::processEconomyData(LLMessageSystem *msg, LLGlobalEconomy*  	econ_data->notifyObservers();  } -S32	LLGlobalEconomy::calculateTeleportCost(F32 distance) const +S32	LLBaseEconomy::calculateTeleportCost(F32 distance) const  {  	S32 min_cost = getTeleportMinPrice();  	F32 exponent = getTeleportPriceExponent(); @@ -135,13 +135,13 @@ S32	LLGlobalEconomy::calculateTeleportCost(F32 distance) const  	return cost;  } -S32	LLGlobalEconomy::calculateLightRent(const LLVector3& object_size) const +S32	LLBaseEconomy::calculateLightRent(const LLVector3& object_size) const  {  	F32 intensity_mod = llmax(object_size.magVec(), 1.f);  	return (S32)(intensity_mod * getPriceRentLight());  } -void LLGlobalEconomy::print() +void LLBaseEconomy::print()  {  	LL_INFOS() << "Global Economy Settings: " << LL_ENDL;  	LL_INFOS() << "Object Capacity: " << mObjectCapacity << LL_ENDL; @@ -159,8 +159,7 @@ void LLGlobalEconomy::print()  }  LLRegionEconomy::LLRegionEconomy() -:	LLGlobalEconomy(), -	mPriceObjectRent( -1.f ), +:	mPriceObjectRent( -1.f ),  	mPriceObjectScaleFactor( -1.f ),  	mEnergyEfficiency( -1.f ),  	mBasePriceParcelClaimDefault(-1), @@ -187,7 +186,7 @@ void LLRegionEconomy::processEconomyData(LLMessageSystem *msg, void** user_data)  	LLRegionEconomy *this_ptr = (LLRegionEconomy*)user_data; -	LLGlobalEconomy::processEconomyData(msg, this_ptr); +	LLBaseEconomy::processEconomyData(msg, this_ptr);  	msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceParcelClaim, i);  	this_ptr->setBasePriceParcelClaimDefault(i); @@ -252,7 +251,7 @@ S32 LLRegionEconomy::getPriceParcelRent() const  void LLRegionEconomy::print()  { -	this->LLGlobalEconomy::print(); +	this->LLBaseEconomy::print();  	LL_INFOS() << "Region Economy Settings: " << LL_ENDL;  	LL_INFOS() << "Land (square meters): " << mAreaTotal << LL_ENDL; diff --git a/indra/llinventory/lleconomy.h b/indra/llinventory/lleconomy.h index 47fcf688a2..cdfde171c1 100644 --- a/indra/llinventory/lleconomy.h +++ b/indra/llinventory/lleconomy.h @@ -42,18 +42,11 @@ public:  	virtual void onEconomyDataChange() = 0;  }; -class LLGlobalEconomy +class LLBaseEconomy  {  public: -	LLGlobalEconomy(); -	virtual ~LLGlobalEconomy(); - -	// This class defines its singleton internally as a typedef instead of inheriting from -	// LLSingleton like most others because the LLRegionEconomy sub-class might also -	// become a singleton and this pattern will more easily disambiguate them. -	typedef LLSingleton<LLGlobalEconomy> Singleton; - -	void initSingleton() { } +	LLBaseEconomy(); +	virtual ~LLBaseEconomy();  	virtual void print(); @@ -61,7 +54,7 @@ public:  	void	removeObserver(LLEconomyObserver* observer);  	void	notifyObservers(); -	static void processEconomyData(LLMessageSystem *msg, LLGlobalEconomy* econ_data); +	static void processEconomyData(LLMessageSystem *msg, LLBaseEconomy* econ_data);  	S32		calculateTeleportCost(F32 distance) const;  	S32		calculateLightRent(const LLVector3& object_size) const; @@ -108,8 +101,12 @@ private:  	std::list<LLEconomyObserver*> mObservers;  }; +class LLGlobalEconomy: public LLSingleton<LLGlobalEconomy>, public LLBaseEconomy +{ +	LLSINGLETON_EMPTY_CTOR(LLGlobalEconomy); +}; -class LLRegionEconomy : public LLGlobalEconomy +class LLRegionEconomy : public LLBaseEconomy  {  public:  	LLRegionEconomy(); diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp index 86aca77de8..b0daf639fa 100644 --- a/indra/llinventory/llfoldertype.cpp +++ b/indra/llinventory/llfoldertype.cpp @@ -51,8 +51,7 @@ struct FolderEntry : public LLDictionaryEntry  class LLFolderDictionary : public LLSingleton<LLFolderDictionary>,  						   public LLDictionary<LLFolderType::EType, FolderEntry>  { -public: -	LLFolderDictionary(); +	LLSINGLETON(LLFolderDictionary);  protected:  	virtual LLFolderType::EType notFound() const  	{ diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index 8807b36117..d1e6807f52 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -63,8 +63,7 @@ struct InventoryEntry : public LLDictionaryEntry  class LLInventoryDictionary : public LLSingleton<LLInventoryDictionary>,  							  public LLDictionary<LLInventoryType::EType, InventoryEntry>  { -public: -	LLInventoryDictionary(); +	LLSINGLETON(LLInventoryDictionary);  };  LLInventoryDictionary::LLInventoryDictionary() diff --git a/indra/llmessage/llcoproceduremanager.h b/indra/llmessage/llcoproceduremanager.h index 497367b80c..7d0e83180c 100644 --- a/indra/llmessage/llcoproceduremanager.h +++ b/indra/llmessage/llcoproceduremanager.h @@ -37,7 +37,8 @@ class LLCoprocedurePool;  class LLCoprocedureManager : public LLSingleton < LLCoprocedureManager >  { -    friend class LLSingleton < LLCoprocedureManager > ; +    LLSINGLETON(LLCoprocedureManager); +    virtual ~LLCoprocedureManager();  public:      typedef boost::function<U32(const std::string &)> SettingQuery_t; @@ -45,9 +46,6 @@ public:      typedef boost::function<void(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, const LLUUID &id)> CoProcedure_t; -    LLCoprocedureManager(); -    virtual ~LLCoprocedureManager(); -      /// Places the coprocedure on the queue for processing.       ///       /// @param name Is used for debugging and should identify this coroutine. diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h index 1002b33f80..8ee7080d38 100644 --- a/indra/llmessage/llexperiencecache.h +++ b/indra/llmessage/llexperiencecache.h @@ -43,7 +43,7 @@ class LLUUID;  class LLExperienceCache: public LLSingleton < LLExperienceCache >  { -    friend class LLSingleton < LLExperienceCache > ; +    LLSINGLETON(LLExperienceCache);  public:      typedef boost::function<std::string(const std::string &)> CapabilityQuery_t; @@ -103,7 +103,6 @@ public:      static const int PROPERTY_SUSPENDED;	// 1 << 7  private: -    LLExperienceCache();      virtual ~LLExperienceCache();      virtual void initSingleton(); diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h index bd23dd39de..688dff7c83 100644 --- a/indra/llmessage/llproxy.h +++ b/indra/llmessage/llproxy.h @@ -218,14 +218,14 @@ enum LLSocks5AuthType   */  class LLProxy: public LLSingleton<LLProxy>  { -	LOG_CLASS(LLProxy); -public:  	/*###########################################################################################  	METHODS THAT DO NOT LOCK mProxyMutex!  	###########################################################################################*/  	// Constructor, cannot have parameters due to LLSingleton parent class. Call from main thread only. -	LLProxy(); +	LLSINGLETON(LLProxy); +	LOG_CLASS(LLProxy); +public:  	// Static check for enabled status for UDP packets. Call from main thread only.  	static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; } @@ -239,9 +239,11 @@ public:  	/*###########################################################################################  	METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!  	###########################################################################################*/ +private:  	// Destructor, closes open connections. Do not call directly, use cleanupClass().  	~LLProxy(); +public:  	// Delete LLProxy singleton. Allows the apr_socket used in the SOCKS 5 control channel to be  	// destroyed before the call to apr_terminate. Call from main thread only.  	static void cleanupClass(); diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index 290b67feb3..6ef4025ab1 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -76,6 +76,7 @@  #include "v4math.h"  #include "lltransfertargetvfile.h"  #include "llcorehttputil.h" +#include "llpounceable.h"  // Constants  //const char* MESSAGE_LOG_FILENAME = "message.log"; @@ -1724,7 +1725,9 @@ std::ostream& operator<<(std::ostream& s, LLMessageSystem &msg)  	return s;  } -LLMessageSystem	*gMessageSystem = NULL; +// LLPounceable supports callWhenReady(), to permit clients to queue up (e.g.) +// callback registrations for when gMessageSystem is first assigned +LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;  // update appropriate ping info  void	process_complete_ping_check(LLMessageSystem *msgsystem, void** /*user_data*/) @@ -2641,7 +2644,7 @@ void end_messaging_system(bool print_summary)  			LL_INFOS("Messaging") << str.str().c_str() << LL_ENDL;  		} -		delete gMessageSystem; +		delete static_cast<LLMessageSystem*>(gMessageSystem);  		gMessageSystem = NULL;  	}  } diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h index 133db620e6..f6c5d9e228 100644 --- a/indra/llmessage/message.h +++ b/indra/llmessage/message.h @@ -60,6 +60,7 @@  #include "llstoredmessage.h"  #include "boost/function.hpp" +#include "llpounceable.h"  const U32 MESSAGE_MAX_STRINGS_LENGTH = 64;  const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192; @@ -68,10 +69,10 @@ const S32 MESSAGE_MAX_PER_FRAME = 400;  class LLMessageStringTable : public LLSingleton<LLMessageStringTable>  { -public: -	LLMessageStringTable(); +	LLSINGLETON(LLMessageStringTable);  	~LLMessageStringTable(); +public:  	char *getString(const char *str);  	U32	 mUsed; @@ -832,7 +833,7 @@ private:  // external hook into messaging system -extern LLMessageSystem	*gMessageSystem; +extern LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;  // Must specific overall system version, which is used to determine  // if a patch is available in the message template checksum verification. diff --git a/indra/llmessage/tests/llhttpclient_test.cpp b/indra/llmessage/tests/llhttpclient_test.cpp index a32bfa59ce..9356a14f1f 100644 --- a/indra/llmessage/tests/llhttpclient_test.cpp +++ b/indra/llmessage/tests/llhttpclient_test.cpp @@ -42,6 +42,7 @@  #include "lliosocket.h"  #include "stringize.h" +#include "llcleanup.h"  namespace tut  { @@ -66,7 +67,7 @@ namespace tut  		~HTTPClientTestData()  		{  			delete mClientPump; -			LLProxy::cleanupClass(); +			SUBSYSTEM_CLEANUP(LLProxy);  			apr_pool_destroy(mPool);  		} diff --git a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp index 3b04530c1a..e20f61b73f 100644 --- a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp +++ b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp @@ -31,11 +31,12 @@  #include "llhost.h"  #include "message.h"  #include "llsd.h" +#include "llpounceable.h"  #include "llhost.cpp" // Needed for copy operator  #include "net.cpp" // Needed by LLHost. -LLMessageSystem * gMessageSystem = NULL; +LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;  // sensor test doubles  bool gClearRecvWasCalled = false; diff --git a/indra/llmessage/tests/lltrustedmessageservice_test.cpp b/indra/llmessage/tests/lltrustedmessageservice_test.cpp index 55748ad27e..41f982a7e2 100644 --- a/indra/llmessage/tests/lltrustedmessageservice_test.cpp +++ b/indra/llmessage/tests/lltrustedmessageservice_test.cpp @@ -33,8 +33,9 @@  #include "message.h"  #include "llmessageconfig.h"  #include "llhttpnode_stub.cpp" +#include "llpounceable.h" -LLMessageSystem* gMessageSystem = NULL; +LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;  LLMessageConfig::SenderTrust  LLMessageConfig::getSenderTrustedness(const std::string& msg_name) diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h index 5eb739393f..5986524342 100644 --- a/indra/llmessage/tests/networkio.h +++ b/indra/llmessage/tests/networkio.h @@ -44,7 +44,7 @@  // init time. Use the lazy, on-demand initialization we get from LLSingleton.  class NetworkIO: public LLSingleton<NetworkIO>  { -public: +    LLSINGLETON(NetworkIO);      NetworkIO():          mServicePump(NULL),          mDone(false) @@ -69,6 +69,7 @@ public:                                                         boost::bind(&NetworkIO::done, this, _1));      } +public:      bool pump(F32 timeout=10)      {          // Reset the done flag so we don't pop out prematurely diff --git a/indra/llui/llclipboard.h b/indra/llui/llclipboard.h index 58d80e2687..a668ac1ac6 100644 --- a/indra/llui/llclipboard.h +++ b/indra/llui/llclipboard.h @@ -48,10 +48,10 @@  class LLClipboard : public LLSingleton<LLClipboard>  { -public: -	LLClipboard(); +	LLSINGLETON(LLClipboard);  	~LLClipboard(); +public:  	// Clears the clipboard  	void reset();  	// Returns the state of the clipboard so client can know if it has been modified (comparing with tracked state) diff --git a/indra/llui/llcommandmanager.h b/indra/llui/llcommandmanager.h index f2f2145953..8cec5e2b24 100644 --- a/indra/llui/llcommandmanager.h +++ b/indra/llui/llcommandmanager.h @@ -173,6 +173,9 @@ private:  class LLCommandManager  :	public LLSingleton<LLCommandManager>  { +	LLSINGLETON(LLCommandManager); +	~LLCommandManager(); +  public:  	struct Params : public LLInitParam::Block<Params>  	{ @@ -184,9 +187,6 @@ public:  		}  	}; -	LLCommandManager(); -	~LLCommandManager(); -  	U32 commandCount() const;  	LLCommand * getCommand(U32 commandIndex);  	LLCommand * getCommand(const LLCommandId& commandId); diff --git a/indra/llui/llcontainerview.h b/indra/llui/llcontainerview.h index ac92b19977..99267d978a 100644 --- a/indra/llui/llcontainerview.h +++ b/indra/llui/llcontainerview.h @@ -35,7 +35,9 @@  class LLScrollContainer;  struct ContainerViewRegistry : public LLChildRegistry<ContainerViewRegistry> -{}; +{ +	LLSINGLETON_EMPTY_CTOR(ContainerViewRegistry); +};  class LLContainerView : public LLView  { diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h index f5364f4863..e43974bc52 100644 --- a/indra/llui/llfunctorregistry.h +++ b/indra/llui/llfunctorregistry.h @@ -53,14 +53,8 @@  template <typename FUNCTOR_TYPE>  class LLFunctorRegistry : public LLSingleton<LLFunctorRegistry<FUNCTOR_TYPE> >  { -	friend class LLSingleton<LLFunctorRegistry>; +	LLSINGLETON(LLFunctorRegistry);  	LOG_CLASS(LLFunctorRegistry); -private: -	LLFunctorRegistry() : LOGFUNCTOR("LogFunctor"), DONOTHING("DoNothing") -	{ -		mMap[LOGFUNCTOR] = log_functor; -		mMap[DONOTHING] = do_nothing; -	}  public:  	typedef FUNCTOR_TYPE ResponseFunctor; @@ -125,6 +119,14 @@ private:  };  template <typename FUNCTOR_TYPE> +LLFunctorRegistry<FUNCTOR_TYPE>::LLFunctorRegistry() : +	LOGFUNCTOR("LogFunctor"), DONOTHING("DoNothing") +{ +	mMap[LOGFUNCTOR] = log_functor; +	mMap[DONOTHING] = do_nothing; +} + +template <typename FUNCTOR_TYPE>  class LLFunctorRegistration  {  public: diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index a245ebe1b9..f772dbc6b4 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -40,7 +40,9 @@ class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>  public:  	struct LayoutStackRegistry : public LLChildRegistry<LayoutStackRegistry> -	{}; +	{ +		LLSINGLETON_EMPTY_CTOR(LayoutStackRegistry); +	};  	struct Params : public LLInitParam::Block<Params, LLView::Params>  	{ diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 628dedb906..c7f7f6848c 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -347,7 +347,9 @@ private:  // child widget registry  struct MenuRegistry : public LLChildRegistry<MenuRegistry> -{}; +{ +	LLSINGLETON_EMPTY_CTOR(MenuRegistry); +};  class LLMenuGL  diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 354add0b82..024332ee65 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -884,9 +884,9 @@ class LLNotifications :  	public LLSingleton<LLNotifications>,   	public LLNotificationChannelBase  { +	LLSINGLETON(LLNotifications);  	LOG_CLASS(LLNotifications); -	friend class LLSingleton<LLNotifications>;  public:      // Needed to clear up RefCounted things prior to actual destruction @@ -966,8 +966,6 @@ public:  	bool isVisibleByRules(LLNotificationPtr pNotification);  private: -	// we're a singleton, so we don't have a public constructor -	LLNotifications();  	/*virtual*/ void initSingleton();  	void loadPersistentNotifications(); diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index c2185f24de..b8f47ef6ba 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -268,8 +268,9 @@ typedef boost::function<LLPanel* (void)> LLPanelClassCreatorFunc;  class LLRegisterPanelClass  :	public LLSingleton< LLRegisterPanelClass >  { +	LLSINGLETON_EMPTY_CTOR(LLRegisterPanelClass);  public: -	// reigister with either the provided builder, or the generic templated builder +	// register with either the provided builder, or the generic templated builder  	void addPanelClass(const std::string& tag,LLPanelClassCreatorFunc func)  	{  		mPanelClassesNames[tag] = func; diff --git a/indra/llui/llresmgr.h b/indra/llui/llresmgr.h index a652dcd2c0..b19d8d40b8 100644 --- a/indra/llui/llresmgr.h +++ b/indra/llui/llresmgr.h @@ -42,9 +42,9 @@ enum LLLOCALE_ID  class LLResMgr : public LLSingleton<LLResMgr>  { -public: -	LLResMgr(); +	LLSINGLETON(LLResMgr); +public:  	void				setLocale( LLLOCALE_ID locale_id );  	LLLOCALE_ID			getLocale() const						{ return mLocale; } diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h index f64cf43a8e..c4c4d0a136 100644 --- a/indra/llui/llscrollcontainer.h +++ b/indra/llui/llscrollcontainer.h @@ -48,7 +48,9 @@ class LLUICtrlFactory;   *****************************************************************************/  struct ScrollContainerRegistry : public LLChildRegistry<ScrollContainerRegistry> -{}; +{ +	LLSINGLETON_EMPTY_CTOR(ScrollContainerRegistry); +};  class LLScrollContainer : public LLUICtrl  { diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h index 4ab80195ea..acac589e43 100644 --- a/indra/llui/llspellcheck.h +++ b/indra/llui/llspellcheck.h @@ -29,16 +29,15 @@  #include "llsingleton.h"  #include "llui.h" +#include "llinitdestroyclass.h"  #include <boost/signals2.hpp>  class Hunspell;  class LLSpellChecker : public LLSingleton<LLSpellChecker>, public LLInitClass<LLSpellChecker>  { -	friend class LLSingleton<LLSpellChecker>; +	LLSINGLETON(LLSpellChecker);  	friend class LLInitClass<LLSpellChecker>; -protected: -	LLSpellChecker();  	~LLSpellChecker();  public: diff --git a/indra/llui/llstatview.h b/indra/llui/llstatview.h index bc78d3b5fd..af4db7d7ea 100644 --- a/indra/llui/llstatview.h +++ b/indra/llui/llstatview.h @@ -35,7 +35,9 @@ class LLStatBar;  // widget registrars  struct StatViewRegistry : public LLChildRegistry<StatViewRegistry> -{}; +{ +	LLSINGLETON_EMPTY_CTOR(StatViewRegistry); +};  class LLStatView : public LLContainerView  { diff --git a/indra/llui/lltextparser.h b/indra/llui/lltextparser.h index 400aeeb8be..3d71e40452 100644 --- a/indra/llui/lltextparser.h +++ b/indra/llui/lltextparser.h @@ -37,14 +37,14 @@ class LLColor4;  class LLTextParser : public LLSingleton<LLTextParser>  { +	LLSINGLETON(LLTextParser); +  public:  	typedef enum e_condition_type { CONTAINS, MATCHES, STARTS_WITH, ENDS_WITH } EConditionType;  	typedef enum e_highlight_type { PART, ALL } EHighlightType;  	typedef enum e_highlight_position { WHOLE, START, MIDDLE, END } EHighlightPosition;  	typedef enum e_dialog_action { ACTION_NONE, ACTION_CLOSE, ACTION_ADD, ACTION_COPY, ACTION_UPDATE } EDialogAction; -	LLTextParser(); -  	LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color, EHighlightPosition part=WHOLE, S32 index=0);  	bool parseFullLineHighlights(const std::string &text, LLColor4 *color); diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h index fad127fc4c..0b1fbe5367 100644 --- a/indra/llui/lltooltip.h +++ b/indra/llui/lltooltip.h @@ -129,9 +129,10 @@ public:  class LLToolTipMgr : public LLSingleton<LLToolTipMgr>  { +	LLSINGLETON(LLToolTipMgr);  	LOG_CLASS(LLToolTipMgr); +  public: -	LLToolTipMgr();  	void show(const LLToolTip::Params& params);  	void show(const std::string& message); diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index f790d8e005..770f13c1c3 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -60,6 +60,7 @@  #include "llflyoutbutton.h"  #include "llsearcheditor.h"  #include "lltoolbar.h" +#include "llcleanup.h"  // for XUIParse  #include "llquaternion.h" @@ -208,7 +209,7 @@ void LLUI::initClass(const settings_map_t& settings,  void LLUI::cleanupClass()  { -	LLRender2D::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLRender2D);  }  void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& remove_popup,  const clear_popups_t& clear_popups) diff --git a/indra/llui/llui.h b/indra/llui/llui.h index c727f75c4f..d7151dbee9 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -344,95 +344,6 @@ private:  // Moved LLLocalClipRect to lllocalcliprect.h -class LLCallbackRegistry -{ -public: -	typedef boost::signals2::signal<void()> callback_signal_t; -	 -	void registerCallback(const callback_signal_t::slot_type& slot) -	{ -		mCallbacks.connect(slot); -	} - -	void fireCallbacks() -	{ -		mCallbacks(); -	} - -private: -	callback_signal_t mCallbacks; -}; - -class LLInitClassList :  -	public LLCallbackRegistry,  -	public LLSingleton<LLInitClassList> -{ -	friend class LLSingleton<LLInitClassList>; -private: -	LLInitClassList() {} -}; - -class LLDestroyClassList :  -	public LLCallbackRegistry,  -	public LLSingleton<LLDestroyClassList> -{ -	friend class LLSingleton<LLDestroyClassList>; -private: -	LLDestroyClassList() {} -}; - -template<typename T> -class LLRegisterWith -{ -public: -	LLRegisterWith(boost::function<void ()> func) -	{ -		T::instance().registerCallback(func); -	} - -	// this avoids a MSVC bug where non-referenced static members are "optimized" away -	// even if their constructors have side effects -	S32 reference() -	{ -		S32 dummy; -		dummy = 0; -		return dummy; -	} -}; - -template<typename T> -class LLInitClass -{ -public: -	LLInitClass() { sRegister.reference(); } - -	static LLRegisterWith<LLInitClassList> sRegister; -private: - -	static void initClass() -	{ -		LL_ERRS() << "No static initClass() method defined for " << typeid(T).name() << LL_ENDL; -	} -}; - -template<typename T> -class LLDestroyClass -{ -public: -	LLDestroyClass() { sRegister.reference(); } - -	static LLRegisterWith<LLDestroyClassList> sRegister; -private: - -	static void destroyClass() -	{ -		LL_ERRS() << "No static destroyClass() method defined for " << typeid(T).name() << LL_ENDL; -	} -}; - -template <typename T> LLRegisterWith<LLInitClassList> LLInitClass<T>::sRegister(&T::initClass); -template <typename T> LLRegisterWith<LLDestroyClassList> LLDestroyClass<T>::sRegister(&T::destroyClass); -  // useful parameter blocks  struct TimeIntervalParam : public LLInitParam::ChoiceBlock<TimeIntervalParam>  { diff --git a/indra/llui/lluicolortable.h b/indra/llui/lluicolortable.h index 6a7a681d57..44472070cc 100644 --- a/indra/llui/lluicolortable.h +++ b/indra/llui/lluicolortable.h @@ -38,7 +38,8 @@ class LLUIColor;  class LLUIColorTable : public LLSingleton<LLUIColorTable>  { -LOG_CLASS(LLUIColorTable); +	LLSINGLETON_EMPTY_CTOR(LLUIColorTable); +	LOG_CLASS(LLUIColorTable);  	// consider using sorted vector, can be much faster  	typedef std::map<std::string, LLUIColor>  string_color_map_t; diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 99553ee0d2..550bee5c70 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -258,18 +258,25 @@ public:  	class LLTextInputFilter : public LLQueryFilter, public LLSingleton<LLTextInputFilter>  	{ +		LLSINGLETON_EMPTY_CTOR(LLTextInputFilter);  		/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const   		{  			return filterResult_t(view->isCtrl() && static_cast<const LLUICtrl *>(view)->acceptsTextInput(), TRUE);  		}  	}; -	 +  	template <typename F, typename DERIVED> class CallbackRegistry : public LLRegistrySingleton<std::string, F, DERIVED >  	{};	 -	class CommitCallbackRegistry : public CallbackRegistry<commit_callback_t, CommitCallbackRegistry>{}; +	class CommitCallbackRegistry : public CallbackRegistry<commit_callback_t, CommitCallbackRegistry> +	{ +		LLSINGLETON_EMPTY_CTOR(CommitCallbackRegistry); +	};  	// the enable callback registry is also used for visiblity callbacks -	class EnableCallbackRegistry : public CallbackRegistry<enable_callback_t, EnableCallbackRegistry>{}; +	class EnableCallbackRegistry : public CallbackRegistry<enable_callback_t, EnableCallbackRegistry> +	{ +		LLSINGLETON_EMPTY_CTOR(EnableCallbackRegistry); +	};  protected: diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 3ce39c947f..03d946f1b7 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -33,6 +33,8 @@  #include "llxuiparser.h"  #include "llstl.h"  #include "lldir.h" +#include "llsingleton.h" +#include "llheteromap.h"  class LLView; @@ -57,22 +59,24 @@ protected:  class LLDefaultChildRegistry : public LLChildRegistry<LLDefaultChildRegistry>  { -protected: -	LLDefaultChildRegistry(){} -	friend class LLSingleton<LLDefaultChildRegistry>; +	LLSINGLETON_EMPTY_CTOR(LLDefaultChildRegistry);  };  // lookup widget name by type  class LLWidgetNameRegistry   :	public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry> -{}; +{ +	LLSINGLETON_EMPTY_CTOR(LLWidgetNameRegistry); +};  // lookup function for generating empty param block by widget type  // this is used for schema generation  //typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)();  //class LLDefaultParamBlockRegistry  //:	public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry> -//{}; +//{ +//	LLSINGLETON(LLDefaultParamBlockRegistry); +//};  extern LLTrace::BlockTimerStatHandle FTM_WIDGET_SETUP;  extern LLTrace::BlockTimerStatHandle FTM_WIDGET_CONSTRUCTION; @@ -85,31 +89,15 @@ extern template class LLUICtrlFactory* LLSingleton<class LLUICtrlFactory>::getIn  class LLUICtrlFactory : public LLSingleton<LLUICtrlFactory>  { -private: -	friend class LLSingleton<LLUICtrlFactory>; -	LLUICtrlFactory(); +	LLSINGLETON(LLUICtrlFactory);  	~LLUICtrlFactory();  	// only partial specialization allowed in inner classes, so use extra dummy parameter  	template <typename PARAM_BLOCK, int DUMMY> -	class ParamDefaults : public LLSingleton<ParamDefaults<PARAM_BLOCK, DUMMY> >  +	class ParamDefaults  	{  	public: -		ParamDefaults() -		{ -			// look up template file for this param block... -			const std::string* param_block_tag = LLWidgetNameRegistry::instance().getValue(&typeid(PARAM_BLOCK)); -			if (param_block_tag) -			{	// ...and if it exists, back fill values using the most specific template first -				PARAM_BLOCK params; -				LLUICtrlFactory::loadWidgetTemplate(*param_block_tag, params); -				mPrototype.fillFrom(params); -			} -			// recursively fill from base class param block -			((typename PARAM_BLOCK::base_block_t&)mPrototype).fillFrom(ParamDefaults<typename PARAM_BLOCK::base_block_t, DUMMY>::instance().get()); - -		} - +		ParamDefaults();  		const PARAM_BLOCK& get() { return mPrototype; }  	private: @@ -118,9 +106,10 @@ private:  	// base case for recursion, there are NO base classes of LLInitParam::BaseBlock  	template<int DUMMY> -	class ParamDefaults<LLInitParam::BaseBlock, DUMMY> : public LLSingleton<ParamDefaults<LLInitParam::BaseBlock, DUMMY> > +	class ParamDefaults<LLInitParam::BaseBlock, DUMMY>  	{  	public: +		ParamDefaults();  		const LLInitParam::BaseBlock& get() { return mBaseBlock; }  	private:  		LLInitParam::BaseBlock mBaseBlock; @@ -132,7 +121,7 @@ public:  	template<typename T>  	static const typename T::Params& getDefaultParams()  	{ -		return ParamDefaults<typename T::Params, 0>::instance().get(); +		return instance().mParamDefaultsMap.obtain< ParamDefaults<typename T::Params, 0> >().get();  	}  	// Does what you want for LLFloaters and LLPanels @@ -147,7 +136,8 @@ public:  	template<typename T>  	static T* create(typename T::Params& params, LLView* parent = NULL)  	{ -		params.fillFrom(ParamDefaults<typename T::Params, 0>::instance().get()); +		params.fillFrom(instance().mParamDefaultsMap.obtain< +						ParamDefaults<typename T::Params, 0> >().get());  		T* widget = createWidgetImpl<T>(params, parent);  		if (widget) @@ -295,8 +285,40 @@ private:  	class LLPanel*		mDummyPanel;  	std::vector<std::string>	mFileNames; + +	// store ParamDefaults specializations +	// Each ParamDefaults specialization used to be an LLSingleton in its own +	// right. But the 2016 changes to the LLSingleton mechanism, making +	// LLSingleton instances polymorphic, are incompatible with current +	// LLInitParam::BaseBlock functionality. (Thanks NickyD for spotting +	// that!) Moreover, instances of the private nested ParamDefaults template +	// aren't global resources -- which is what LLSingleton is designed for. +	// This is simply a cache looked up by type. Its lifespan is tied to +	// LLUICtrlFactory. Use LLHeteroMap for this cache. +	LLHeteroMap mParamDefaultsMap;  }; +template <typename PARAM_BLOCK, int DUMMY> +LLUICtrlFactory::ParamDefaults<PARAM_BLOCK, DUMMY>::ParamDefaults() +{ +	// look up template file for this param block... +	const std::string* param_block_tag = LLWidgetNameRegistry::instance().getValue(&typeid(PARAM_BLOCK)); +	if (param_block_tag) +	{	// ...and if it exists, back fill values using the most specific template first +		PARAM_BLOCK params; +		LLUICtrlFactory::loadWidgetTemplate(*param_block_tag, params); +		mPrototype.fillFrom(params); +	} +	// recursively fill from base class param block +	((typename PARAM_BLOCK::base_block_t&)mPrototype).fillFrom( +		LLUICtrlFactory::instance().mParamDefaultsMap.obtain< +		ParamDefaults<typename PARAM_BLOCK::base_block_t, DUMMY> >().get()); + +} + +template <int DUMMY> +LLUICtrlFactory::ParamDefaults<LLInitParam::BaseBlock, DUMMY>::ParamDefaults() {} +  // this is here to make gcc happy with reference to LLUICtrlFactory  template<typename DERIVED>  template<typename T>  diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h index 24c3a2b513..efafe543ab 100644 --- a/indra/llui/llurlregistry.h +++ b/indra/llui/llurlregistry.h @@ -62,9 +62,9 @@ void LLUrlRegistryNullCallback(const std::string &url,  ///  class LLUrlRegistry : public LLSingleton<LLUrlRegistry>  { -public: +	LLSINGLETON(LLUrlRegistry);  	~LLUrlRegistry(); - +public:  	/// add a new Url handler to the registry (will be freed on destruction)  	/// optionally force it to the front of the list, making it take  	/// priority over other regular expression matches for URLs @@ -89,9 +89,6 @@ public:  	bool isUrl(const LLWString &text);  private: -	LLUrlRegistry(); -	friend class LLSingleton<LLUrlRegistry>; -  	std::vector<LLUrlEntryBase *> mUrlEntry;  	LLUrlEntryBase*	mUrlEntryTrusted;  	LLUrlEntryBase*	mUrlEntryIcon; diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 9604e5ce10..89ad8138d8 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1912,6 +1912,7 @@ private:  class SortByTabOrder : public LLQuerySorter, public LLSingleton<SortByTabOrder>  { +	LLSINGLETON_EMPTY_CTOR(SortByTabOrder);  	/*virtual*/ void sort(LLView * parent, LLView::child_list_t &children) const   	{  		children.sort(CompareByTabOrder(parent->getTabOrder(), parent->getDefaultTabGroup())); @@ -1935,6 +1936,7 @@ const LLViewQuery & LLView::getTabOrderQuery()  // This class is only used internally by getFocusRootsQuery below.   class LLFocusRootsFilter : public LLQueryFilter, public LLSingleton<LLFocusRootsFilter>  { +	LLSINGLETON_EMPTY_CTOR(LLFocusRootsFilter);  	/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const   	{  		return filterResult_t(view->isCtrl() && view->isFocusRoot(), !view->isFocusRoot()); diff --git a/indra/llui/llviewereventrecorder.h b/indra/llui/llviewereventrecorder.h index 375efcc3de..d1059d55de 100644 --- a/indra/llui/llviewereventrecorder.h +++ b/indra/llui/llviewereventrecorder.h @@ -44,13 +44,10 @@  class LLViewerEventRecorder : public LLSingleton<LLViewerEventRecorder>  { - - public: - -  LLViewerEventRecorder(); // TODO Protect constructor better if we can (not happy in private section) - could add a factory... - we are singleton +  LLSINGLETON(LLViewerEventRecorder);    ~LLViewerEventRecorder(); - + public:    void updateMouseEventInfo(S32 local_x,S32 local_y, S32 global_x, S32 global_y,  std::string mName);    void setMouseLocalCoords(S32 x,S32 y);    void setMouseGlobalCoords(S32 x,S32 y); diff --git a/indra/llui/llviewquery.h b/indra/llui/llviewquery.h index 9044c4ff29..21bb1be26f 100644 --- a/indra/llui/llviewquery.h +++ b/indra/llui/llviewquery.h @@ -54,31 +54,37 @@ public:  class LLLeavesFilter : public LLQueryFilter, public LLSingleton<LLLeavesFilter>  { +	LLSINGLETON_EMPTY_CTOR(LLLeavesFilter);  	/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;  };  class LLRootsFilter : public LLQueryFilter, public LLSingleton<LLRootsFilter>  { +	LLSINGLETON_EMPTY_CTOR(LLRootsFilter);  	/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;  };  class LLVisibleFilter : public LLQueryFilter, public LLSingleton<LLVisibleFilter>  { +	LLSINGLETON_EMPTY_CTOR(LLVisibleFilter);  	/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;  };  class LLEnabledFilter : public LLQueryFilter, public LLSingleton<LLEnabledFilter>  { +	LLSINGLETON_EMPTY_CTOR(LLEnabledFilter);  	/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;  };  class LLTabStopFilter : public LLQueryFilter, public LLSingleton<LLTabStopFilter>  { +	LLSINGLETON_EMPTY_CTOR(LLTabStopFilter);  	/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;  };  class LLCtrlFilter : public LLQueryFilter, public LLSingleton<LLCtrlFilter>  { +	LLSINGLETON_EMPTY_CTOR(LLCtrlFilter);  	/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;  }; diff --git a/indra/llui/llxuiparser.h b/indra/llui/llxuiparser.h index bb11a23938..eb0eac8194 100644 --- a/indra/llui/llxuiparser.h +++ b/indra/llui/llxuiparser.h @@ -41,7 +41,9 @@ class LLView;  // lookup widget type by name  class LLWidgetTypeRegistry  :	public LLRegistrySingleton<std::string, const std::type_info*, LLWidgetTypeRegistry> -{}; +{ +	LLSINGLETON_EMPTY_CTOR(LLWidgetTypeRegistry); +};  // global static instance for registering all widget types @@ -51,7 +53,9 @@ typedef LLRegistry<std::string, LLWidgetCreatorFunc> widget_registry_t;  class LLChildRegistryRegistry  : public LLRegistrySingleton<const std::type_info*, widget_registry_t, LLChildRegistryRegistry> -{}; +{ +	LLSINGLETON_EMPTY_CTOR(LLChildRegistryRegistry); +};  class LLXSDWriter : public LLInitParam::Parser  { diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index f01178c374..338be1808d 100644..100755 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -31,6 +31,7 @@  #include "llcachename.h"  #include "lluuid.h"  #include "message.h" +#include "llpounceable.h"  #include <string> @@ -165,7 +166,7 @@ LLFontGL* LLFontGL::getFontDefault()  char const* const _PREHASH_AgentData = (char *)"AgentData";  char const* const _PREHASH_AgentID = (char *)"AgentID"; -LLMessageSystem* gMessageSystem = NULL; +LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;  //  // Stub implementation for LLMessageSystem diff --git a/indra/media_plugins/cef/windows_volume_catcher.cpp b/indra/media_plugins/cef/windows_volume_catcher.cpp index 0cfb810906..c9ea3ed597 100644 --- a/indra/media_plugins/cef/windows_volume_catcher.cpp +++ b/indra/media_plugins/cef/windows_volume_catcher.cpp @@ -31,17 +31,16 @@  #include "llsingleton.h"  class VolumeCatcherImpl : public LLSingleton<VolumeCatcherImpl>  { -friend LLSingleton<VolumeCatcherImpl>; +	LLSINGLETON(VolumeCatcherImpl); +	// This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. +	~VolumeCatcherImpl(); +  public:  	void setVolume(F32 volume);  	void setPan(F32 pan);  private: -	// This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. -	VolumeCatcherImpl(); -	~VolumeCatcherImpl(); -  	typedef void (WINAPI *set_volume_func_t)(F32);  	typedef void (WINAPI *set_mute_func_t)(bool); diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h index f251ceffd4..55e1d19f05 100644 --- a/indra/newview/llaccountingcostmanager.h +++ b/indra/newview/llaccountingcostmanager.h @@ -58,9 +58,9 @@ protected:  //===============================================================================  class LLAccountingCostManager : public LLSingleton<LLAccountingCostManager>  { +	LLSINGLETON(LLAccountingCostManager); +  public: -	//Ctor -	LLAccountingCostManager();  	//Store an object that will be eventually fetched  	void addObject( const LLUUID& objectID );  	//Request quotas for object list diff --git a/indra/newview/llagentpicksinfo.h b/indra/newview/llagentpicksinfo.h index abf7027ed2..f981e08ff7 100644 --- a/indra/newview/llagentpicksinfo.h +++ b/indra/newview/llagentpicksinfo.h @@ -36,14 +36,12 @@ struct LLAvatarPicks;   */  class LLAgentPicksInfo : public LLSingleton<LLAgentPicksInfo>  { +	LLSINGLETON(LLAgentPicksInfo); +	virtual ~LLAgentPicksInfo(); +  	class LLAgentPicksObserver;  public: - -	LLAgentPicksInfo(); -	 -	virtual ~LLAgentPicksInfo(); -  	/**  	 * Requests number of picks from server.   	 *  diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index b27698fd8f..2710262910 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -38,6 +38,7 @@  #include "llviewerinventory.h"  #include "llavatarappearancedefines.h"  #include "llwearabledata.h" +#include "llinitdestroyclass.h"  class LLInventoryItem;  class LLVOAvatarSelf; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 92e3cd0279..2d84251da0 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -3942,7 +3942,6 @@ LLAppearanceMgr::LLAppearanceMgr():  	mAttachmentInvLinkEnabled(false),  	mOutfitIsDirty(false),  	mOutfitLocked(false), -	mInFlightCounter(0),  	mInFlightTimer(),  	mIsInUpdateAppearanceFromCOF(false),      mOutstandingAppearanceBakeRequest(false), diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index f0d3f80f59..5948dd870c 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -42,9 +42,10 @@ class LLOutfitUnLockTimer;  class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>  { +	LLSINGLETON(LLAppearanceMgr); +	~LLAppearanceMgr();  	LOG_CLASS(LLAppearanceMgr); -	friend class LLSingleton<LLAppearanceMgr>;  	friend class LLOutfitUnLockTimer;  public: @@ -241,10 +242,6 @@ private:      static void debugAppearanceUpdateCOF(const LLSD& content);  	std::string		mAppearanceServiceURL; -	 -protected: -	LLAppearanceMgr(); -	~LLAppearanceMgr();  private: @@ -272,7 +269,6 @@ private:  	 * to avoid unsynchronized outfit state or performing duplicate operations.  	 */  	bool mOutfitLocked; -	S32  mInFlightCounter;  	LLTimer mInFlightTimer;  	static bool mActive; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 9db03a7438..dac1da6ad1 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -233,6 +233,7 @@  #include "llsecapi.h"  #include "llmachineid.h"  #include "llmainlooprepeater.h" +#include "llcleanup.h"  #include "llcoproceduremanager.h"  #include "llviewereventrecorder.h" @@ -387,6 +388,7 @@ const char* const VIEWER_WINDOW_CLASSNAME = "Second Life";   */  class LLDeferredTaskList: public LLSingleton<LLDeferredTaskList>  { +	LLSINGLETON_EMPTY_CTOR(LLDeferredTaskList);  	LOG_CLASS(LLDeferredTaskList);  	friend class LLAppViewer; @@ -737,7 +739,7 @@ LLAppViewer::LLAppViewer()  LLAppViewer::~LLAppViewer()  {  	delete mSettingsLocationList; -	LLViewerEventRecorder::instance().~LLViewerEventRecorder(); +	LLViewerEventRecorder::deleteSingleton();  	LLLoginInstance::instance().setUpdaterService(0); @@ -1743,7 +1745,7 @@ bool LLAppViewer::cleanup()  	gTransferManager.cleanup();  #endif -	LLLocalBitmapMgr::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLLocalBitmapMgr);  	// Note: this is where gWorldMap used to be deleted. @@ -1852,11 +1854,11 @@ bool LLAppViewer::cleanup()  	LLViewerObject::cleanupVOClasses(); -	LLAvatarAppearance::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLAvatarAppearance); -	LLAvatarAppearance::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLAvatarAppearance); -	LLPostProcess::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLPostProcess);  	LLTracker::cleanupInstance(); @@ -1882,12 +1884,12 @@ bool LLAppViewer::cleanup()   	//end_messaging_system(); -	LLFollowCamMgr::cleanupClass(); -	//LLVolumeMgr::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLFollowCamMgr); +	//SUBSYSTEM_CLEANUP(LLVolumeMgr);  	LLPrimitive::cleanupVolumeManager(); -	LLWorldMapView::cleanupClass(); -	LLFolderViewItem::cleanupClass(); -	LLUI::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLWorldMapView); +	SUBSYSTEM_CLEANUP(LLFolderViewItem); +	SUBSYSTEM_CLEANUP(LLUI);  	//  	// Shut down the VFS's AFTER the decode manager cleans up (since it cleans up vfiles). @@ -1896,7 +1898,7 @@ bool LLAppViewer::cleanup()  	//  	LL_INFOS() << "Cleaning up VFS" << LL_ENDL; -	LLVFile::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLVFile);  	LL_INFOS() << "Saving Data" << LL_ENDL; @@ -1999,9 +2001,9 @@ bool LLAppViewer::cleanup()  	// Non-LLCurl libcurl library  	mAppCoreHttp.cleanup(); -	LLFilePickerThread::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLFilePickerThread); -	//MUST happen AFTER LLCurl::cleanupClass +	//MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl)  	delete sTextureCache;      sTextureCache = NULL;  	delete sTextureFetch; @@ -2025,22 +2027,22 @@ bool LLAppViewer::cleanup()  			gDirUtilp->getExpandedFilename(LL_PATH_LOGS, report_name));  	}	 -	LLMetricPerformanceTesterBasic::cleanClass() ; +	SUBSYSTEM_CLEANUP(LLMetricPerformanceTesterBasic) ;  	LL_INFOS() << "Cleaning up Media and Textures" << LL_ENDL;  	//Note: -	//LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown() +	//SUBSYSTEM_CLEANUP(LLViewerMedia) has to be put before gTextureList.shutdown()  	//because some new image might be generated during cleaning up media. --bao -	LLViewerMedia::cleanupClass(); -	LLViewerParcelMedia::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLViewerMedia); +	SUBSYSTEM_CLEANUP(LLViewerParcelMedia);  	gTextureList.shutdown(); // shutdown again in case a callback added something  	LLUIImageList::getInstance()->cleanUp();  	// This should eventually be done in LLAppViewer -	LLImage::cleanupClass(); -	LLVFSThread::cleanupClass(); -	LLLFSThread::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLImage); +	SUBSYSTEM_CLEANUP(LLVFSThread); +	SUBSYSTEM_CLEANUP(LLLFSThread);  #ifndef LL_RELEASE_FOR_DOWNLOAD  	LL_INFOS() << "Auditing VFS" << LL_ENDL; @@ -2083,10 +2085,10 @@ bool LLAppViewer::cleanup()  		LL_INFOS() << "File launched." << LL_ENDL;  	}  	LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL; -	LLProxy::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLProxy);      LLCore::LLHttp::cleanup(); -	LLWearableType::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLWearableType);  	LLMainLoopRepeater::instance().stop(); @@ -2098,10 +2100,34 @@ bool LLAppViewer::cleanup()  	LLError::LLCallStacks::cleanup();  	removeMarkerFiles(); -	 -    LL_INFOS() << "Goodbye!" << LL_ENDL; -    removeDumpDir(); +	// It's not at first obvious where, in this long sequence, generic cleanup +	// calls OUGHT to go. So let's say this: as we migrate cleanup from +	// explicit hand-placed calls into the generic mechanism, eventually +	// all cleanup will get subsumed into the generic calls. So the calls you +	// still see above are calls that MUST happen before the generic cleanup +	// kicks in. +     +	// This calls every remaining LLSingleton's cleanupSingleton() method. +	// This method should perform any cleanup that might take significant +	// realtime, or might throw an exception. +	LLSingletonBase::cleanupAll(); + +	// This calls every remaining LLSingleton's deleteSingleton() method. +	// No class destructor should perform any cleanup that might take +	// significant realtime, or throw an exception. +	// LLSingleton machinery includes a last-gasp implicit deleteAll() call, +	// so this explicit call shouldn't strictly be necessary. However, by the +	// time the runtime engages that implicit call, it may already have +	// destroyed things like std::cerr -- so the implicit deleteAll() refrains +	// from logging anything. Since both cleanupAll() and deleteAll() call +	// their respective cleanup methods in computed dependency order, it's +	// probably useful to be able to log that order. +	LLSingletonBase::deleteAll(); + +	LL_INFOS() << "Goodbye!" << LL_ENDL; + +	removeDumpDir();  	// return 0;  	return true; @@ -5496,9 +5522,12 @@ void LLAppViewer::disconnectViewer()  	}  	saveNameCache(); -    LLExperienceCache *expCache = LLExperienceCache::getIfExists(); -    if (expCache) -        expCache->cleanup(); +	if (LLExperienceCache::instanceExists()) +	{ +		// TODO: LLExperienceCache::cleanup() logic should be moved to +		// cleanupSingleton(). +		LLExperienceCache::instance().cleanup(); +	}  	// close inventory interface, close all windows  	LLFloaterInventory::cleanup(); diff --git a/indra/newview/llattachmentsmgr.h b/indra/newview/llattachmentsmgr.h index bb7d35edbc..a4ef762e8b 100644 --- a/indra/newview/llattachmentsmgr.h +++ b/indra/newview/llattachmentsmgr.h @@ -62,6 +62,9 @@ class LLViewerInventoryItem;  //--------------------------------------------------------------------------------  class LLAttachmentsMgr: public LLSingleton<LLAttachmentsMgr>  { +    LLSINGLETON(LLAttachmentsMgr); +	virtual ~LLAttachmentsMgr(); +  public:      // Stores info for attachments that will be requested during idle.  	struct AttachmentsInfo @@ -72,9 +75,6 @@ public:  	};  	typedef std::deque<AttachmentsInfo> attachments_vec_t; -	LLAttachmentsMgr(); -	virtual ~LLAttachmentsMgr(); -  	void addAttachmentRequest(const LLUUID& item_id,                                const U8 attachment_pt,                                const BOOL add); diff --git a/indra/newview/llautoreplace.h b/indra/newview/llautoreplace.h index 9eecc2d981..23cc313646 100644 --- a/indra/newview/llautoreplace.h +++ b/indra/newview/llautoreplace.h @@ -191,6 +191,7 @@ class LLAutoReplaceSettings   */  class LLAutoReplace : public LLSingleton<LLAutoReplace>  { +    LLSINGLETON(LLAutoReplace);  public:      /// Callback that provides the hook for use in text entry methods      void autoreplaceCallback(S32& replacement_start, S32& replacement_length, LLWString& replacement_string, S32& cursor_pos, const LLWString& input_text); @@ -202,8 +203,6 @@ public:      void setSettings(const LLAutoReplaceSettings& settings);  private: -    friend class LLSingleton<LLAutoReplace>; -    LLAutoReplace();      /*virtual*/ void initSingleton();      LLAutoReplaceSettings mSettings; ///< configuration information diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 7b8c630837..36e95c07f4 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -689,6 +689,8 @@ namespace action_give_inventory  	struct LLShareInfo : public LLSingleton<LLShareInfo>  	{ +		LLSINGLETON_EMPTY_CTOR(LLShareInfo); +	public:  		std::vector<LLAvatarName> mAvatarNames;  		uuid_vec_t mAvatarUuids;  	}; diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h index 5b5720f4ac..a1dacd1a27 100644 --- a/indra/newview/llavatariconctrl.h +++ b/indra/newview/llavatariconctrl.h @@ -37,6 +37,8 @@ class LLAvatarName;  class LLAvatarIconIDCache: public LLSingleton<LLAvatarIconIDCache>  { +	LLSINGLETON(LLAvatarIconIDCache); +  public:  	struct LLAvatarIconIDCacheItem  	{ @@ -46,10 +48,6 @@ public:  		bool expired();  	}; -	LLAvatarIconIDCache() -	:	mFilename("avatar_icons_cache.txt") -	{} -  	void				load	();  	void				save	(); @@ -64,6 +62,11 @@ protected:  	std::map<LLUUID,LLAvatarIconIDCacheItem> mCache;//we cache only LLUID and time  }; +inline +LLAvatarIconIDCache::LLAvatarIconIDCache() +	:	mFilename("avatar_icons_cache.txt") +{} +  namespace LLAvatarIconCtrlEnums  {  	enum ESymbolPos diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h index 1dcd2c9b90..d5c5c75c69 100644 --- a/indra/newview/llavatarpropertiesprocessor.h +++ b/indra/newview/llavatarpropertiesprocessor.h @@ -187,13 +187,12 @@ public:  class LLAvatarPropertiesProcessor  	: public LLSingleton<LLAvatarPropertiesProcessor>  { -public: -	 -	LLAvatarPropertiesProcessor(); +	LLSINGLETON(LLAvatarPropertiesProcessor);  	virtual ~LLAvatarPropertiesProcessor(); +public:  	void addObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer); -	 +  	void removeObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer);  	// Request various types of avatar data.  Duplicate requests will be diff --git a/indra/newview/llavatarrenderinfoaccountant.h b/indra/newview/llavatarrenderinfoaccountant.h index 870ef4f394..6b5fa7bc35 100644 --- a/indra/newview/llavatarrenderinfoaccountant.h +++ b/indra/newview/llavatarrenderinfoaccountant.h @@ -38,13 +38,13 @@ class LLViewerRegion;  // that is sent to or fetched from regions.  class LLAvatarRenderInfoAccountant : public LLSingleton<LLAvatarRenderInfoAccountant>  { +	LLSINGLETON(LLAvatarRenderInfoAccountant); +	~LLAvatarRenderInfoAccountant(); +    private:  	LOG_CLASS(LLAvatarRenderInfoAccountant);    public: -	LLAvatarRenderInfoAccountant(); -	~LLAvatarRenderInfoAccountant(); -  	void sendRenderInfoToRegion(LLViewerRegion * regionp);  	void getRenderInfoFromRegion(LLViewerRegion * regionp); diff --git a/indra/newview/llavatarrendernotifier.h b/indra/newview/llavatarrendernotifier.h index a169baef40..de65bd2e13 100644 --- a/indra/newview/llavatarrendernotifier.h +++ b/indra/newview/llavatarrendernotifier.h @@ -67,9 +67,9 @@ typedef std::list<LLHUDComplexity> hud_complexity_list_t;  // reported that user's agent is too 'heavy' for their settings  class LLAvatarRenderNotifier : public LLSingleton<LLAvatarRenderNotifier>  { -public: -	LLAvatarRenderNotifier(); +	LLSINGLETON(LLAvatarRenderNotifier); +public:      void displayNotification(bool show_over_limit);  	bool isNotificationVisible(); diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h index a5de8a5327..8b9d0dda8b 100644 --- a/indra/newview/llchannelmanager.h +++ b/indra/newview/llchannelmanager.h @@ -43,6 +43,9 @@ namespace LLNotificationsUI   */  class LLChannelManager : public LLSingleton<LLChannelManager>  { +	LLSINGLETON(LLChannelManager); +	virtual ~LLChannelManager(); +  public: @@ -65,9 +68,6 @@ public:  		}  	}; -	LLChannelManager();	 -	virtual ~LLChannelManager(); -  	// On LoginCompleted - show StartUp toast  	void onLoginCompleted();  	// removes a channel intended for the startup toast and allows other channels to show their toasts diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index 254e3f61a8..c4f959bfa9 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -38,7 +38,7 @@ namespace  	const std::string& PANEL_CHICLET_NAME	= "chiclet_list_panel";  } -LLChicletBar::LLChicletBar(const LLSD&) +LLChicletBar::LLChicletBar()  :	mChicletPanel(NULL),  	mToolbarStack(NULL)  { diff --git a/indra/newview/llchicletbar.h b/indra/newview/llchicletbar.h index 956c82cb77..6c521dc1d5 100644 --- a/indra/newview/llchicletbar.h +++ b/indra/newview/llchicletbar.h @@ -38,8 +38,9 @@ class LLChicletBar  	: public LLSingleton<LLChicletBar>  	, public LLPanel  { +	LLSINGLETON(LLChicletBar);  	LOG_CLASS(LLChicletBar); -	friend class LLSingleton<LLChicletBar>; +  public:  	BOOL postBuild(); @@ -82,8 +83,6 @@ private:  	void fitWithTopInfoBar();  protected: -	LLChicletBar(const LLSD& key = LLSD()); -  	LLChicletPanel* 	mChicletPanel;  	LLLayoutStack*		mToolbarStack;  }; diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 62f08144b9..035cbcb945 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -109,7 +109,7 @@ private:  class LLConversationLog : public LLSingleton<LLConversationLog>, LLIMSessionObserver  { -	friend class LLSingleton<LLConversationLog>; +	LLSINGLETON(LLConversationLog);  public:  	void removeConversation(const LLConversation& conversation); @@ -157,7 +157,6 @@ public:  private: -	LLConversationLog();  	virtual ~LLConversationLog()  	{  		if (mAvatarNameCacheConnection.connected()) diff --git a/indra/newview/lldaycyclemanager.h b/indra/newview/lldaycyclemanager.h index 3d2144960d..04db9d5dac 100644 --- a/indra/newview/lldaycyclemanager.h +++ b/indra/newview/lldaycyclemanager.h @@ -40,6 +40,7 @@   */  class LLDayCycleManager : public LLSingleton<LLDayCycleManager>  { +	LLSINGLETON_EMPTY_CTOR(LLDayCycleManager);  	LOG_CLASS(LLDayCycleManager);  public: @@ -66,7 +67,6 @@ public:  	boost::signals2::connection setModifyCallback(const modify_signal_t::slot_type& cb);  private: -	friend class LLSingleton<LLDayCycleManager>;  	/*virtual*/ void initSingleton();  	void loadAllPresets(); diff --git a/indra/newview/lldeferredsounds.h b/indra/newview/lldeferredsounds.h index bf1eb62957..33f02b3521 100644 --- a/indra/newview/lldeferredsounds.h +++ b/indra/newview/lldeferredsounds.h @@ -33,7 +33,7 @@ struct SoundData;  class LLDeferredSounds : public LLSingleton<LLDeferredSounds>  { -private: +	LLSINGLETON_EMPTY_CTOR(LLDeferredSounds);  	std::vector<SoundData> soundVector;  public:  	//Add sounds to be played once progress bar is hidden (such as after teleport or loading screen) diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 7836e2cb94..7d2712eec7 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -69,8 +69,7 @@ BOOL LLDoNotDisturbNotificationStorageTimer::tick()  }  LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage() -	: LLSingleton<LLDoNotDisturbNotificationStorage>() -	, LLNotificationStorage("") +	: LLNotificationStorage("")      , mDirty(false)  {      nameToPayloadParameterMap[toastName] = "SESSION_ID"; diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h index 6e68b0d1be..e6cb7835e3 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.h +++ b/indra/newview/lldonotdisturbnotificationstorage.h @@ -47,14 +47,14 @@ public:  class LLDoNotDisturbNotificationStorage : public LLSingleton<LLDoNotDisturbNotificationStorage>, public LLNotificationStorage  { +	LLSINGLETON(LLDoNotDisturbNotificationStorage); +	~LLDoNotDisturbNotificationStorage(); +  	LOG_CLASS(LLDoNotDisturbNotificationStorage);  public:      static const char * toastName;      static const char * offerName; -	LLDoNotDisturbNotificationStorage(); -	~LLDoNotDisturbNotificationStorage(); -  	void initialize();      bool getDirty();      void resetDirty(); diff --git a/indra/newview/llenvmanager.h b/indra/newview/llenvmanager.h index c7877303fc..6a0a267f4e 100644 --- a/indra/newview/llenvmanager.h +++ b/indra/newview/llenvmanager.h @@ -162,14 +162,13 @@ public:   */  class LLEnvManagerNew : public LLSingleton<LLEnvManagerNew>  { +	LLSINGLETON(LLEnvManagerNew);  	LOG_CLASS(LLEnvManagerNew);  public:  	typedef boost::signals2::signal<void()> prefs_change_signal_t;  	typedef boost::signals2::signal<void()> region_settings_change_signal_t;  	typedef boost::signals2::signal<void(bool)> region_settings_applied_signal_t; -	LLEnvManagerNew(); -  	// getters to access user env. preferences  	bool getUseRegionSettings() const;  	bool getUseDayCycle() const; @@ -231,7 +230,6 @@ public:  	void onRegionSettingsApplyResponse(bool ok);  private: -	friend class LLSingleton<LLEnvManagerNew>;  	/*virtual*/ void initSingleton();  	void loadUserPrefs(); diff --git a/indra/newview/llestateinfomodel.h b/indra/newview/llestateinfomodel.h index fcfbd1ce7d..e7a6a2a725 100644 --- a/indra/newview/llestateinfomodel.h +++ b/indra/newview/llestateinfomodel.h @@ -38,6 +38,7 @@ class LLMessageSystem;   */  class LLEstateInfoModel : public LLSingleton<LLEstateInfoModel>  { +	LLSINGLETON(LLEstateInfoModel);  	LOG_CLASS(LLEstateInfoModel);  public: @@ -73,11 +74,8 @@ public:  protected:  	typedef std::vector<std::string> strings_t; -	friend class LLSingleton<LLEstateInfoModel>;  	friend class LLDispatchEstateUpdateInfo; -	LLEstateInfoModel(); -  	/// refresh model with data from the incoming server message  	void update(const strings_t& strings); diff --git a/indra/newview/llexperiencelog.h b/indra/newview/llexperiencelog.h index ac227db336..09e0cd8821 100644 --- a/indra/newview/llexperiencelog.h +++ b/indra/newview/llexperiencelog.h @@ -33,6 +33,7 @@  class LLExperienceLog : public LLSingleton<LLExperienceLog>  { +	LLSINGLETON(LLExperienceLog);  public:  	typedef boost::signals2::signal<void(LLSD&)>   		callback_signal_t; @@ -62,7 +63,6 @@ public:  	void setEventsToSave(LLSD new_events){mEventsToSave = new_events; }  	bool isNotExpired(std::string& date);  protected: -	LLExperienceLog();  	void handleExperienceMessage(LLSD& message); @@ -81,7 +81,6 @@ protected:  	bool mNotifyNewEvent;  	friend class LLExperienceLogDispatchHandler; -	friend class LLSingleton<LLExperienceLog>;  }; diff --git a/indra/newview/llfacebookconnect.h b/indra/newview/llfacebookconnect.h index 2a2cdb5499..7fd4070f54 100644 --- a/indra/newview/llfacebookconnect.h +++ b/indra/newview/llfacebookconnect.h @@ -43,6 +43,8 @@ class LLEventPump;   */  class LLFacebookConnect : public LLSingleton<LLFacebookConnect>  { +	LLSINGLETON(LLFacebookConnect); +	~LLFacebookConnect() {};  	LOG_CLASS(LLFacebookConnect);  public:      enum EConnectionState @@ -86,10 +88,7 @@ public:      void openFacebookWeb(std::string url);  private: -	friend class LLSingleton<LLFacebookConnect>; -	LLFacebookConnect(); -	~LLFacebookConnect() {};   	std::string getFacebookConnectURL(const std::string& route = "", bool include_read_from_master = false);      EConnectionState mConnectionState; diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 2115f77cf3..cac32c7f2a 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -34,6 +34,7 @@  #include "llinventoryobserver.h"  #include "llinventorymodel.h"  #include "llviewerinventory.h" +#include "llinitdestroyclass.h"  class LLMenuItemCallGL;  class LLToggleableMenu; @@ -173,6 +174,7 @@ private:  class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage>  	, public LLDestroyClass<LLFavoritesOrderStorage>  { +	LLSINGLETON(LLFavoritesOrderStorage);  	LOG_CLASS(LLFavoritesOrderStorage);  public:  	/** @@ -221,10 +223,6 @@ public:  	std::map<LLUUID,std::string> mFavoriteNames;  private: -	friend class LLSingleton<LLFavoritesOrderStorage>; -	LLFavoritesOrderStorage() : mIsDirty(false), mUpdateRequired(false){ load(); } -	~LLFavoritesOrderStorage() {} -      	/**  	 * Removes sort indexes for items which are not in Favorites bar for now.  	 */ @@ -274,4 +272,10 @@ private:  	};  }; + +inline +LLFavoritesOrderStorage::LLFavoritesOrderStorage() : +	mIsDirty(false), mUpdateRequired(false) +{ load(); } +  #endif // LL_LLFAVORITESBARCTRL_H diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h index c3d87cea0b..54bd07329a 100644 --- a/indra/newview/llfeaturemanager.h +++ b/indra/newview/llfeaturemanager.h @@ -97,20 +97,10 @@ protected:  class LLFeatureManager : public LLFeatureList, public LLSingleton<LLFeatureManager>  { -public: -	LLFeatureManager() -	:	LLFeatureList("default"), - -		mInited(FALSE), -		mTableVersion(0), -		mSafe(FALSE), -		mGPUClass(GPU_CLASS_UNKNOWN), -		mExpectedGLVersion(0.f), -		mGPUSupported(FALSE)		 -	{ -	} +	LLSINGLETON(LLFeatureManager);  	~LLFeatureManager() {cleanupFeatureTables();} +public:  	// initialize this by loading feature table and gpu table  	void init(); @@ -181,5 +171,17 @@ protected:  	BOOL		mGPUSupported;  }; +inline +LLFeatureManager::LLFeatureManager() +:	LLFeatureList("default"), + +	mInited(FALSE), +	mTableVersion(0), +	mSafe(FALSE), +	mGPUClass(GPU_CLASS_UNKNOWN), +	mExpectedGLVersion(0.f), +	mGPUSupported(FALSE) +{ +}  #endif // LL_LLFEATUREMANAGER_H diff --git a/indra/newview/llflickrconnect.h b/indra/newview/llflickrconnect.h index 0155804da0..43cadca708 100644 --- a/indra/newview/llflickrconnect.h +++ b/indra/newview/llflickrconnect.h @@ -43,6 +43,8 @@ class LLEventPump;   */  class LLFlickrConnect : public LLSingleton<LLFlickrConnect>  { +	LLSINGLETON(LLFlickrConnect); +	~LLFlickrConnect() {};  	LOG_CLASS(LLFlickrConnect);  public:      enum EConnectionState @@ -80,10 +82,7 @@ public:      void openFlickrWeb(std::string url);  private: -	friend class LLSingleton<LLFlickrConnect>; -	LLFlickrConnect(); -	~LLFlickrConnect() {};   	std::string getFlickrConnectURL(const std::string& route = "", bool include_read_from_master = false);      EConnectionState mConnectionState; diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index e5df417ca9..602d2dce73 100644 --- a/indra/newview/llfloaterbvhpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -992,7 +992,7 @@ void LLFloaterBvhPreview::onBtnOK(void* userdata)  			{  				std::string name = floaterp->getChild<LLUICtrl>("name_form")->getValue().asString();  				std::string desc = floaterp->getChild<LLUICtrl>("description_form")->getValue().asString(); -				S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); +				S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();                  LLResourceUploadInfo::ptr_t assetUpdloadInfo(new LLResourceUploadInfo(                      floaterp->mTransactionID, LLAssetType::AT_ANIMATION, diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 15b67b905d..7039e48e74 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -101,7 +101,7 @@ LLFloaterIMContainer::~LLFloaterIMContainer()  	gSavedPerAccountSettings.setBOOL("ConversationsMessagePaneCollapsed", mMessagesPane->isCollapsed());  	gSavedPerAccountSettings.setBOOL("ConversationsParticipantListCollapsed", !isParticipantListExpanded()); -	if (!LLSingleton<LLIMMgr>::destroyed()) +	if (LLIMMgr::instanceExists())  	{  		LLIMMgr::getInstance()->removeSessionObserver(this);  	} diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp index 4a5732aecf..c9a689281e 100644 --- a/indra/newview/llfloaternamedesc.cpp +++ b/indra/newview/llfloaternamedesc.cpp @@ -123,7 +123,7 @@ BOOL LLFloaterNameDesc::postBuild()  	// Cancel button  	getChild<LLUICtrl>("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnCancel, this)); -	getChild<LLUICtrl>("ok_btn")->setLabelArg("[AMOUNT]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload() )); +	getChild<LLUICtrl>("ok_btn")->setLabelArg("[AMOUNT]", llformat("%d", LLGlobalEconomy::getInstance()->getPriceUpload() ));  	setDefaultBtn("ok_btn"); @@ -162,7 +162,7 @@ void LLFloaterNameDesc::onBtnOK( )  	getChildView("ok_btn")->setEnabled(FALSE); // don't allow inadvertent extra uploads  	LLAssetStorage::LLStoreAssetCallback callback = NULL; -	S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass). +	S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass).      if (can_afford_transaction(expected_upload_cost))      { diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h index ae3800e17b..2fb912a930 100644 --- a/indra/newview/llfriendcard.h +++ b/indra/newview/llfriendcard.h @@ -37,9 +37,10 @@ class LLFriendCardsManager  	: public LLSingleton<LLFriendCardsManager>  	, public LLFriendObserver  { +	LLSINGLETON(LLFriendCardsManager); +	~LLFriendCardsManager();  	LOG_CLASS(LLFriendCardsManager); -	friend class LLSingleton<LLFriendCardsManager>;  	friend class CreateFriendCardCallback;  public: @@ -97,8 +98,6 @@ public:  private:  	typedef boost::function<void()> callback_t; -	LLFriendCardsManager(); -	~LLFriendCardsManager();  	/** diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h index 26a5924ec3..402bdf6039 100644 --- a/indra/newview/llgesturemgr.h +++ b/indra/newview/llgesturemgr.h @@ -51,6 +51,8 @@ public:  class LLGestureMgr : public LLSingleton<LLGestureMgr>, public LLInventoryFetchItemsObserver  { +	LLSINGLETON(LLGestureMgr); +	~LLGestureMgr();  public:  	typedef boost::function<void (LLMultiGesture* loaded_gesture)> gesture_loaded_callback_t; @@ -58,8 +60,6 @@ public:  	typedef std::map<LLUUID, LLMultiGesture*> item_map_t;  	typedef std::map<LLUUID, gesture_loaded_callback_t> callback_map_t; -	LLGestureMgr(); -	~LLGestureMgr();  	void init(); diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index e5ce768035..940ef6eea1 100644 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -348,6 +348,8 @@ struct LLRoleActionSet  class LLGroupMgr : public LLSingleton<LLGroupMgr>  { +	LLSINGLETON(LLGroupMgr); +	~LLGroupMgr();  	LOG_CLASS(LLGroupMgr);  public: @@ -369,8 +371,6 @@ public:  public: -	LLGroupMgr(); -	~LLGroupMgr();  	void addObserver(LLGroupMgrObserver* observer);  	void addObserver(const LLUUID& group_id, LLParticularGroupObserver* observer); diff --git a/indra/newview/llhints.h b/indra/newview/llhints.h index ebffe561b9..dd6195a9ce 100644 --- a/indra/newview/llhints.h +++ b/indra/newview/llhints.h @@ -29,6 +29,7 @@  #include "llpanel.h"  #include "llnotifications.h" +#include "llinitdestroyclass.h"  class LLHints :  public LLInitClass<LLHints> diff --git a/indra/newview/llhudmanager.h b/indra/newview/llhudmanager.h index 9c5d49decd..7782739690 100644 --- a/indra/newview/llhudmanager.h +++ b/indra/newview/llhudmanager.h @@ -36,10 +36,10 @@ class LLMessageSystem;  class LLHUDManager : public LLSingleton<LLHUDManager>  { -public: -	LLHUDManager(); +	LLSINGLETON(LLHUDManager);  	~LLHUDManager(); +public:  	LLHUDEffect *createViewerEffect(const U8 type, BOOL send_to_sim = TRUE, BOOL originated_here = TRUE);  	void updateEffects(); diff --git a/indra/newview/llimagefiltersmanager.h b/indra/newview/llimagefiltersmanager.h index 4751933065..f1ed3cf1c3 100644 --- a/indra/newview/llimagefiltersmanager.h +++ b/indra/newview/llimagefiltersmanager.h @@ -34,6 +34,8 @@  class LLImageFiltersManager : public LLSingleton<LLImageFiltersManager>  { +	LLSINGLETON(LLImageFiltersManager); +	~LLImageFiltersManager();  	LOG_CLASS(LLImageFiltersManager);  public:      const std::vector<std::string> getFiltersList() const; @@ -43,10 +45,7 @@ private:  	void loadAllFilters();  	void loadFiltersFromDir(const std::string& dir); -    friend class LLSingleton<LLImageFiltersManager>;  	/*virtual*/ void initSingleton(); -	LLImageFiltersManager(); -	~LLImageFiltersManager();  	// List of filters : first is the user friendly localized name, second is the xml file name      std::map<std::string,std::string> mFiltersList; diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 41a8813acb..da40ac8393 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -33,6 +33,7 @@  #include "lllogchat.h"  #include "llvoicechannel.h" +#include "llinitdestroyclass.h"  #include "llcoros.h"  #include "lleventcoro.h" @@ -61,6 +62,7 @@ private:   */  class LLIMModel :  public LLSingleton<LLIMModel>  { +	LLSINGLETON(LLIMModel);  public:  	struct LLIMSession : public boost::signals2::trackable @@ -151,7 +153,6 @@ public:  	}; -	LLIMModel();  	/** Session id to session object */  	std::map<LLUUID, LLIMSession*> mId2SessionMap; @@ -312,6 +313,7 @@ public:  class LLIMMgr : public LLSingleton<LLIMMgr>  { +	LLSINGLETON(LLIMMgr);  	friend class LLIMModel;  public: @@ -322,8 +324,6 @@ public:  		INVITATION_TYPE_IMMEDIATE = 2  	}; -	LLIMMgr(); -	virtual ~LLIMMgr() {};  	// Add a message to a session. The session can keyed to sesion id  	// or agent id. diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp index 013a5a7629..495180f087 100644 --- a/indra/newview/llinventoryicon.cpp +++ b/indra/newview/llinventoryicon.cpp @@ -46,8 +46,7 @@ struct IconEntry : public LLDictionaryEntry  class LLIconDictionary : public LLSingleton<LLIconDictionary>,  						 public LLDictionary<LLInventoryType::EIconName, IconEntry>  { -public: -	LLIconDictionary(); +	LLSINGLETON(LLIconDictionary);  };  typedef LLPointer<LLUIImage> LLUIImagePtr; diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index 19fbfc2ed3..00d2908c1b 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -43,9 +43,9 @@  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  class LLInventoryModelBackgroundFetch : public LLSingleton<LLInventoryModelBackgroundFetch>  { -public: -	LLInventoryModelBackgroundFetch(); +	LLSINGLETON(LLInventoryModelBackgroundFetch);  	~LLInventoryModelBackgroundFetch(); +public:  	// Start and stop background breadth-first fetching of inventory contents.  	// This gets triggered when performing a filter-search. diff --git a/indra/newview/lllocationhistory.h b/indra/newview/lllocationhistory.h index 9fef42c5df..1cecbabd3b 100644 --- a/indra/newview/lllocationhistory.h +++ b/indra/newview/lllocationhistory.h @@ -103,6 +103,7 @@ public:  class LLLocationHistory: public LLSingleton<LLLocationHistory>  { +	LLSINGLETON(LLLocationHistory);  	LOG_CLASS(LLLocationHistory);  public: @@ -117,7 +118,6 @@ public:  	typedef boost::function<void(EChangeType event)>			history_changed_callback_t;  	typedef boost::signals2::signal<void(EChangeType event)>	history_changed_signal_t; -	LLLocationHistory();  	void					addItem(const LLLocationHistoryItem& item);  	bool					touchItem(const LLLocationHistoryItem& item); diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 485d4677b1..b9194c6c67 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -132,15 +132,9 @@ void append_to_last_message(std::list<LLSD>& messages, const std::string& line)  class LLLogChatTimeScanner: public LLSingleton<LLLogChatTimeScanner>  { -public: -	LLLogChatTimeScanner() -	{ -		// Note, date/time facets will be destroyed by string streams -		mDateStream.imbue(std::locale(mDateStream.getloc(), new date_input_facet(DATE_FORMAT))); -		mTimeStream.imbue(std::locale(mTimeStream.getloc(), new time_facet(TIME_FORMAT))); -		mTimeStream.imbue(std::locale(mTimeStream.getloc(), new time_input_facet(DATE_FORMAT))); -	} +	LLSINGLETON(LLLogChatTimeScanner); +public:  	date getTodayPacificDate()  	{  		typedef	boost::date_time::local_adjustor<ptime, -8, no_dst> pst; @@ -205,6 +199,15 @@ private:  	std::stringstream mTimeStream;  }; +inline +LLLogChatTimeScanner::LLLogChatTimeScanner() +{ +	// Note, date/time facets will be destroyed by string streams +	mDateStream.imbue(std::locale(mDateStream.getloc(), new date_input_facet(DATE_FORMAT))); +	mTimeStream.imbue(std::locale(mTimeStream.getloc(), new time_facet(TIME_FORMAT))); +	mTimeStream.imbue(std::locale(mTimeStream.getloc(), new time_input_facet(DATE_FORMAT))); +} +  LLLogChat::save_history_signal_t * LLLogChat::sSaveHistorySignal = NULL;  std::map<LLUUID,LLLoadHistoryThread *> LLLogChat::sLoadHistoryThreads; diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index c6773bbf68..282ddc1cea 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -40,12 +40,12 @@ class LLUpdaterService;  // negotiate user authentication attempts.  class LLLoginInstance : public LLSingleton<LLLoginInstance>  { +	LLSINGLETON(LLLoginInstance); +	~LLLoginInstance(); +  public:  	class Disposable; -	LLLoginInstance(); -	~LLLoginInstance(); -  	void connect(LLPointer<LLCredential> credentials); // Connect to the current grid choice.  	void connect(const std::string& uri, LLPointer<LLCredential> credentials);	// Connect to the given uri.  	void reconnect(); // reconnect using the current credentials. diff --git a/indra/newview/llmainlooprepeater.h b/indra/newview/llmainlooprepeater.h index f84c0ca94c..2ec3a74e4a 100644 --- a/indra/newview/llmainlooprepeater.h +++ b/indra/newview/llmainlooprepeater.h @@ -43,9 +43,8 @@  class LLMainLoopRepeater:  	public LLSingleton<LLMainLoopRepeater>  { +	LLSINGLETON(LLMainLoopRepeater);  public: -	LLMainLoopRepeater(void); -	  	// Start the repeater service.  	void start(void); diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h index 9d795c6ced..ec312baca3 100644 --- a/indra/newview/llmarketplacefunctions.h +++ b/indra/newview/llmarketplacefunctions.h @@ -86,11 +86,10 @@ namespace MarketplaceFetchCodes  class LLMarketplaceInventoryImporter  	: public LLSingleton<LLMarketplaceInventoryImporter>  { +	LLSINGLETON(LLMarketplaceInventoryImporter);  public:  	static void update(); -	 -	LLMarketplaceInventoryImporter(); -	 +  	typedef boost::signals2::signal<void (bool)> status_changed_signal_t;  	typedef boost::signals2::signal<void (U32, const LLSD&)> status_report_signal_t; @@ -181,10 +180,11 @@ class LLSLMDeleteListingsResponder;  class LLMarketplaceData      : public LLSingleton<LLMarketplaceData>  { -    friend class LLSingleton < LLMarketplaceData > ; +    LLSINGLETON(LLMarketplaceData); +    virtual ~LLMarketplaceData();  public: -	friend class LLSLMGetMerchantResponder; +    friend class LLSLMGetMerchantResponder;      friend class LLSLMGetListingsResponder;      friend class LLSLMCreateListingsResponder;      friend class LLSLMGetListingResponder; @@ -242,9 +242,6 @@ public:      void decrementValidationWaiting(const LLUUID& folder_id, S32 count = 1);  private: -    LLMarketplaceData(); -    virtual ~LLMarketplaceData(); -      // Modify Marketplace data set  : each method returns true if the function succeeds, false if error      // Used internally only by SLM Responders when data are received from the SLM Server      bool addListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, const std::string& edit_url, S32 count); diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h index 36dd0904b6..60b58d17de 100644 --- a/indra/newview/llmaterialmgr.h +++ b/indra/newview/llmaterialmgr.h @@ -38,9 +38,7 @@ class LLViewerRegion;  class LLMaterialMgr : public LLSingleton<LLMaterialMgr>  { -	friend class LLSingleton<LLMaterialMgr>; -protected: -	LLMaterialMgr(); +	LLSINGLETON(LLMaterialMgr);  	virtual ~LLMaterialMgr();  public: diff --git a/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp b/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp index 8879cfd7fb..63d97f6ac2 100644 --- a/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp +++ b/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp @@ -41,8 +41,7 @@  #include "llpathfindingnavmeshstatus.h"  #include "llviewerregion.h" -LLMenuOptionPathfindingRebakeNavmesh::LLMenuOptionPathfindingRebakeNavmesh()  -	: LLSingleton<LLMenuOptionPathfindingRebakeNavmesh>(), +LLMenuOptionPathfindingRebakeNavmesh::LLMenuOptionPathfindingRebakeNavmesh() :  	mIsInitialized(false),  	mCanRebakeRegion(false),  	mRebakeNavMeshMode(kRebakeNavMesh_Default), diff --git a/indra/newview/llmenuoptionpathfindingrebakenavmesh.h b/indra/newview/llmenuoptionpathfindingrebakenavmesh.h index 7b1d2873ba..649a387dd3 100644 --- a/indra/newview/llmenuoptionpathfindingrebakenavmesh.h +++ b/indra/newview/llmenuoptionpathfindingrebakenavmesh.h @@ -37,6 +37,8 @@ class LLPathfindingNavMeshStatus;  class LLMenuOptionPathfindingRebakeNavmesh : public LLSingleton<LLMenuOptionPathfindingRebakeNavmesh>  { +	LLSINGLETON(LLMenuOptionPathfindingRebakeNavmesh); +	virtual ~LLMenuOptionPathfindingRebakeNavmesh();  	LOG_CLASS(LLMenuOptionPathfindingRebakeNavmesh);  public: @@ -49,8 +51,6 @@ public:  		kRebakeNavMesh_Default = kRebakeNavMesh_NotAvailable  	} ERebakeNavMeshMode; -	LLMenuOptionPathfindingRebakeNavmesh(); -	virtual ~LLMenuOptionPathfindingRebakeNavmesh();  	void               initialize();  	void               quit(); diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index 84cf7d0313..0f70c9d13f 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -47,6 +47,7 @@  #include "pipeline.h"  #include <boost/tokenizer.hpp> +#include <boost/bind.hpp>  #include "lldispatcher.h"  #include "llxfermanager.h" @@ -147,22 +148,6 @@ std::string LLMute::getDisplayType() const  	}  } - -/* static */ -LLMuteList* LLMuteList::getInstance() -{ -	// Register callbacks at the first time that we find that the message system has been created. -	static BOOL registered = FALSE; -	if( !registered && gMessageSystem != NULL) -	{ -		registered = TRUE; -		// Register our various callbacks -		gMessageSystem->setHandlerFuncFast(_PREHASH_MuteListUpdate, processMuteListUpdate); -		gMessageSystem->setHandlerFuncFast(_PREHASH_UseCachedMuteList, processUseCachedMuteList); -	} -	return LLSingleton<LLMuteList>::getInstance(); // Call the "base" implementation. -} -  //-----------------------------------------------------------------------------  // LLMuteList()  //----------------------------------------------------------------------------- @@ -170,6 +155,18 @@ LLMuteList::LLMuteList() :  	mIsLoaded(FALSE)  {  	gGenericDispatcher.addHandler("emptymutelist", &sDispatchEmptyMuteList); + +	// Register our callbacks. We may be constructed before gMessageSystem, so +	// use callWhenReady() to register them as soon as gMessageSystem becomes +	// available. +	// When using bind(), must be explicit about default arguments such as +	// that last NULL. +	gMessageSystem.callWhenReady(boost::bind(&LLMessageSystem::setHandlerFuncFast, _1, +											 _PREHASH_MuteListUpdate, processMuteListUpdate, +											 static_cast<void**>(NULL))); +	gMessageSystem.callWhenReady(boost::bind(&LLMessageSystem::setHandlerFuncFast, _1, +											 _PREHASH_UseCachedMuteList, processUseCachedMuteList, +											 static_cast<void**>(NULL)));  }  //----------------------------------------------------------------------------- diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index 4e7b6ee880..4ceddc97fd 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -71,6 +71,8 @@ public:  class LLMuteList : public LLSingleton<LLMuteList>  { +	LLSINGLETON(LLMuteList); +	~LLMuteList();  public:  	// reasons for auto-unmuting a resident  	enum EAutoReason  @@ -81,13 +83,6 @@ public:  		AR_COUNT			// enum count  	}; -	LLMuteList(); -	~LLMuteList(); - -	// Implemented locally so that we can perform some delayed initialization.  -	// Callers should be careful to call this one and not LLSingleton<LLMuteList>::getInstance() -	// which would circumvent that mechanism. -MG -	static LLMuteList* getInstance();  	void addObserver(LLMuteListObserver* observer);  	void removeObserver(LLMuteListObserver* observer); diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h index 29dbaedf7a..a44c6dd699 100644..100755 --- a/indra/newview/llnavigationbar.h +++ b/indra/newview/llnavigationbar.h @@ -30,6 +30,7 @@  #include "llpanel.h"  #include "llbutton.h"  #include "lllayoutstack.h" +#include "llinitdestroyclass.h"  class LLLocationInputCtrl;  class LLMenuGL; @@ -84,12 +85,12 @@ protected:  class LLNavigationBar  	:	public LLPanel, public LLSingleton<LLNavigationBar>, private LLDestroyClass<LLNavigationBar>  { +	LLSINGLETON(LLNavigationBar); +	virtual ~LLNavigationBar();  	LOG_CLASS(LLNavigationBar);  	friend class LLDestroyClass<LLNavigationBar>; -	 +  public: -	LLNavigationBar(); -	virtual ~LLNavigationBar();  	/*virtual*/ void	draw();  	/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h index f37c6b833c..52c79cc689 100644 --- a/indra/newview/llnotificationmanager.h +++ b/indra/newview/llnotificationmanager.h @@ -46,11 +46,11 @@ class LLToast;   */  class LLNotificationManager : public LLSingleton<LLNotificationManager>  { -	typedef std::pair<std::string, LLEventHandler*> eventhandlers; -public:	 -	LLNotificationManager();	 +	LLSINGLETON(LLNotificationManager);  	virtual ~LLNotificationManager(); +	typedef std::pair<std::string, LLEventHandler*> eventhandlers; +public:  	//TODO: make private  	// this method initialize handlers' map for different types of notifications  	void init(void); diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index 3418b33d37..35fdfa88bb 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -45,9 +45,10 @@ typedef boost::function<LLNotificationResponderInterface * (const LLSD& pParams)  class LLResponderRegistry : public LLRegistrySingleton<std::string, responder_constructor_t, LLResponderRegistry>  { -    public: -        template<typename RESPONDER_TYPE> static LLNotificationResponderInterface * create(const LLSD& pParams); -        LLNotificationResponderInterface * createResponder(const std::string& pNotificationName, const LLSD& pParams); +    LLSINGLETON_EMPTY_CTOR(LLResponderRegistry); +public: +    template<typename RESPONDER_TYPE> static LLNotificationResponderInterface * create(const LLSD& pParams); +    LLNotificationResponderInterface * createResponder(const std::string& pNotificationName, const LLSD& pParams);  };  template<typename RESPONDER_TYPE> LLNotificationResponderInterface * LLResponderRegistry::create(const LLSD& pParams) diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index bc1e2c5d59..8887a61857 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -1126,7 +1126,7 @@ void LLOutfitGallery::uploadPhoto(LLUUID outfit_id)                  return;              } -            S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass). +            S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass).              void *nruserdata = NULL;              nruserdata = (void *)&outfit_id; diff --git a/indra/newview/lloutfitobserver.h b/indra/newview/lloutfitobserver.h index 87d4b0c998..77041db68d 100644 --- a/indra/newview/lloutfitobserver.h +++ b/indra/newview/lloutfitobserver.h @@ -36,10 +36,10 @@   */  class LLOutfitObserver: public LLInventoryObserver, public LLSingleton<LLOutfitObserver>  { -public: +	LLSINGLETON(LLOutfitObserver);  	virtual ~LLOutfitObserver(); -	friend class LLSingleton<LLOutfitObserver>; +public:  	virtual void changed(U32 mask); @@ -58,7 +58,6 @@ public:  	void addOutfitLockChangedCallback(const signal_t::slot_type& cb) { mOutfitLockChanged.connect(cb); }  protected: -	LLOutfitObserver();  	/** Get a version of an inventory category specified by its UUID */  	static S32 getCategoryVersion(const LLUUID& cat_id); diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index b7e1b2d3a4..f2d43a1037 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -117,8 +117,7 @@ class LLEditWearableDictionary : public LLSingleton<LLEditWearableDictionary>          //--------------------------------------------------------------------          // Constructors and Destructors          //-------------------------------------------------------------------- -public: -        LLEditWearableDictionary(); +        LLSINGLETON(LLEditWearableDictionary);          virtual ~LLEditWearableDictionary();          //-------------------------------------------------------------------- diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index eb40616a9c..211cb32c01 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -1309,7 +1309,7 @@ void LLPanelMainInventory::setUploadCostIfNeeded()  		LLMenuItemBranchGL* upload_menu = menu->findChild<LLMenuItemBranchGL>("upload");  		if(upload_menu)  		{ -			S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); +			S32 upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();  			std::string cost_str;  			// getPriceUpload() returns -1 if no data available yet. diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp index b2952834fb..21ac7604ff 100644 --- a/indra/newview/llpanelsnapshotinventory.cpp +++ b/indra/newview/llpanelsnapshotinventory.cpp @@ -135,7 +135,7 @@ BOOL LLPanelSnapshotInventory::postBuild()  // virtual  void LLPanelSnapshotInventory::onOpen(const LLSD& key)  { -	getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload())); +	getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::getInstance()->getPriceUpload()));  	LLPanelSnapshot::onOpen(key);  } @@ -155,7 +155,7 @@ void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl)  void LLPanelSnapshotInventoryBase::onSend()  { -    S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); +    S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();      if (can_afford_transaction(expected_upload_cost))      {          if (mSnapshotFloater) @@ -191,7 +191,7 @@ BOOL LLPanelOutfitSnapshotInventory::postBuild()  // virtual  void LLPanelOutfitSnapshotInventory::onOpen(const LLSD& key)  { -    getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload())); +    getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::getInstance()->getPriceUpload()));      LLPanelSnapshot::onOpen(key);  } diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp index 269f16c5e4..95c14e4226 100644 --- a/indra/newview/llpanelsnapshotoptions.cpp +++ b/indra/newview/llpanelsnapshotoptions.cpp @@ -77,12 +77,12 @@ LLPanelSnapshotOptions::LLPanelSnapshotOptions()  	mCommitCallbackRegistrar.add("Snapshot.SendToFacebook",		boost::bind(&LLPanelSnapshotOptions::onSendToFacebook, this));  	mCommitCallbackRegistrar.add("Snapshot.SendToTwitter",		boost::bind(&LLPanelSnapshotOptions::onSendToTwitter, this));  	mCommitCallbackRegistrar.add("Snapshot.SendToFlickr",		boost::bind(&LLPanelSnapshotOptions::onSendToFlickr, this)); -	LLGlobalEconomy::Singleton::getInstance()->addObserver(this); +	LLGlobalEconomy::getInstance()->addObserver(this);  }  LLPanelSnapshotOptions::~LLPanelSnapshotOptions()  { -	LLGlobalEconomy::Singleton::getInstance()->removeObserver(this); +	LLGlobalEconomy::getInstance()->removeObserver(this);  }  // virtual @@ -100,7 +100,7 @@ void LLPanelSnapshotOptions::onOpen(const LLSD& key)  void LLPanelSnapshotOptions::updateUploadCost()  { -	S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); +	S32 upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();  	getChild<LLUICtrl>("save_to_inventory_btn")->setLabelArg("[AMOUNT]", llformat("%d", upload_cost));  } diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 3de9dc2f80..fe0608d544 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -104,7 +104,9 @@ private:  ////////////////////////////////////////////////////////////////////////////////  //////////////////////////////////////////////////////////////////////////////// -class LLTeleportHistoryFlatItemStorage: public LLSingleton<LLTeleportHistoryFlatItemStorage> { +class LLTeleportHistoryFlatItemStorage: public LLSingleton<LLTeleportHistoryFlatItemStorage> +{ +	LLSINGLETON_EMPTY_CTOR(LLTeleportHistoryFlatItemStorage);  protected:  	typedef std::vector< LLHandle<LLTeleportHistoryFlatItem> > flat_item_list_t; diff --git a/indra/newview/llpaneltopinfobar.h b/indra/newview/llpaneltopinfobar.h index f37bd9c048..78dd997029 100644 --- a/indra/newview/llpaneltopinfobar.h +++ b/indra/newview/llpaneltopinfobar.h @@ -28,6 +28,7 @@  #define LLPANELTOPINFOBAR_H_  #include "llpanel.h" +#include "llinitdestroyclass.h"  class LLButton;  class LLTextBox; @@ -36,6 +37,8 @@ class LLParcelChangeObserver;  class LLPanelTopInfoBar : public LLPanel, public LLSingleton<LLPanelTopInfoBar>, private LLDestroyClass<LLPanelTopInfoBar>  { +	LLSINGLETON(LLPanelTopInfoBar); +	~LLPanelTopInfoBar();  	LOG_CLASS(LLPanelTopInfoBar);  	friend class LLDestroyClass<LLPanelTopInfoBar>; @@ -43,9 +46,6 @@ class LLPanelTopInfoBar : public LLPanel, public LLSingleton<LLPanelTopInfoBar>,  public:  	typedef boost::signals2::signal<void ()> resize_signal_t; -	LLPanelTopInfoBar(); -	~LLPanelTopInfoBar(); -  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void draw(); diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp index 711a869e82..cb4c07a417 100644 --- a/indra/newview/llpathfindingmanager.cpp +++ b/indra/newview/llpathfindingmanager.cpp @@ -144,8 +144,7 @@ typedef boost::shared_ptr<LinksetsResponder> LinksetsResponderPtr;  // LLPathfindingManager  //--------------------------------------------------------------------------- -LLPathfindingManager::LLPathfindingManager() -	: LLSingleton<LLPathfindingManager>(), +LLPathfindingManager::LLPathfindingManager():  	mNavMeshMap(),  	mAgentStateSignal()  { diff --git a/indra/newview/llpathfindingmanager.h b/indra/newview/llpathfindingmanager.h index e8fad590ba..a44cd892da 100644 --- a/indra/newview/llpathfindingmanager.h +++ b/indra/newview/llpathfindingmanager.h @@ -48,6 +48,9 @@ class LinksetsResponder;  class LLPathfindingManager : public LLSingleton<LLPathfindingManager>  { +	LLSINGLETON(LLPathfindingManager); +	virtual ~LLPathfindingManager(); +  	friend class LLNavMeshSimStateChangeNode;  	friend class NavMeshStatusResponder;  	friend class LLAgentStateChangeNode; @@ -60,9 +63,6 @@ public:  		kRequestError  	} ERequestStatus; -	LLPathfindingManager(); -	virtual ~LLPathfindingManager(); -  	void initSystem();  	void quitSystem(); diff --git a/indra/newview/llpathfindingpathtool.cpp b/indra/newview/llpathfindingpathtool.cpp index 006755e20b..3187325101 100644 --- a/indra/newview/llpathfindingpathtool.cpp +++ b/indra/newview/llpathfindingpathtool.cpp @@ -46,7 +46,6 @@  LLPathfindingPathTool::LLPathfindingPathTool()  	: LLTool(PATH_TOOL_NAME), -	LLSingleton<LLPathfindingPathTool>(),  	mFinalPathData(),  	mTempPathData(),  	mPathResult(LLPathingLib::LLPL_NO_PATH), diff --git a/indra/newview/llpathfindingpathtool.h b/indra/newview/llpathfindingpathtool.h index 97284265f1..88cb3a15f8 100644 --- a/indra/newview/llpathfindingpathtool.h +++ b/indra/newview/llpathfindingpathtool.h @@ -36,6 +36,9 @@  class LLPathfindingPathTool : public LLTool, public LLSingleton<LLPathfindingPathTool>  { +	LLSINGLETON(LLPathfindingPathTool); +	virtual ~LLPathfindingPathTool(); +  public:  	typedef enum  	{ @@ -59,9 +62,6 @@ public:  		kCharacterTypeD  	} ECharacterType; -	LLPathfindingPathTool(); -	virtual ~LLPathfindingPathTool(); -  	typedef boost::function<void (void)>         path_event_callback_t;  	typedef boost::signals2::signal<void (void)> path_event_signal_t;  	typedef boost::signals2::connection          path_event_slot_t; diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp index 9c0222d0bc..264382ae82 100644 --- a/indra/newview/llpersistentnotificationstorage.cpp +++ b/indra/newview/llpersistentnotificationstorage.cpp @@ -36,9 +36,8 @@  #include "llscriptfloater.h"  #include "llviewermessage.h"  #include "llviewernetwork.h" -LLPersistentNotificationStorage::LLPersistentNotificationStorage() -	: LLSingleton<LLPersistentNotificationStorage>() -	, LLNotificationStorage("") +LLPersistentNotificationStorage::LLPersistentNotificationStorage(): +	  LLNotificationStorage("")  	, mLoaded(false)  {  } diff --git a/indra/newview/llpersistentnotificationstorage.h b/indra/newview/llpersistentnotificationstorage.h index bf0306380e..40c9923c74 100644 --- a/indra/newview/llpersistentnotificationstorage.h +++ b/indra/newview/llpersistentnotificationstorage.h @@ -45,10 +45,10 @@ class LLSD;  class LLPersistentNotificationStorage : public LLSingleton<LLPersistentNotificationStorage>, public LLNotificationStorage  { +	LLSINGLETON(LLPersistentNotificationStorage); +	~LLPersistentNotificationStorage();  	LOG_CLASS(LLPersistentNotificationStorage);  public: -	LLPersistentNotificationStorage(); -	~LLPersistentNotificationStorage();  	void saveNotifications();  	void loadNotifications(); diff --git a/indra/newview/llpresetsmanager.h b/indra/newview/llpresetsmanager.h index 21f9885f27..0014e32267 100644 --- a/indra/newview/llpresetsmanager.h +++ b/indra/newview/llpresetsmanager.h @@ -46,6 +46,9 @@ enum EDefaultOptions  class LLPresetsManager : public LLSingleton<LLPresetsManager>  { +	LLSINGLETON(LLPresetsManager); +	~LLPresetsManager(); +  public:  	typedef std::list<std::string> preset_name_list_t; @@ -67,9 +70,6 @@ public:  	preset_name_list_t mPresetNames; -	LLPresetsManager(); -	~LLPresetsManager(); -  	preset_list_signal_t mPresetListChangeSignal;    private: diff --git a/indra/newview/llproductinforequest.h b/indra/newview/llproductinforequest.h index 75dbf220d1..d1036374e8 100644 --- a/indra/newview/llproductinforequest.h +++ b/indra/newview/llproductinforequest.h @@ -41,12 +41,11 @@   */  class LLProductInfoRequestManager : public LLSingleton<LLProductInfoRequestManager>  { +	LLSINGLETON(LLProductInfoRequestManager);  public: -	LLProductInfoRequestManager();  	std::string getDescriptionForSku(const std::string& sku);  private: -	friend class LLSingleton<LLProductInfoRequestManager>;	  	/* virtual */ void initSingleton();      void getLandDescriptionsCoro(std::string url); diff --git a/indra/newview/llrecentpeople.h b/indra/newview/llrecentpeople.h index d0d6376867..c7aaf604f5 100644 --- a/indra/newview/llrecentpeople.h +++ b/indra/newview/llrecentpeople.h @@ -50,6 +50,7 @@ class LLDate;   */  class LLRecentPeople: public LLSingleton<LLRecentPeople>, public LLOldEvents::LLSimpleListener  { +	LLSINGLETON_EMPTY_CTOR(LLRecentPeople);  	LOG_CLASS(LLRecentPeople);  public:  	typedef boost::signals2::signal<void ()> signal_t; diff --git a/indra/newview/llregioninfomodel.h b/indra/newview/llregioninfomodel.h index d22a0de463..ea9640efda 100644 --- a/indra/newview/llregioninfomodel.h +++ b/indra/newview/llregioninfomodel.h @@ -36,6 +36,7 @@ class LLMessageSystem;   */  class LLRegionInfoModel : public LLSingleton<LLRegionInfoModel>  { +	LLSINGLETON(LLRegionInfoModel);  	LOG_CLASS(LLRegionInfoModel);  public: @@ -73,10 +74,8 @@ public:  	std::string	mSimType;  protected: -	friend class LLSingleton<LLRegionInfoModel>;  	friend class LLViewerRegion; -	LLRegionInfoModel();  	/**  	 * Refresh model with data from the incoming server message. diff --git a/indra/newview/llremoteparcelrequest.h b/indra/newview/llremoteparcelrequest.h index cb5af50c5f..5b0d189137 100644 --- a/indra/newview/llremoteparcelrequest.h +++ b/indra/newview/llremoteparcelrequest.h @@ -74,9 +74,10 @@ protected:  class LLRemoteParcelInfoProcessor : public LLSingleton<LLRemoteParcelInfoProcessor>  { -public: +	LLSINGLETON_EMPTY_CTOR(LLRemoteParcelInfoProcessor);  	virtual ~LLRemoteParcelInfoProcessor() {} +public:  	void addObserver(const LLUUID& parcel_id, LLRemoteParcelInfoObserver* observer);  	void removeObserver(const LLUUID& parcel_id, LLRemoteParcelInfoObserver* observer); diff --git a/indra/newview/llrootview.h b/indra/newview/llrootview.h index 5223a314f3..2ac958e7b8 100644 --- a/indra/newview/llrootview.h +++ b/indra/newview/llrootview.h @@ -32,7 +32,9 @@  #include "lltooltip.h"  class LLRootViewRegistry : public LLChildRegistry<LLRootViewRegistry> -{}; +{ +	LLSINGLETON(LLRootViewRegistry); +};  class LLRootView : public LLView  { diff --git a/indra/newview/llscenemonitor.h b/indra/newview/llscenemonitor.h index 2b6ea57b96..7cd531bd34 100644 --- a/indra/newview/llscenemonitor.h +++ b/indra/newview/llscenemonitor.h @@ -39,10 +39,10 @@ class LLViewerTexture;  class LLSceneMonitor : public LLSingleton<LLSceneMonitor>  { +	LLSINGLETON(LLSceneMonitor); +	~LLSceneMonitor();  	LOG_CLASS(LLSceneMonitor);  public: -	LLSceneMonitor(); -	~LLSceneMonitor();  	void freezeAvatar(LLCharacter* avatarp);  	void setDebugViewerVisible(bool visible); diff --git a/indra/newview/llscriptfloater.h b/indra/newview/llscriptfloater.h index 70451194b3..c0b84abdcb 100644 --- a/indra/newview/llscriptfloater.h +++ b/indra/newview/llscriptfloater.h @@ -41,6 +41,7 @@ class LLScriptFloaterManager : public LLSingleton<LLScriptFloaterManager>  	// *TODO  	// LLScriptFloaterManager and LLScriptFloater will need some refactoring after we   	// know how script notifications should look like. +	LLSINGLETON_EMPTY_CTOR(LLScriptFloaterManager);  public:  	typedef enum e_object_type diff --git a/indra/newview/llsearchhistory.h b/indra/newview/llsearchhistory.h index 3309a8fcac..5aab5e6765 100644 --- a/indra/newview/llsearchhistory.h +++ b/indra/newview/llsearchhistory.h @@ -28,6 +28,7 @@  #define LL_LLSEARCHHISTORY_H  #include "llsingleton.h" +#include "llinitdestroyclass.h"  #include "llui.h"  /** @@ -36,6 +37,7 @@   */  class LLSearchHistory : public LLSingleton<LLSearchHistory>, private LLDestroyClass<LLSearchHistory>  { +	LLSINGLETON(LLSearchHistory);  	friend class LLDestroyClass<LLSearchHistory>;  public: @@ -71,7 +73,6 @@ public:  	 */  	void addEntry(const std::string& search_text); -	LLSearchHistory();  	/**  	 * Class for storing data about single search request. diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index bc50e443f8..c167ecd236 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -388,6 +388,9 @@ struct LLSelectGetFirstTest;  class LLSelectMgr : public LLEditMenuHandler, public LLSingleton<LLSelectMgr>  { +	LLSINGLETON(LLSelectMgr); +	~LLSelectMgr(); +  public:  	static BOOL					sRectSelectInclusive;	// do we need to surround an object to pick it?  	static BOOL					sRenderHiddenSelections;	// do we show selection silhouettes that are occluded? @@ -413,9 +416,6 @@ public:  	LLCachedControl<bool>					mDebugSelectMgr;  public: -	LLSelectMgr(); -	~LLSelectMgr(); -  	static void cleanupGlobals();  	// LLEditMenuHandler interface diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 0b5c4eb9ae..58e48480c1 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -1036,7 +1036,7 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name)  		LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL);  		std::string who_took_it;  		LLAgentUI::buildFullname(who_took_it); -		S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); +		S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();          std::string res_name = outfit_snapshot ? name : "Snapshot : " + pos_string;          std::string res_desc = outfit_snapshot ? "" : "Taken by " + who_took_it + " at " + pos_string;          LLFolderType::EType folder_type = outfit_snapshot ? LLFolderType::FT_NONE : LLFolderType::FT_SNAPSHOT_CATEGORY; diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index 5cff70f377..617bae3984 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -341,20 +341,18 @@ protected:  class LLActiveSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLActiveSpeakerMgr>  { +	LLSINGLETON(LLActiveSpeakerMgr);  	LOG_CLASS(LLActiveSpeakerMgr); -public: -	LLActiveSpeakerMgr();  protected:  	virtual void updateSpeakerList();  };  class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLLocalSpeakerMgr>  { -	LOG_CLASS(LLLocalSpeakerMgr); -public: -	LLLocalSpeakerMgr(); +	LLSINGLETON(LLLocalSpeakerMgr);  	~LLLocalSpeakerMgr (); +	LOG_CLASS(LLLocalSpeakerMgr);  protected:  	virtual void updateSpeakerList();  }; diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index 78fe7863c8..5ca1d4b4a5 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -48,6 +48,8 @@   */  class SpeakingIndicatorManager : public LLSingleton<SpeakingIndicatorManager>, LLVoiceClientParticipantObserver  { +	LLSINGLETON(SpeakingIndicatorManager); +	~SpeakingIndicatorManager();  	LOG_CLASS(SpeakingIndicatorManager);  public: @@ -91,10 +93,6 @@ private:  	typedef speaking_indicators_mmap_t::const_iterator indicator_const_iterator;  	typedef std::pair<indicator_const_iterator, indicator_const_iterator> indicator_range_t; -	friend class LLSingleton<SpeakingIndicatorManager>; -	SpeakingIndicatorManager(); -	~SpeakingIndicatorManager(); -  	/**  	 * Callback to determine when voice channel is changed.  	 * diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 4e81d78455..1bc20ccf12 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -193,6 +193,7 @@  #include "llstartuplistener.h"  #include "lltoolbarview.h"  #include "llexperiencelog.h" +#include "llcleanup.h"  #if LL_WINDOWS  #include "lldxhardware.h" @@ -2808,7 +2809,7 @@ void LLStartUp::initExperiences()  void LLStartUp::cleanupNameCache()  { -	LLAvatarNameCache::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLAvatarNameCache);  	delete gCacheName;  	gCacheName = NULL; diff --git a/indra/newview/llstylemap.h b/indra/newview/llstylemap.h index 8aa0af535c..96b3920593 100644 --- a/indra/newview/llstylemap.h +++ b/indra/newview/llstylemap.h @@ -39,6 +39,7 @@ typedef std::map<LLUUID, LLStyle::Params> style_map_t;  class LLStyleMap : public LLSingleton<LLStyleMap>  { +	LLSINGLETON_EMPTY_CTOR(LLStyleMap);  public:  	// Just like the [] accessor but it will add the entry in if it doesn't exist.  	const LLStyle::Params &lookupAgent(const LLUUID &source);  diff --git a/indra/newview/llsyntaxid.h b/indra/newview/llsyntaxid.h index 0afa6dc04b..1360b3e042 100644 --- a/indra/newview/llsyntaxid.h +++ b/indra/newview/llsyntaxid.h @@ -38,9 +38,9 @@ class fetchKeywordsFileResponder;  class LLSyntaxIdLSL : public LLSingleton<LLSyntaxIdLSL>  { -	friend class LLSingleton<LLSyntaxIdLSL>; +	LLSINGLETON(LLSyntaxIdLSL);  	friend class fetchKeywordsFileResponder; -	 +  private:      std::set<std::string> mInflightFetches;  	typedef boost::signals2::signal<void()> syntax_id_changed_signal_t; @@ -67,7 +67,6 @@ private:  	LLSD			mKeywordsXml;  public: -	LLSyntaxIdLSL();  	void initialize();  	bool keywordFetchInProgress();  	LLSD getKeywordsXML() const { return mKeywordsXml; }; diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index d02293e6ff..b96a2573a1 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -32,6 +32,7 @@  #include "llscreenchannel.h"  #include "llsyswellitem.h"  #include "lltransientdockablefloater.h" +#include "llinitdestroyclass.h"  class LLAvatarName;  class LLChiclet; diff --git a/indra/newview/llteleporthistory.h b/indra/newview/llteleporthistory.h index e9c29c39bf..db0ccdda59 100644 --- a/indra/newview/llteleporthistory.h +++ b/indra/newview/llteleporthistory.h @@ -73,6 +73,8 @@ public:   */  class LLTeleportHistory: public LLSingleton<LLTeleportHistory>  { +	LLSINGLETON(LLTeleportHistory); +	~LLTeleportHistory();  	LOG_CLASS(LLTeleportHistory);  public: @@ -81,9 +83,6 @@ public:  	typedef boost::function<void()>				history_callback_t;  	typedef boost::signals2::signal<void()>		history_signal_t; -	LLTeleportHistory(); -	~LLTeleportHistory(); -  	/**  	 * Go back in the history.  	 */ diff --git a/indra/newview/llteleporthistorystorage.h b/indra/newview/llteleporthistorystorage.h index cf4c85a991..946ac0af1a 100644 --- a/indra/newview/llteleporthistorystorage.h +++ b/indra/newview/llteleporthistorystorage.h @@ -68,6 +68,8 @@ public:   */  class LLTeleportHistoryStorage: public LLSingleton<LLTeleportHistoryStorage>  { +	LLSINGLETON(LLTeleportHistoryStorage); +	~LLTeleportHistoryStorage();  	LOG_CLASS(LLTeleportHistoryStorage);  public: @@ -78,9 +80,6 @@ public:  	typedef boost::function<void(S32 removed_index)>		history_callback_t;  	typedef boost::signals2::signal<void(S32 removed_index)>	history_signal_t; -	LLTeleportHistoryStorage(); -	~LLTeleportHistoryStorage(); -  	/**  	 * @return history items.  	 */ diff --git a/indra/newview/lltextureatlasmanager.h b/indra/newview/lltextureatlasmanager.h index b643056198..1b8df708c6 100644 --- a/indra/newview/lltextureatlasmanager.h +++ b/indra/newview/lltextureatlasmanager.h @@ -85,12 +85,11 @@ private:  class LLTextureAtlasManager : public LLSingleton<LLTextureAtlasManager>  { -private: +	LLSINGLETON(LLTextureAtlasManager); +	~LLTextureAtlasManager();  	typedef std::list<LLPointer<LLTextureAtlas> > ll_texture_atlas_list_t ;  public: -	LLTextureAtlasManager(); -	~LLTextureAtlasManager();  	LLPointer<LLTextureAtlasSlot> reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents,   		LLSpatialGroup* groupp, LLViewerTexture* imagep) ; diff --git a/indra/newview/lltoolbrush.h b/indra/newview/lltoolbrush.h index 2ec6911de9..c108d83256 100644 --- a/indra/newview/lltoolbrush.h +++ b/indra/newview/lltoolbrush.h @@ -43,10 +43,10 @@ class LLViewerRegion;  class LLToolBrushLand : public LLTool, public LLEditMenuHandler, public LLSingleton<LLToolBrushLand>  { +	LLSINGLETON(LLToolBrushLand);  	typedef std::set<LLViewerRegion*> region_list_t;  public: -	LLToolBrushLand();  	// x,y in window coords, 0,0 = left,bot  	virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp index 2b4fa757f6..d9adec82b4 100644 --- a/indra/newview/lltoolcomp.cpp +++ b/indra/newview/lltoolcomp.cpp @@ -683,7 +683,7 @@ LLToolCompGun::LLToolCompGun()  	: LLToolComposite(std::string("Mouselook"))  {  	mGun = new LLToolGun(this); -	mGrab = new LLToolGrab(this); +	mGrab = new LLToolGrabBase(this);  	mNull = sNullTool;  	setCurrentTool(mGun); diff --git a/indra/newview/lltoolcomp.h b/indra/newview/lltoolcomp.h index e75d3c22e2..86506f725e 100644 --- a/indra/newview/lltoolcomp.h +++ b/indra/newview/lltoolcomp.h @@ -103,9 +103,9 @@ public:  class LLToolCompInspect : public LLToolComposite, public LLSingleton<LLToolCompInspect>  { -public: -	LLToolCompInspect(); +	LLSINGLETON(LLToolCompInspect);  	virtual ~LLToolCompInspect(); +public:  	// Overridden from LLToolComposite      virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask); @@ -128,9 +128,9 @@ private:  class LLToolCompTranslate : public LLToolComposite, public LLSingleton<LLToolCompTranslate>  { -public: -	LLToolCompTranslate(); +	LLSINGLETON(LLToolCompTranslate);  	virtual ~LLToolCompTranslate(); +public:  	// Overridden from LLToolComposite  	virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask); @@ -149,9 +149,9 @@ public:  class LLToolCompScale : public LLToolComposite, public LLSingleton<LLToolCompScale>  { -public: -	LLToolCompScale(); +	LLSINGLETON(LLToolCompScale);  	virtual ~LLToolCompScale(); +public:  	// Overridden from LLToolComposite      virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask); @@ -171,9 +171,9 @@ public:  class LLToolCompRotate : public LLToolComposite, public LLSingleton<LLToolCompRotate>  { -public: -	LLToolCompRotate(); +	LLSINGLETON(LLToolCompRotate);  	virtual ~LLToolCompRotate(); +public:  	// Overridden from LLToolComposite      virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask); @@ -194,9 +194,9 @@ protected:  class LLToolCompCreate : public LLToolComposite, public LLSingleton<LLToolCompCreate>  { -public: -	LLToolCompCreate(); +	LLSINGLETON(LLToolCompCreate);  	virtual ~LLToolCompCreate(); +public:  	// Overridden from LLToolComposite      virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask); @@ -214,14 +214,14 @@ protected:  // LLToolCompGun  class LLToolGun; -class LLToolGrab; +class LLToolGrabBase;  class LLToolSelect;  class LLToolCompGun : public LLToolComposite, public LLSingleton<LLToolCompGun>  { -public: -	LLToolCompGun(); +	LLSINGLETON(LLToolCompGun);  	virtual ~LLToolCompGun(); +public:  	// Overridden from LLToolComposite      virtual BOOL			handleHover(S32 x, S32 y, MASK mask); @@ -237,7 +237,7 @@ public:  protected:  	LLToolGun*			mGun; -	LLToolGrab*			mGrab; +	LLToolGrabBase*		mGrab;  	LLTool*				mNull;  }; diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 63be1ef09b..766046785b 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -43,11 +43,10 @@ class LLPickInfo;  class LLToolDragAndDrop : public LLTool, public LLSingleton<LLToolDragAndDrop>  { +	LLSINGLETON(LLToolDragAndDrop);  public:  	typedef boost::signals2::signal<void ()> enddrag_signal_t; -	LLToolDragAndDrop(); -  	// overridden from LLTool  	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask);  	virtual BOOL	handleHover(S32 x, S32 y, MASK mask); @@ -281,8 +280,8 @@ private:  	class LLDragAndDropDictionary : public LLSingleton<LLDragAndDropDictionary>,  									public LLDictionary<EDragAndDropType, DragAndDropEntry>  	{ +		LLSINGLETON(LLDragAndDropDictionary);  	public: -		LLDragAndDropDictionary();  		dragOrDrop3dImpl get(EDragAndDropType dad_type, EDropTarget drop_target);  	};  }; diff --git a/indra/newview/lltoolface.h b/indra/newview/lltoolface.h index 7eb13b0fbc..e4b8ae12b8 100644 --- a/indra/newview/lltoolface.h +++ b/indra/newview/lltoolface.h @@ -35,9 +35,9 @@ class LLPickInfo;  class LLToolFace  :	public LLTool, public LLSingleton<LLToolFace>  { -public: -	LLToolFace(); +	LLSINGLETON(LLToolFace);  	virtual ~LLToolFace(); +public:  	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask);  	virtual BOOL	handleDoubleClick(S32 x, S32 y, MASK mask); diff --git a/indra/newview/lltoolfocus.h b/indra/newview/lltoolfocus.h index d23eb2cce6..cfc235b6c2 100644 --- a/indra/newview/lltoolfocus.h +++ b/indra/newview/lltoolfocus.h @@ -34,9 +34,9 @@ class LLPickInfo;  class LLToolCamera  :	public LLTool, public LLSingleton<LLToolCamera>  { -public: -	LLToolCamera(); +	LLSINGLETON(LLToolCamera);  	virtual ~LLToolCamera(); +public:  	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask);  	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask); diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp index c0ca4d7a9a..ed32e584a5 100644 --- a/indra/newview/lltoolgrab.cpp +++ b/indra/newview/lltoolgrab.cpp @@ -69,7 +69,7 @@ extern BOOL gDebugClicks;  //  // Methods  // -LLToolGrab::LLToolGrab( LLToolComposite* composite ) +LLToolGrabBase::LLToolGrabBase( LLToolComposite* composite )  :	LLTool( std::string("Grab"), composite ),  	mMode( GRAB_INACTIVE ),  	mVerticalDragging( FALSE ), @@ -88,12 +88,12 @@ LLToolGrab::LLToolGrab( LLToolComposite* composite )  	mHideBuildHighlight(FALSE)  { } -LLToolGrab::~LLToolGrab() +LLToolGrabBase::~LLToolGrabBase()  { }  // virtual -void LLToolGrab::handleSelect() +void LLToolGrabBase::handleSelect()  {  	if(gFloaterTools)  	{ @@ -106,7 +106,7 @@ void LLToolGrab::handleSelect()  	gGrabBtnSpin = FALSE;  } -void LLToolGrab::handleDeselect() +void LLToolGrabBase::handleDeselect()  {  	if( hasMouseCapture() )  	{ @@ -123,7 +123,7 @@ void LLToolGrab::handleDeselect()  } -BOOL LLToolGrab::handleDoubleClick(S32 x, S32 y, MASK mask) +BOOL LLToolGrabBase::handleDoubleClick(S32 x, S32 y, MASK mask)  {  	if (gDebugClicks)  	{ @@ -133,7 +133,7 @@ BOOL LLToolGrab::handleDoubleClick(S32 x, S32 y, MASK mask)  	return FALSE;  } -BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask) +BOOL LLToolGrabBase::handleMouseDown(S32 x, S32 y, MASK mask)  {  	if (gDebugClicks)  	{ @@ -152,7 +152,7 @@ BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask)  	return TRUE;  } -void LLToolGrab::pickCallback(const LLPickInfo& pick_info) +void LLToolGrabBase::pickCallback(const LLPickInfo& pick_info)  {  	LLToolGrab::getInstance()->mGrabPick = pick_info;  	LLViewerObject	*objectp = pick_info.getObject(); @@ -182,7 +182,7 @@ void LLToolGrab::pickCallback(const LLPickInfo& pick_info)  	}  } -BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info) +BOOL LLToolGrabBase::handleObjectHit(const LLPickInfo& info)  {  	mGrabPick = info;  	LLViewerObject* objectp = mGrabPick.getObject(); @@ -315,7 +315,7 @@ BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info)  } -void LLToolGrab::startSpin() +void LLToolGrabBase::startSpin()  {  	LLViewerObject* objectp = mGrabPick.getObject();  	if (!objectp) @@ -339,7 +339,7 @@ void LLToolGrab::startSpin()  } -void LLToolGrab::stopSpin() +void LLToolGrabBase::stopSpin()  {  	mSpinGrabbing = FALSE; @@ -373,7 +373,7 @@ void LLToolGrab::stopSpin()  } -void LLToolGrab::startGrab() +void LLToolGrabBase::startGrab()  {  	// Compute grab_offset in the OBJECT's root's coordinate frame  	// (sometimes root == object) @@ -422,7 +422,7 @@ void LLToolGrab::startGrab()  } -BOOL LLToolGrab::handleHover(S32 x, S32 y, MASK mask) +BOOL LLToolGrabBase::handleHover(S32 x, S32 y, MASK mask)  {  	if (!gViewerWindow->getLeftMouseDown())  	{ @@ -466,7 +466,7 @@ const F32 GRAB_SENSITIVITY_Y = 0.0075f;  // Dragging. -void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask) +void LLToolGrabBase::handleHoverActive(S32 x, S32 y, MASK mask)  {  	LLViewerObject* objectp = mGrabPick.getObject();  	if (!objectp || !hasMouseCapture() ) return; @@ -724,7 +724,7 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)  } -void LLToolGrab::handleHoverNonPhysical(S32 x, S32 y, MASK mask) +void LLToolGrabBase::handleHoverNonPhysical(S32 x, S32 y, MASK mask)  {  	LLViewerObject* objectp = mGrabPick.getObject();  	if (!objectp || !hasMouseCapture() ) return; @@ -881,7 +881,7 @@ void LLToolGrab::handleHoverNonPhysical(S32 x, S32 y, MASK mask)  // Not dragging.  Just showing affordances -void LLToolGrab::handleHoverInactive(S32 x, S32 y, MASK mask) +void LLToolGrabBase::handleHoverInactive(S32 x, S32 y, MASK mask)  {  	// JC - TODO - change cursor based on gGrabBtnVertical, gGrabBtnSpin  	LL_DEBUGS("UserInput") << "hover handled by LLToolGrab (inactive-not over editable object)" << LL_ENDL;		 @@ -889,7 +889,7 @@ void LLToolGrab::handleHoverInactive(S32 x, S32 y, MASK mask)  }  // User is trying to do something that's not allowed. -void LLToolGrab::handleHoverFailed(S32 x, S32 y, MASK mask) +void LLToolGrabBase::handleHoverFailed(S32 x, S32 y, MASK mask)  {  	if( GRAB_NOOBJECT == mMode )  	{ @@ -930,7 +930,7 @@ void LLToolGrab::handleHoverFailed(S32 x, S32 y, MASK mask) -BOOL LLToolGrab::handleMouseUp(S32 x, S32 y, MASK mask) +BOOL LLToolGrabBase::handleMouseUp(S32 x, S32 y, MASK mask)  {  	// call the base class to propogate info to sim  	LLTool::handleMouseUp(x, y, mask); @@ -961,7 +961,7 @@ BOOL LLToolGrab::handleMouseUp(S32 x, S32 y, MASK mask)  	return TRUE;  }  -void LLToolGrab::stopEditing() +void LLToolGrabBase::stopEditing()  {  	if( hasMouseCapture() )  	{ @@ -969,7 +969,7 @@ void LLToolGrab::stopEditing()  	}  } -void LLToolGrab::onMouseCaptureLost() +void LLToolGrabBase::onMouseCaptureLost()  {  	LLViewerObject* objectp = mGrabPick.getObject();  	if (!objectp) @@ -1026,7 +1026,7 @@ void LLToolGrab::onMouseCaptureLost()  } -void LLToolGrab::stopGrab() +void LLToolGrabBase::stopGrab()  {  	LLViewerObject* objectp = mGrabPick.getObject();  	if (!objectp) @@ -1067,29 +1067,29 @@ void LLToolGrab::stopGrab()  } -void LLToolGrab::draw() +void LLToolGrabBase::draw()  { } -void LLToolGrab::render() +void LLToolGrabBase::render()  { } -BOOL LLToolGrab::isEditing() +BOOL LLToolGrabBase::isEditing()  {  	return (mGrabPick.getObject().notNull());  } -LLViewerObject* LLToolGrab::getEditingObject() +LLViewerObject* LLToolGrabBase::getEditingObject()  {  	return mGrabPick.getObject();  } -LLVector3d LLToolGrab::getEditingPointGlobal() +LLVector3d LLToolGrabBase::getEditingPointGlobal()  {  	return getGrabPointGlobal();  } -LLVector3d LLToolGrab::getGrabPointGlobal() +LLVector3d LLToolGrabBase::getGrabPointGlobal()  {  	switch(mMode)  	{ diff --git a/indra/newview/lltoolgrab.h b/indra/newview/lltoolgrab.h index 5d24c8813e..02ed5c26d7 100644 --- a/indra/newview/lltoolgrab.h +++ b/indra/newview/lltoolgrab.h @@ -45,12 +45,17 @@ void send_ObjectGrab_message(LLViewerObject* object, const LLPickInfo & pick, co  void send_ObjectDeGrab_message(LLViewerObject* object, const LLPickInfo & pick); - -class LLToolGrab : public LLTool, public LLSingleton<LLToolGrab> +/** + * LLToolGrabBase contains most of the semantics of LLToolGrab. It's just that + * LLToolGrab is an LLSingleton, but we also explicitly instantiate + * LLToolGrabBase as part of LLToolCompGun. You can't just make an extra + * instance of an LLSingleton! + */ +class LLToolGrabBase : public LLTool  {  public: -	LLToolGrab( LLToolComposite* composite = NULL ); -	~LLToolGrab(); +	LLToolGrabBase(LLToolComposite* composite=NULL); +	~LLToolGrabBase();  	/*virtual*/ BOOL	handleHover(S32 x, S32 y, MASK mask);  	/*virtual*/ BOOL	handleMouseDown(S32 x, S32 y, MASK mask); @@ -140,10 +145,14 @@ private:  	BOOL			mClickedInMouselook;  }; +/// This is the LLSingleton instance of LLToolGrab. +class LLToolGrab : public LLToolGrabBase, public LLSingleton<LLToolGrab> +{ +	LLSINGLETON_EMPTY_CTOR(LLToolGrab); +}; +  extern BOOL gGrabBtnVertical;  extern BOOL gGrabBtnSpin;  extern LLTool* gGrabTransientTool;  #endif  // LL_TOOLGRAB_H - - diff --git a/indra/newview/lltoolindividual.h b/indra/newview/lltoolindividual.h index 961a6a4d93..e7c2060fba 100644 --- a/indra/newview/lltoolindividual.h +++ b/indra/newview/lltoolindividual.h @@ -39,9 +39,9 @@ class LLPickInfo;  class LLToolIndividual : public LLTool, public LLSingleton<LLToolIndividual>  { -public: -	LLToolIndividual(); +	LLSINGLETON(LLToolIndividual);  	virtual ~LLToolIndividual(); +public:  	virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);  	virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); diff --git a/indra/newview/lltoolmgr.h b/indra/newview/lltoolmgr.h index e5b45750d9..28465d5d2c 100644 --- a/indra/newview/lltoolmgr.h +++ b/indra/newview/lltoolmgr.h @@ -42,9 +42,9 @@ const MASK MASK_COPY			= MASK_SHIFT;  class LLToolMgr : public LLSingleton<LLToolMgr>  { -public: -	LLToolMgr(); +	LLSINGLETON(LLToolMgr);  	~LLToolMgr(); +public:  	// Must be called after gSavedSettings set up.  	void			initTools(); diff --git a/indra/newview/lltoolobjpicker.h b/indra/newview/lltoolobjpicker.h index 0c37be1f92..5ad9b67e21 100644 --- a/indra/newview/lltoolobjpicker.h +++ b/indra/newview/lltoolobjpicker.h @@ -35,8 +35,8 @@ class LLPickInfo;  class LLToolObjPicker : public LLTool, public LLSingleton<LLToolObjPicker>  { +	LLSINGLETON(LLToolObjPicker);  public: -	LLToolObjPicker();  	virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask);  	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask); diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h index 6391e675c5..95d155a474 100644 --- a/indra/newview/lltoolpie.h +++ b/indra/newview/lltoolpie.h @@ -37,9 +37,9 @@ class LLObjectSelection;  class LLToolPie : public LLTool, public LLSingleton<LLToolPie>  { +	LLSINGLETON(LLToolPie);  	LOG_CLASS(LLToolPie);  public: -	LLToolPie( );  	// Virtual functions inherited from LLMouseHandler  	virtual BOOL		handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down); diff --git a/indra/newview/lltoolpipette.h b/indra/newview/lltoolpipette.h index 8a83bf31af..7575d8ad18 100644 --- a/indra/newview/lltoolpipette.h +++ b/indra/newview/lltoolpipette.h @@ -43,10 +43,10 @@ class LLPickInfo;  class LLToolPipette  :	public LLTool, public LLSingleton<LLToolPipette>  { -public: -	LLToolPipette(); +	LLSINGLETON(LLToolPipette);  	virtual ~LLToolPipette(); +public:  	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask);  	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask);  	virtual BOOL	handleHover(S32 x, S32 y, MASK mask); diff --git a/indra/newview/lltoolselectland.h b/indra/newview/lltoolselectland.h index b368a4b153..b5ba72f16d 100644 --- a/indra/newview/lltoolselectland.h +++ b/indra/newview/lltoolselectland.h @@ -35,10 +35,10 @@ class LLParcelSelection;  class LLToolSelectLand  :	public LLTool, public LLSingleton<LLToolSelectLand>  { -public: -	LLToolSelectLand( ); +	LLSINGLETON(LLToolSelectLand);  	virtual ~LLToolSelectLand(); +public:  	/*virtual*/ BOOL		handleMouseDown(S32 x, S32 y, MASK mask);  	/*virtual*/ BOOL		handleDoubleClick(S32 x, S32 y, MASK mask);  	/*virtual*/ BOOL		handleMouseUp(S32 x, S32 y, MASK mask); diff --git a/indra/newview/lltransientfloatermgr.h b/indra/newview/lltransientfloatermgr.h index b4611c8c87..d126543f15 100644 --- a/indra/newview/lltransientfloatermgr.h +++ b/indra/newview/lltransientfloatermgr.h @@ -38,9 +38,7 @@ class LLTransientFloater;   */  class LLTransientFloaterMgr: public LLSingleton<LLTransientFloaterMgr>  { -protected: -	LLTransientFloaterMgr(); -	friend class LLSingleton<LLTransientFloaterMgr>; +	LLSINGLETON(LLTransientFloaterMgr);  public:  	enum ETransientGroup diff --git a/indra/newview/lltwitterconnect.h b/indra/newview/lltwitterconnect.h index be481a17c1..e77048cc35 100644 --- a/indra/newview/lltwitterconnect.h +++ b/indra/newview/lltwitterconnect.h @@ -43,6 +43,7 @@ class LLEventPump;   */  class LLTwitterConnect : public LLSingleton<LLTwitterConnect>  { +	LLSINGLETON(LLTwitterConnect);  	LOG_CLASS(LLTwitterConnect);  public:      enum EConnectionState @@ -81,10 +82,7 @@ public:      void openTwitterWeb(std::string url);  private: -	friend class LLSingleton<LLTwitterConnect>; -	LLTwitterConnect(); -	~LLTwitterConnect() {};   	std::string getTwitterConnectURL(const std::string& route = "", bool include_read_from_master = false);      EConnectionState mConnectionState; diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp index 08ba5a5f25..ad0c1734f9 100644 --- a/indra/newview/llviewerassettype.cpp +++ b/indra/newview/llviewerassettype.cpp @@ -48,8 +48,7 @@ struct ViewerAssetEntry : public LLDictionaryEntry  class LLViewerAssetDictionary : public LLSingleton<LLViewerAssetDictionary>,  						  public LLDictionary<LLViewerAssetType::EType, ViewerAssetEntry>  { -public: -	LLViewerAssetDictionary(); +	LLSINGLETON(LLViewerAssetDictionary);  };  LLViewerAssetDictionary::LLViewerAssetDictionary() diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index 94f1b09fa9..4271b20ad6 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -174,7 +174,7 @@ S32 LLResourceUploadInfo::getEconomyUploadCost()          getAssetType() == LLAssetType::AT_ANIMATION ||          getAssetType() == LLAssetType::AT_MESH)      { -        return LLGlobalEconomy::Singleton::instance().getPriceUpload(); +        return LLGlobalEconomy::instance().getPriceUpload();      }      return 0; diff --git a/indra/newview/llvieweraudio.h b/indra/newview/llvieweraudio.h index 8c302c6549..16f9b63113 100644 --- a/indra/newview/llvieweraudio.h +++ b/indra/newview/llvieweraudio.h @@ -43,6 +43,9 @@ void audio_update_wind(bool force_update = true);  class LLViewerAudio : public LLSingleton<LLViewerAudio>  { +	LLSINGLETON(LLViewerAudio); +	virtual ~LLViewerAudio(); +  public:  	enum EFadeState @@ -52,9 +55,6 @@ public:  		FADE_OUT,  	}; -	LLViewerAudio(); -	virtual ~LLViewerAudio(); -	  	void startInternetStreamWithAutoFade(std::string streamURI);  	void stopInternetStreamWithAutoFade(); diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index 7b2887d725..f8c973690a 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -54,6 +54,7 @@ extern template class LLViewerCamera* LLSingleton<class LLViewerCamera>::getInst  LL_ALIGN_PREFIX(16)  class LLViewerCamera : public LLCamera, public LLSingleton<LLViewerCamera>  { +	LLSINGLETON(LLViewerCamera);  public:  	void* operator new(size_t size)  	{ @@ -82,8 +83,6 @@ public:  	static eCameraID sCurCameraID; -	LLViewerCamera(); -  	void updateCameraLocation(const LLVector3 ¢er,  								const LLVector3 &up_direction,  								const LLVector3 &point_of_interest); diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp index b8ff2cc9b4..9cb2e0336a 100644 --- a/indra/newview/llviewerfoldertype.cpp +++ b/indra/newview/llviewerfoldertype.cpp @@ -103,8 +103,7 @@ struct ViewerFolderEntry : public LLDictionaryEntry  class LLViewerFolderDictionary : public LLSingleton<LLViewerFolderDictionary>,  								 public LLDictionary<LLFolderType::EType, ViewerFolderEntry>  { -public: -	LLViewerFolderDictionary(); +	LLSINGLETON(LLViewerFolderDictionary);  protected:  	bool initEnsemblesFromFile(); // Reads in ensemble information from foldertypes.xml  }; diff --git a/indra/newview/llviewerhelp.h b/indra/newview/llviewerhelp.h index a983012e2e..da50e07a43 100644 --- a/indra/newview/llviewerhelp.h +++ b/indra/newview/llviewerhelp.h @@ -39,7 +39,7 @@ class LLUICtrl;  class LLViewerHelp : public LLHelp, public LLSingleton<LLViewerHelp>  { -	friend class LLSingleton<LLViewerHelp>; +	LLSINGLETON_EMPTY_CTOR(LLViewerHelp);   public:  	/// display the specified help topic in the help viewer diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 434641aa25..87d8f753b8 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -94,107 +94,10 @@ void doInventoryCb(LLPointer<LLInventoryCallback> cb, LLUUID id)  ///----------------------------------------------------------------------------  class LLLocalizedInventoryItemsDictionary : public LLSingleton<LLLocalizedInventoryItemsDictionary>  { +	LLSINGLETON(LLLocalizedInventoryItemsDictionary);  public:  	std::map<std::string, std::string> mInventoryItemsDict; -	LLLocalizedInventoryItemsDictionary() -	{ -		mInventoryItemsDict["New Shape"]		= LLTrans::getString("New Shape"); -		mInventoryItemsDict["New Skin"]			= LLTrans::getString("New Skin"); -		mInventoryItemsDict["New Hair"]			= LLTrans::getString("New Hair"); -		mInventoryItemsDict["New Eyes"]			= LLTrans::getString("New Eyes"); -		mInventoryItemsDict["New Shirt"]		= LLTrans::getString("New Shirt"); -		mInventoryItemsDict["New Pants"]		= LLTrans::getString("New Pants"); -		mInventoryItemsDict["New Shoes"]		= LLTrans::getString("New Shoes"); -		mInventoryItemsDict["New Socks"]		= LLTrans::getString("New Socks"); -		mInventoryItemsDict["New Jacket"]		= LLTrans::getString("New Jacket"); -		mInventoryItemsDict["New Gloves"]		= LLTrans::getString("New Gloves"); -		mInventoryItemsDict["New Undershirt"]	= LLTrans::getString("New Undershirt"); -		mInventoryItemsDict["New Underpants"]	= LLTrans::getString("New Underpants"); -		mInventoryItemsDict["New Skirt"]		= LLTrans::getString("New Skirt"); -		mInventoryItemsDict["New Alpha"]		= LLTrans::getString("New Alpha"); -		mInventoryItemsDict["New Tattoo"]		= LLTrans::getString("New Tattoo"); -		mInventoryItemsDict["New Physics"]		= LLTrans::getString("New Physics"); -		mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable"); - -		mInventoryItemsDict["New Gesture"]		= LLTrans::getString("New Gesture"); -		mInventoryItemsDict["New Script"]		= LLTrans::getString("New Script"); -		mInventoryItemsDict["New Folder"]		= LLTrans::getString("New Folder"); -		mInventoryItemsDict["New Note"]			= LLTrans::getString("New Note"); -		mInventoryItemsDict["Contents"]			= LLTrans::getString("Contents"); - -		mInventoryItemsDict["Gesture"]			= LLTrans::getString("Gesture"); -		mInventoryItemsDict["Male Gestures"]	= LLTrans::getString("Male Gestures"); -		mInventoryItemsDict["Female Gestures"]	= LLTrans::getString("Female Gestures"); -		mInventoryItemsDict["Other Gestures"]	= LLTrans::getString("Other Gestures"); -		mInventoryItemsDict["Speech Gestures"]	= LLTrans::getString("Speech Gestures"); -		mInventoryItemsDict["Common Gestures"]	= LLTrans::getString("Common Gestures"); - -		//predefined gestures - -		//male -		mInventoryItemsDict["Male - Excuse me"]			= LLTrans::getString("Male - Excuse me"); -		mInventoryItemsDict["Male  - Get lost"]			= LLTrans::getString("Male - Get lost"); // double space after Male. EXT-8319 -		mInventoryItemsDict["Male - Blow kiss"]			= LLTrans::getString("Male - Blow kiss"); -		mInventoryItemsDict["Male - Boo"]				= LLTrans::getString("Male - Boo"); -		mInventoryItemsDict["Male - Bored"]				= LLTrans::getString("Male - Bored"); -		mInventoryItemsDict["Male - Hey"]				= LLTrans::getString("Male - Hey"); -		mInventoryItemsDict["Male - Laugh"]				= LLTrans::getString("Male - Laugh"); -		mInventoryItemsDict["Male - Repulsed"]			= LLTrans::getString("Male - Repulsed"); -		mInventoryItemsDict["Male - Shrug"]				= LLTrans::getString("Male - Shrug"); -		mInventoryItemsDict["Male - Stick tougue out"]	= LLTrans::getString("Male - Stick tougue out"); -		mInventoryItemsDict["Male - Wow"]				= LLTrans::getString("Male - Wow"); - -		//female -		mInventoryItemsDict["Female - Chuckle"]			= LLTrans::getString("Female - Chuckle"); -		mInventoryItemsDict["Female - Cry"]				= LLTrans::getString("Female - Cry"); -		mInventoryItemsDict["Female - Embarrassed"]		= LLTrans::getString("Female - Embarrassed"); -		mInventoryItemsDict["Female - Excuse me"]		= LLTrans::getString("Female - Excuse me"); -		mInventoryItemsDict["Female  - Get lost"]		= LLTrans::getString("Female - Get lost"); // double space after Female. EXT-8319 -		mInventoryItemsDict["Female - Blow kiss"]		= LLTrans::getString("Female - Blow kiss"); -		mInventoryItemsDict["Female - Boo"]				= LLTrans::getString("Female - Boo"); -		mInventoryItemsDict["Female - Bored"]			= LLTrans::getString("Female - Bored"); -		mInventoryItemsDict["Female - Hey"]				= LLTrans::getString("Female - Hey"); -		mInventoryItemsDict["Female - Hey baby"]		= LLTrans::getString("Female - Hey baby"); -		mInventoryItemsDict["Female - Laugh"]			= LLTrans::getString("Female - Laugh"); -		mInventoryItemsDict["Female - Looking good"]	= LLTrans::getString("Female - Looking good"); -		mInventoryItemsDict["Female - Over here"]		= LLTrans::getString("Female - Over here"); -		mInventoryItemsDict["Female - Please"]			= LLTrans::getString("Female - Please"); -		mInventoryItemsDict["Female - Repulsed"]		= LLTrans::getString("Female - Repulsed"); -		mInventoryItemsDict["Female - Shrug"]			= LLTrans::getString("Female - Shrug"); -		mInventoryItemsDict["Female - Stick tougue out"]= LLTrans::getString("Female - Stick tougue out"); -		mInventoryItemsDict["Female - Wow"]				= LLTrans::getString("Female - Wow"); - -		//common -		mInventoryItemsDict["/bow"]						= LLTrans::getString("/bow"); -		mInventoryItemsDict["/clap"]					= LLTrans::getString("/clap"); -		mInventoryItemsDict["/count"]					= LLTrans::getString("/count"); -		mInventoryItemsDict["/extinguish"]				= LLTrans::getString("/extinguish"); -		mInventoryItemsDict["/kmb"]						= LLTrans::getString("/kmb"); -		mInventoryItemsDict["/muscle"]					= LLTrans::getString("/muscle"); -		mInventoryItemsDict["/no"]						= LLTrans::getString("/no"); -		mInventoryItemsDict["/no!"]						= LLTrans::getString("/no!"); -		mInventoryItemsDict["/paper"]					= LLTrans::getString("/paper"); -		mInventoryItemsDict["/pointme"]					= LLTrans::getString("/pointme"); -		mInventoryItemsDict["/pointyou"]				= LLTrans::getString("/pointyou"); -		mInventoryItemsDict["/rock"]					= LLTrans::getString("/rock"); -		mInventoryItemsDict["/scissor"]					= LLTrans::getString("/scissor"); -		mInventoryItemsDict["/smoke"]					= LLTrans::getString("/smoke"); -		mInventoryItemsDict["/stretch"]					= LLTrans::getString("/stretch"); -		mInventoryItemsDict["/whistle"]					= LLTrans::getString("/whistle"); -		mInventoryItemsDict["/yes"]						= LLTrans::getString("/yes"); -		mInventoryItemsDict["/yes!"]					= LLTrans::getString("/yes!"); -		mInventoryItemsDict["afk"]						= LLTrans::getString("afk"); -		mInventoryItemsDict["dance1"]					= LLTrans::getString("dance1"); -		mInventoryItemsDict["dance2"]					= LLTrans::getString("dance2"); -		mInventoryItemsDict["dance3"]					= LLTrans::getString("dance3"); -		mInventoryItemsDict["dance4"]					= LLTrans::getString("dance4"); -		mInventoryItemsDict["dance5"]					= LLTrans::getString("dance5"); -		mInventoryItemsDict["dance6"]					= LLTrans::getString("dance6"); -		mInventoryItemsDict["dance7"]					= LLTrans::getString("dance7"); -		mInventoryItemsDict["dance8"]					= LLTrans::getString("dance8"); -	} -  	/**  	 * Finds passed name in dictionary and replaces it with found localized value.  	 * @@ -217,6 +120,103 @@ public:  	}  }; +LLLocalizedInventoryItemsDictionary::LLLocalizedInventoryItemsDictionary() +{ +	mInventoryItemsDict["New Shape"]		= LLTrans::getString("New Shape"); +	mInventoryItemsDict["New Skin"]			= LLTrans::getString("New Skin"); +	mInventoryItemsDict["New Hair"]			= LLTrans::getString("New Hair"); +	mInventoryItemsDict["New Eyes"]			= LLTrans::getString("New Eyes"); +	mInventoryItemsDict["New Shirt"]		= LLTrans::getString("New Shirt"); +	mInventoryItemsDict["New Pants"]		= LLTrans::getString("New Pants"); +	mInventoryItemsDict["New Shoes"]		= LLTrans::getString("New Shoes"); +	mInventoryItemsDict["New Socks"]		= LLTrans::getString("New Socks"); +	mInventoryItemsDict["New Jacket"]		= LLTrans::getString("New Jacket"); +	mInventoryItemsDict["New Gloves"]		= LLTrans::getString("New Gloves"); +	mInventoryItemsDict["New Undershirt"]	= LLTrans::getString("New Undershirt"); +	mInventoryItemsDict["New Underpants"]	= LLTrans::getString("New Underpants"); +	mInventoryItemsDict["New Skirt"]		= LLTrans::getString("New Skirt"); +	mInventoryItemsDict["New Alpha"]		= LLTrans::getString("New Alpha"); +	mInventoryItemsDict["New Tattoo"]		= LLTrans::getString("New Tattoo"); +	mInventoryItemsDict["New Physics"]		= LLTrans::getString("New Physics"); +	mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable"); + +	mInventoryItemsDict["New Gesture"]		= LLTrans::getString("New Gesture"); +	mInventoryItemsDict["New Script"]		= LLTrans::getString("New Script"); +	mInventoryItemsDict["New Folder"]		= LLTrans::getString("New Folder"); +	mInventoryItemsDict["New Note"]			= LLTrans::getString("New Note"); +	mInventoryItemsDict["Contents"]			= LLTrans::getString("Contents"); + +	mInventoryItemsDict["Gesture"]			= LLTrans::getString("Gesture"); +	mInventoryItemsDict["Male Gestures"]	= LLTrans::getString("Male Gestures"); +	mInventoryItemsDict["Female Gestures"]	= LLTrans::getString("Female Gestures"); +	mInventoryItemsDict["Other Gestures"]	= LLTrans::getString("Other Gestures"); +	mInventoryItemsDict["Speech Gestures"]	= LLTrans::getString("Speech Gestures"); +	mInventoryItemsDict["Common Gestures"]	= LLTrans::getString("Common Gestures"); + +	//predefined gestures + +	//male +	mInventoryItemsDict["Male - Excuse me"]			= LLTrans::getString("Male - Excuse me"); +	mInventoryItemsDict["Male  - Get lost"]			= LLTrans::getString("Male - Get lost"); // double space after Male. EXT-8319 +	mInventoryItemsDict["Male - Blow kiss"]			= LLTrans::getString("Male - Blow kiss"); +	mInventoryItemsDict["Male - Boo"]				= LLTrans::getString("Male - Boo"); +	mInventoryItemsDict["Male - Bored"]				= LLTrans::getString("Male - Bored"); +	mInventoryItemsDict["Male - Hey"]				= LLTrans::getString("Male - Hey"); +	mInventoryItemsDict["Male - Laugh"]				= LLTrans::getString("Male - Laugh"); +	mInventoryItemsDict["Male - Repulsed"]			= LLTrans::getString("Male - Repulsed"); +	mInventoryItemsDict["Male - Shrug"]				= LLTrans::getString("Male - Shrug"); +	mInventoryItemsDict["Male - Stick tougue out"]	= LLTrans::getString("Male - Stick tougue out"); +	mInventoryItemsDict["Male - Wow"]				= LLTrans::getString("Male - Wow"); + +	//female +	mInventoryItemsDict["Female - Chuckle"]			= LLTrans::getString("Female - Chuckle"); +	mInventoryItemsDict["Female - Cry"]				= LLTrans::getString("Female - Cry"); +	mInventoryItemsDict["Female - Embarrassed"]		= LLTrans::getString("Female - Embarrassed"); +	mInventoryItemsDict["Female - Excuse me"]		= LLTrans::getString("Female - Excuse me"); +	mInventoryItemsDict["Female  - Get lost"]		= LLTrans::getString("Female - Get lost"); // double space after Female. EXT-8319 +	mInventoryItemsDict["Female - Blow kiss"]		= LLTrans::getString("Female - Blow kiss"); +	mInventoryItemsDict["Female - Boo"]				= LLTrans::getString("Female - Boo"); +	mInventoryItemsDict["Female - Bored"]			= LLTrans::getString("Female - Bored"); +	mInventoryItemsDict["Female - Hey"]				= LLTrans::getString("Female - Hey"); +	mInventoryItemsDict["Female - Hey baby"]		= LLTrans::getString("Female - Hey baby"); +	mInventoryItemsDict["Female - Laugh"]			= LLTrans::getString("Female - Laugh"); +	mInventoryItemsDict["Female - Looking good"]	= LLTrans::getString("Female - Looking good"); +	mInventoryItemsDict["Female - Over here"]		= LLTrans::getString("Female - Over here"); +	mInventoryItemsDict["Female - Please"]			= LLTrans::getString("Female - Please"); +	mInventoryItemsDict["Female - Repulsed"]		= LLTrans::getString("Female - Repulsed"); +	mInventoryItemsDict["Female - Shrug"]			= LLTrans::getString("Female - Shrug"); +	mInventoryItemsDict["Female - Stick tougue out"]= LLTrans::getString("Female - Stick tougue out"); +	mInventoryItemsDict["Female - Wow"]				= LLTrans::getString("Female - Wow"); + +	//common +	mInventoryItemsDict["/bow"]						= LLTrans::getString("/bow"); +	mInventoryItemsDict["/clap"]					= LLTrans::getString("/clap"); +	mInventoryItemsDict["/count"]					= LLTrans::getString("/count"); +	mInventoryItemsDict["/extinguish"]				= LLTrans::getString("/extinguish"); +	mInventoryItemsDict["/kmb"]						= LLTrans::getString("/kmb"); +	mInventoryItemsDict["/muscle"]					= LLTrans::getString("/muscle"); +	mInventoryItemsDict["/no"]						= LLTrans::getString("/no"); +	mInventoryItemsDict["/no!"]						= LLTrans::getString("/no!"); +	mInventoryItemsDict["/paper"]					= LLTrans::getString("/paper"); +	mInventoryItemsDict["/pointme"]					= LLTrans::getString("/pointme"); +	mInventoryItemsDict["/pointyou"]				= LLTrans::getString("/pointyou"); +	mInventoryItemsDict["/rock"]					= LLTrans::getString("/rock"); +	mInventoryItemsDict["/scissor"]					= LLTrans::getString("/scissor"); +	mInventoryItemsDict["/smoke"]					= LLTrans::getString("/smoke"); +	mInventoryItemsDict["/stretch"]					= LLTrans::getString("/stretch"); +	mInventoryItemsDict["/whistle"]					= LLTrans::getString("/whistle"); +	mInventoryItemsDict["/yes"]						= LLTrans::getString("/yes"); +	mInventoryItemsDict["/yes!"]					= LLTrans::getString("/yes!"); +	mInventoryItemsDict["afk"]						= LLTrans::getString("afk"); +	mInventoryItemsDict["dance1"]					= LLTrans::getString("dance1"); +	mInventoryItemsDict["dance2"]					= LLTrans::getString("dance2"); +	mInventoryItemsDict["dance3"]					= LLTrans::getString("dance3"); +	mInventoryItemsDict["dance4"]					= LLTrans::getString("dance4"); +	mInventoryItemsDict["dance5"]					= LLTrans::getString("dance5"); +	mInventoryItemsDict["dance6"]					= LLTrans::getString("dance6"); +	mInventoryItemsDict["dance7"]					= LLTrans::getString("dance7"); +	mInventoryItemsDict["dance8"]					= LLTrans::getString("dance8"); +}  ///----------------------------------------------------------------------------  /// Local function declarations, constants, enums, and typedefs diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 5194679a0c..074d51b8b3 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -30,7 +30,7 @@  #include "llinventory.h"  #include "llframetimer.h"  #include "llwearable.h" -#include "llui.h" //for LLDestroyClass +#include "llinitdestroyclass.h" //for LLDestroyClass  #include <boost/signals2.hpp>	// boost::signals2::trackable diff --git a/indra/newview/llviewerjoystick.h b/indra/newview/llviewerjoystick.h index 80c758a5af..016b435ee8 100644 --- a/indra/newview/llviewerjoystick.h +++ b/indra/newview/llviewerjoystick.h @@ -45,10 +45,10 @@ typedef enum e_joystick_driver_state  class LLViewerJoystick : public LLSingleton<LLViewerJoystick>  { -public: -	LLViewerJoystick(); +	LLSINGLETON(LLViewerJoystick);  	virtual ~LLViewerJoystick(); -	 + +public:  	void init(bool autoenable);  	void terminate(); diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 2186ed3c52..fd4315a319 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -57,6 +57,7 @@ const F32 ORBIT_NUDGE_RATE = 0.05f;  // fraction of normal speed  struct LLKeyboardActionRegistry   :	public LLRegistrySingleton<std::string, boost::function<void (EKeystate keystate)>, LLKeyboardActionRegistry>  { +	LLSINGLETON_EMPTY_CTOR(LLKeyboardActionRegistry);  };  LLViewerKeyboard gViewerKeyboard; diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h index 0b2a64868e..368c671f84 100644 --- a/indra/newview/llviewermediafocus.h +++ b/indra/newview/llviewermediafocus.h @@ -41,10 +41,10 @@ class LLViewerMediaFocus :  	public LLFocusableElement,   	public LLSingleton<LLViewerMediaFocus>  { -public: -	LLViewerMediaFocus(); +	LLSINGLETON(LLViewerMediaFocus);  	~LLViewerMediaFocus(); -	 + +public:  	// Set/clear the face that has media focus (takes keyboard input and has the full set of controls)  	void setFocusFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero);  	void clearFocus(); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 39059fc01e..ac494b6eba 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -133,6 +133,7 @@  #include "llpathfindingmanager.h"  #include "llstartup.h"  #include "boost/unordered_map.hpp" +#include "llcleanup.h"  using namespace LLAvatarAppearanceDefines; @@ -8484,7 +8485,7 @@ class LLWorldPostProcess : public view_listener_t  void handle_flush_name_caches()  { -	LLAvatarNameCache::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLAvatarNameCache);  	if (gCacheName) gCacheName->clear();  } @@ -8528,7 +8529,7 @@ class LLToggleUIHints : public view_listener_t  void LLUploadCostCalculator::calculateCost()  { -	S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); +	S32 upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();  	// getPriceUpload() returns -1 if no data available yet.  	if(upload_cost >= 0) diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 08d024e45c..d46bb0199b 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -84,7 +84,7 @@ class LLFileEnableUpload : public view_listener_t  	bool handleEvent(const LLSD& userdata)  	{          return true; -// 		bool new_value = gStatusBar && LLGlobalEconomy::Singleton::getInstance() && (gStatusBar->getBalance() >= LLGlobalEconomy::Singleton::getInstance()->getPriceUpload()); +// 		bool new_value = gStatusBar && LLGlobalEconomy::getInstance() && (gStatusBar->getBalance() >= LLGlobalEconomy::getInstance()->getPriceUpload());  // 		return new_value;  	}  }; @@ -429,7 +429,7 @@ class LLFileUploadBulk : public view_listener_t  		if (picker.getMultipleOpenFiles())  		{              std::string filename = picker.getFirstFile(); -            S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); +            S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();              while (!filename.empty())              { diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 15ecfe5dca..d81cb804e4 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -6284,9 +6284,9 @@ void process_frozen_message(LLMessageSystem *msgsystem, void **user_data)  // do some extra stuff once we get our economy data  void process_economy_data(LLMessageSystem *msg, void** /*user_data*/)  { -	LLGlobalEconomy::processEconomyData(msg, LLGlobalEconomy::Singleton::getInstance()); +	LLGlobalEconomy::processEconomyData(msg, LLGlobalEconomy::getInstance()); -	S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); +	S32 upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();  	LL_INFOS_ONCE("Messaging") << "EconomyData message arrived; upload cost is L$" << upload_cost << LL_ENDL; diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index d8f5c71f8d..b0eaa37541 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -210,6 +210,7 @@ void set_dad_inbox_object(const LLUUID& object_id);  class LLViewerMessage : public  LLSingleton<LLViewerMessage>  { +	LLSINGLETON_EMPTY_CTOR(LLViewerMessage);  public:  	typedef boost::function<void()> teleport_started_callback_t;  	typedef boost::signals2::signal<void()> teleport_started_signal_t; diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index 2525886222..6937d064f9 100644 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -95,13 +95,6 @@ LLGridManager::LLGridManager()  } -LLGridManager::LLGridManager(const std::string& grid_file) -{ -	// initialize with an explicity grid file for testing. -	LL_DEBUGS("GridManager")<<LL_ENDL; -	initialize(grid_file); -} -  //  // LLGridManager - class for managing the list of known grids, and the current  // selection diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h index 228303d8e2..b8ff494b8b 100644 --- a/indra/newview/llviewernetwork.h +++ b/indra/newview/llviewernetwork.h @@ -58,16 +58,15 @@ protected:   **/  class LLGridManager : public LLSingleton<LLGridManager>  { +	/// Instantiate the grid manager, load default grids, selects the default grid +	LLSINGLETON(LLGridManager); +	~LLGridManager(); +    public:  	/* ================================================================  	 * @name Initialization and Configuration  	 * @{  	 */ -	/// Instantiate the grid manager, load default grids, selects the default grid -	LLGridManager(const std::string& grid_file); -	LLGridManager(); -	~LLGridManager(); -	  	/// add grids from an external grids file  	void initialize(const std::string& grid_file); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 7964bf1848..61dd71ab75 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -102,6 +102,7 @@  #include "llmediaentry.h"  #include "llfloaterperms.h"  #include "llvocache.h" +#include "llcleanup.h"  //#define DEBUG_UPDATE_TYPE @@ -530,11 +531,11 @@ void LLViewerObject::initVOClasses()  void LLViewerObject::cleanupVOClasses()  { -	LLVOGrass::cleanupClass(); -	LLVOWater::cleanupClass(); -	LLVOTree::cleanupClass(); -	LLVOAvatar::cleanupClass(); -	LLVOVolume::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLVOGrass); +	SUBSYSTEM_CLEANUP(LLVOWater); +	SUBSYSTEM_CLEANUP(LLVOTree); +	SUBSYSTEM_CLEANUP(LLVOAvatar); +	SUBSYSTEM_CLEANUP(LLVOVolume);  	sObjectDataMap.clear();  } diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index bb6bbf3308..29219843c9 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -75,6 +75,8 @@ public:  class LLViewerParcelMgr : public LLSingleton<LLViewerParcelMgr>  { +	LLSINGLETON(LLViewerParcelMgr); +	~LLViewerParcelMgr();  public:  	typedef boost::function<void (const LLVector3d&, const bool& local)> teleport_finished_callback_t; @@ -82,9 +84,6 @@ public:  	typedef boost::function<void()> teleport_failed_callback_t;  	typedef boost::signals2::signal<void()> teleport_failed_signal_t; -	LLViewerParcelMgr(); -	~LLViewerParcelMgr(); -  	static void cleanupGlobals();  	BOOL	selectionEmpty() const; diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h index 40e8e1d45d..ab1cd715ab 100644 --- a/indra/newview/llviewerpartsim.h +++ b/indra/newview/llviewerpartsim.h @@ -135,9 +135,8 @@ protected:  class LLViewerPartSim : public LLSingleton<LLViewerPartSim>  { +	LLSINGLETON(LLViewerPartSim);  public: -	LLViewerPartSim(); -	virtual ~LLViewerPartSim(){}  	void destroyClass();  	typedef std::vector<LLViewerPartGroup *> group_list_t; diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 7843652589..97a060d95e 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -246,13 +246,11 @@ extern LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > OBJECT_CACHE_HIT  class LLViewerStats : public LLSingleton<LLViewerStats>  { -public: -	void resetStats(); +	LLSINGLETON(LLViewerStats); +	~LLViewerStats();  public: - -	LLViewerStats(); -	~LLViewerStats(); +	void resetStats();  	void updateFrameStats(const F64Seconds time_diff); diff --git a/indra/newview/llviewerstatsrecorder.h b/indra/newview/llviewerstatsrecorder.h index d1744f4910..c974bea49d 100644 --- a/indra/newview/llviewerstatsrecorder.h +++ b/indra/newview/llviewerstatsrecorder.h @@ -44,11 +44,11 @@ class LLViewerObject;  class LLViewerStatsRecorder : public LLSingleton<LLViewerStatsRecorder>  { - public: -	LOG_CLASS(LLViewerStatsRecorder);	  -	LLViewerStatsRecorder(); +	LLSINGLETON(LLViewerStatsRecorder); +	LOG_CLASS(LLViewerStatsRecorder);  	~LLViewerStatsRecorder(); + public:  	void objectUpdateFailure(U32 local_id, const EObjectUpdateType update_type, S32 msg_size)  	{  #if LL_RECORD_VIEWER_STATS diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index ba76770838..070544063a 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -237,6 +237,7 @@ private:  class LLUIImageList : public LLImageProviderInterface, public LLSingleton<LLUIImageList>  { +	LLSINGLETON_EMPTY_CTOR(LLUIImageList);  public:  	// LLImageProviderInterface  	/*virtual*/ LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 9e68bb78e0..cce988c2fe 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -208,6 +208,7 @@  #include "llwindowlistener.h"  #include "llviewerwindowlistener.h"  #include "llpaneltopinfobar.h" +#include "llcleanup.h"  #if LL_WINDOWS  #include <tchar.h> // For Unicode conversion methods @@ -292,13 +293,8 @@ public:  class RecordToChatConsole : public LLSingleton<RecordToChatConsole>  { +	LLSINGLETON(RecordToChatConsole);  public: -	RecordToChatConsole() -		: LLSingleton<RecordToChatConsole>(), -		mRecorder(new RecordToChatConsoleRecorder()) -	{ -	} -  	void startRecorder() { LLError::addRecorder(mRecorder); }  	void stopRecorder() { LLError::removeRecorder(mRecorder); } @@ -306,6 +302,11 @@ private:  	LLError::RecorderPtr mRecorder;  }; +RecordToChatConsole::RecordToChatConsole(): +	mRecorder(new RecordToChatConsoleRecorder()) +{ +} +  ////////////////////////////////////////////////////////////////////////////  //  // LLDebugText @@ -2176,10 +2177,7 @@ void LLViewerWindow::shutdownViews()  	// destroy the nav bar, not currently part of gViewerWindow  	// *TODO: Make LLNavigationBar part of gViewerWindow -	if (LLNavigationBar::instanceExists()) -	{ -		delete LLNavigationBar::getInstance(); -	} +	LLNavigationBar::deleteSingleton();  	LL_INFOS() << "LLNavigationBar destroyed." << LL_ENDL ;  	// destroy menus after instantiating navbar above, as it needs @@ -2215,7 +2213,7 @@ void LLViewerWindow::shutdownGL()  	// Shutdown GL cleanly.  Order is very important here.  	//--------------------------------------------------------  	LLFontGL::destroyDefaultFonts(); -	LLFontManager::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLFontManager);  	stop_glerror();  	gSky.cleanup(); @@ -2238,7 +2236,7 @@ void LLViewerWindow::shutdownGL()  	LLWorldMapView::cleanupTextures();  	LLViewerTextureManager::cleanup() ; -	LLImageGL::cleanupClass() ; +	SUBSYSTEM_CLEANUP(LLImageGL) ;  	LL_INFOS() << "All textures and llimagegl images are destroyed!" << LL_ENDL ; @@ -2251,7 +2249,7 @@ void LLViewerWindow::shutdownGL()  	gGL.shutdown(); -	LLVertexBuffer::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLVertexBuffer);  	LL_INFOS() << "LLVertexBuffer cleaned." << LL_ENDL ;  } diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index 082f5f0b1d..7aabde1b2d 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -223,6 +223,9 @@ private:  //  class LLVOCache : public LLSingleton<LLVOCache>  { +	LLSINGLETON(LLVOCache); +	~LLVOCache() ; +  private:  	struct HeaderEntryInfo  	{ @@ -253,13 +256,8 @@ private:  	};  	typedef std::set<HeaderEntryInfo*, header_entry_less> header_entry_queue_t;  	typedef std::map<U64, HeaderEntryInfo*> handle_entry_map_t; -private: -    friend class LLSingleton<LLVOCache>; -	LLVOCache() ;  public: -	~LLVOCache() ; -  	void initCache(ELLPath location, U32 size, U32 cache_version) ;  	void removeCache(ELLPath location, bool started = false) ; diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h index ef15b2c79e..309c3eebdd 100644 --- a/indra/newview/llvoicechannel.h +++ b/indra/newview/llvoicechannel.h @@ -167,8 +167,8 @@ private:  class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoiceChannelProximal>  { +	LLSINGLETON(LLVoiceChannelProximal);  public: -	LLVoiceChannelProximal();  	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);  	/*virtual*/ void handleStatusChange(EStatusType status); diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index b05bcb23b7..32637dcf42 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -299,11 +299,11 @@ public:  class LLVoiceClient: public LLSingleton<LLVoiceClient>  { +	LLSINGLETON(LLVoiceClient);  	LOG_CLASS(LLVoiceClient); -public: -	LLVoiceClient();	  	~LLVoiceClient(); +public:  	typedef boost::signals2::signal<void(void)> micro_changed_signal_t;  	micro_changed_signal_t mMicroChangedSignal; @@ -485,6 +485,8 @@ protected:   **/  class LLSpeakerVolumeStorage : public LLSingleton<LLSpeakerVolumeStorage>  { +	LLSINGLETON(LLSpeakerVolumeStorage); +	~LLSpeakerVolumeStorage();  	LOG_CLASS(LLSpeakerVolumeStorage);  public: @@ -513,10 +515,6 @@ public:  	void removeSpeakerVolume(const LLUUID& speaker_id);  private: -	friend class LLSingleton<LLSpeakerVolumeStorage>; -	LLSpeakerVolumeStorage(); -	~LLSpeakerVolumeStorage(); -  	const static std::string SETTINGS_FILE_NAME;  	void load(); diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index f32c7c975f..81e924e438 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -56,12 +56,11 @@ class LLVivoxVoiceClient :	public LLSingleton<LLVivoxVoiceClient>,  							virtual public LLVoiceModuleInterface,  							virtual public LLVoiceEffectInterface  { +	LLSINGLETON(LLVivoxVoiceClient);  	LOG_CLASS(LLVivoxVoiceClient); -public: -	LLVivoxVoiceClient();	  	virtual ~LLVivoxVoiceClient(); -	 -	 + +public:  	/// @name LLVoiceModuleInterface virtual implementations  	///  @see LLVoiceModuleInterface  	//@{ @@ -1027,10 +1026,10 @@ protected:  class LLVivoxSecurity :	public LLSingleton<LLVivoxSecurity>  { -  public: -	LLVivoxSecurity();	 -	virtual ~LLVivoxSecurity(); +    LLSINGLETON(LLVivoxSecurity); +    virtual ~LLVivoxSecurity(); +  public:      std::string     connectorHandle() { return mConnectorHandle; };      std::string     accountHandle()    { return mAccountHandle;    }; diff --git a/indra/newview/llwatchdog.h b/indra/newview/llwatchdog.h index fee3ec6f20..9a6624258e 100644 --- a/indra/newview/llwatchdog.h +++ b/indra/newview/llwatchdog.h @@ -75,10 +75,10 @@ private:  class LLWatchdogTimerThread; // Defined in the cpp  class LLWatchdog : public LLSingleton<LLWatchdog>  { -public: -	LLWatchdog(); +	LLSINGLETON(LLWatchdog);  	~LLWatchdog(); +public:  	// Add an entry to the watchdog.  	void add(LLWatchdogEntry* e);  	void remove(LLWatchdogEntry* e); diff --git a/indra/newview/llwaterparammanager.h b/indra/newview/llwaterparammanager.h index dc7d41be2a..3f169e439a 100644 --- a/indra/newview/llwaterparammanager.h +++ b/indra/newview/llwaterparammanager.h @@ -214,6 +214,8 @@ struct WaterExpFloatControl  /// WindLight parameter manager class - what controls all the wind light shaders  class LLWaterParamManager : public LLSingleton<LLWaterParamManager>  { +	LLSINGLETON(LLWaterParamManager); +	~LLWaterParamManager();  	LOG_CLASS(LLWaterParamManager);  public:  	typedef std::list<std::string> preset_name_list_t; @@ -317,11 +319,7 @@ public:  	F32 mDensitySliderValue;  private: -	friend class LLSingleton<LLWaterParamManager>;  	/*virtual*/ void initSingleton(); -	LLWaterParamManager(); -	~LLWaterParamManager(); -  	void loadAllPresets();  	void loadPresetsFromDir(const std::string& dir);  	bool loadPreset(const std::string& path); diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index 63e3e9dbc9..f3182ed163 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -411,8 +411,8 @@ public:  	 */  	class ContextMenu : public LLListContextMenu, public LLSingleton<ContextMenu>  	{ +		LLSINGLETON(ContextMenu);  	public: -		ContextMenu();  		/*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y);  	protected: diff --git a/indra/newview/llwearablelist.h b/indra/newview/llwearablelist.h index d6f0fd09a6..782f7751e5 100644 --- a/indra/newview/llwearablelist.h +++ b/indra/newview/llwearablelist.h @@ -41,9 +41,9 @@  */  class LLWearableList : public LLSingleton<LLWearableList>  { -public: -	LLWearableList()	{} +	LLSINGLETON_EMPTY_CTOR(LLWearableList);  	~LLWearableList(); +public:  	void cleanup() ;  	S32					getLength() const { return mList.size(); } diff --git a/indra/newview/llwindebug.h b/indra/newview/llwindebug.h index a3cbf6dc03..90882cf04a 100644 --- a/indra/newview/llwindebug.h +++ b/indra/newview/llwindebug.h @@ -34,6 +34,7 @@  class LLWinDebug:  	public LLSingleton<LLWinDebug>  { +	LLSINGLETON_EMPTY_CTOR(LLWinDebug);  public:  	static void init();  	static void generateMinidump(struct _EXCEPTION_POINTERS *pExceptionInfo = NULL); diff --git a/indra/newview/llwlparammanager.h b/indra/newview/llwlparammanager.h index e13aed98ed..a10102edf7 100644 --- a/indra/newview/llwlparammanager.h +++ b/indra/newview/llwlparammanager.h @@ -213,6 +213,8 @@ public:  /// WindLight parameter manager class - what controls all the wind light shaders  class LLWLParamManager : public LLSingleton<LLWLParamManager>  { +	LLSINGLETON(LLWLParamManager); +	~LLWLParamManager();  	LOG_CLASS(LLWLParamManager);  public: @@ -375,11 +377,7 @@ private:  	static std::string getSysDir();  	static std::string getUserDir(); -	friend class LLSingleton<LLWLParamManager>;  	/*virtual*/ void initSingleton(); -	LLWLParamManager(); -	~LLWLParamManager(); -  	// list of all the parameters, listed by name  	std::map<LLWLParamKey, LLWLParamSet> mParamList; diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h index b2d8418064..c9ac241d5a 100644 --- a/indra/newview/llworld.h +++ b/indra/newview/llworld.h @@ -61,8 +61,8 @@ class LLVOAvatar;  class LLWorld : public LLSingleton<LLWorld>  { +	LLSINGLETON(LLWorld);  public: -	LLWorld();  	void destroyClass();  	LLViewerRegion*	addRegion(const U64 ®ion_handle, const LLHost &host); diff --git a/indra/newview/llworldmap.h b/indra/newview/llworldmap.h index 1a168e4b4d..5e5caa6a74 100644 --- a/indra/newview/llworldmap.h +++ b/indra/newview/llworldmap.h @@ -193,10 +193,10 @@ const S32 MAP_BLOCK_RES = (MAP_MAX_SIZE / MAP_BLOCK_SIZE);  class LLWorldMap : public LLSingleton<LLWorldMap>  { -public: -	LLWorldMap(); +	LLSINGLETON(LLWorldMap);  	~LLWorldMap(); +public:  	// Clear all: list of region info, tiles, blocks and items  	void reset(); diff --git a/indra/newview/llworldmapmessage.h b/indra/newview/llworldmapmessage.h index ac1ea1607c..65276df068 100644 --- a/indra/newview/llworldmapmessage.h +++ b/indra/newview/llworldmapmessage.h @@ -34,13 +34,13 @@ class LLMessageSystem;  class LLWorldMapMessage : public LLSingleton<LLWorldMapMessage>  { +	LLSINGLETON(LLWorldMapMessage); +	~LLWorldMapMessage(); +  public:  	typedef boost::function<void(U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport)>  		url_callback_t; -	LLWorldMapMessage(); -	~LLWorldMapMessage(); -  	// Process incoming answers to map stuff requests  	static void processMapBlockReply(LLMessageSystem*, void**);  	static void processMapItemReply(LLMessageSystem*, void**); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 70989bacff..7c019dc3ea 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -114,6 +114,7 @@  #include "llpathfindingpathtool.h"  #include "llscenemonitor.h"  #include "llprogressview.h" +#include "llcleanup.h"  #ifdef _DEBUG  // Debug indices is disabled for now for debug performance - djs 4/24/02 @@ -7385,7 +7386,7 @@ void LLPipeline::doResetVertexBuffers(bool forced)  	}  	LLVOPartGroup::destroyGL(); -	LLVertexBuffer::cleanupClass(); +	SUBSYSTEM_CLEANUP(LLVertexBuffer);  	//delete all name pool caches  	LLGLNamePool::cleanupPools(); diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp index ea5014a59c..4f7f87b6b0 100644 --- a/indra/newview/tests/llremoteparcelrequest_test.cpp +++ b/indra/newview/tests/llremoteparcelrequest_test.cpp @@ -34,6 +34,7 @@  #include "../llagent.h"  #include "message.h"  #include "llurlentry.h" +#include "llpounceable.h"  namespace {  	const LLUUID TEST_PARCEL_ID("11111111-1111-1111-1111-111111111111"); @@ -62,7 +63,7 @@ void LLMessageSystem::addUUID(char const *,LLUUID const &) { }  void LLMessageSystem::addUUIDFast(char const *,LLUUID const &) { }  void LLMessageSystem::nextBlockFast(char const *) { }  void LLMessageSystem::newMessage(char const *) { } -LLMessageSystem * gMessageSystem; +LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;  char const* const _PREHASH_AgentID = 0;   // never dereferenced during this test  char const* const _PREHASH_AgentData = 0; // never dereferenced during this test  LLAgent gAgent; diff --git a/indra/test/message_tut.cpp b/indra/test/message_tut.cpp index 8718360f0c..76063e6db1 100644 --- a/indra/test/message_tut.cpp +++ b/indra/test/message_tut.cpp @@ -103,7 +103,7 @@ namespace tut  		~LLMessageSystemTestData()  		{  			// not end_messaging_system() -			delete gMessageSystem; +			delete static_cast<LLMessageSystem*>(gMessageSystem);  			gMessageSystem = NULL;  			// rm contents of temp dir | 
