summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/integration_tests/llimage_libtest/llimage_libtest.cpp3
-rw-r--r--indra/llappearance/llavatarappearancedefines.h3
-rw-r--r--indra/llappearance/lltexlayer.h4
-rw-r--r--indra/llappearance/llwearabletype.cpp3
-rw-r--r--indra/llcommon/CMakeLists.txt11
-rw-r--r--indra/llcommon/llapp.cpp3
-rw-r--r--indra/llcommon/llassettype.cpp3
-rw-r--r--indra/llcommon/llcleanup.cpp29
-rw-r--r--indra/llcommon/llcleanup.h33
-rw-r--r--indra/llcommon/llcommon.cpp5
-rw-r--r--indra/llcommon/llcoro_get_id.cpp32
-rw-r--r--indra/llcommon/llcoro_get_id.h30
-rw-r--r--indra/llcommon/llcoros.cpp114
-rw-r--r--indra/llcommon/llcoros.h26
-rw-r--r--indra/llcommon/llerror.cpp53
-rw-r--r--indra/llcommon/llerror.h1
-rw-r--r--indra/llcommon/llerrorcontrol.h5
-rw-r--r--indra/llcommon/llevents.h3
-rw-r--r--indra/llcommon/llheteromap.cpp32
-rw-r--r--indra/llcommon/llheteromap.h95
-rw-r--r--indra/llcommon/llinitdestroyclass.cpp30
-rw-r--r--indra/llcommon/llinitdestroyclass.h175
-rw-r--r--indra/llcommon/llmetricperformancetester.cpp2
-rw-r--r--indra/llcommon/llmetricperformancetester.h2
-rw-r--r--indra/llcommon/llpounceable.h216
-rw-r--r--indra/llcommon/llregistry.h7
-rw-r--r--indra/llcommon/llsingleton.cpp440
-rw-r--r--indra/llcommon/llsingleton.h637
-rw-r--r--indra/llcommon/tests/llheteromap_test.cpp163
-rw-r--r--indra/llcommon/tests/llpounceable_test.cpp230
-rw-r--r--indra/llcommon/tests/llsingleton_test.cpp207
-rw-r--r--indra/llcorehttp/CMakeLists.txt5
-rwxr-xr-x[-rw-r--r--]indra/llcorehttp/tests/llcorehttp_test.cpp3
-rw-r--r--indra/llcorehttp/tests/test_httprequest.hpp67
-rw-r--r--indra/llcrashlogger/llcrashlogger.cpp3
-rw-r--r--indra/llinventory/lleconomy.cpp25
-rw-r--r--indra/llinventory/lleconomy.h21
-rw-r--r--indra/llinventory/llfoldertype.cpp3
-rw-r--r--indra/llinventory/llinventorytype.cpp3
-rw-r--r--indra/llmessage/llcoproceduremanager.h6
-rw-r--r--indra/llmessage/llexperiencecache.h3
-rw-r--r--indra/llmessage/llproxy.h8
-rw-r--r--indra/llmessage/message.cpp7
-rw-r--r--indra/llmessage/message.h7
-rw-r--r--indra/llmessage/tests/llhttpclient_test.cpp3
-rw-r--r--indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp3
-rw-r--r--indra/llmessage/tests/lltrustedmessageservice_test.cpp3
-rw-r--r--indra/llmessage/tests/networkio.h3
-rw-r--r--indra/llui/llclipboard.h4
-rw-r--r--indra/llui/llcommandmanager.h6
-rw-r--r--indra/llui/llcontainerview.h4
-rw-r--r--indra/llui/llfunctorregistry.h16
-rw-r--r--indra/llui/lllayoutstack.h4
-rw-r--r--indra/llui/llmenugl.h4
-rw-r--r--indra/llui/llnotifications.h4
-rw-r--r--indra/llui/llpanel.h3
-rw-r--r--indra/llui/llresmgr.h4
-rw-r--r--indra/llui/llscrollcontainer.h4
-rw-r--r--indra/llui/llspellcheck.h5
-rw-r--r--indra/llui/llstatview.h4
-rw-r--r--indra/llui/lltextparser.h4
-rw-r--r--indra/llui/lltooltip.h3
-rw-r--r--indra/llui/llui.cpp3
-rw-r--r--indra/llui/llui.h89
-rw-r--r--indra/llui/lluicolortable.h3
-rw-r--r--indra/llui/lluictrl.h13
-rw-r--r--indra/llui/lluictrlfactory.h76
-rw-r--r--indra/llui/llurlregistry.h7
-rw-r--r--indra/llui/llview.cpp2
-rw-r--r--indra/llui/llviewereventrecorder.h7
-rw-r--r--indra/llui/llviewquery.h6
-rw-r--r--indra/llui/llxuiparser.h8
-rwxr-xr-x[-rw-r--r--]indra/llui/tests/llurlentry_stub.cpp3
-rw-r--r--indra/media_plugins/cef/windows_volume_catcher.cpp9
-rw-r--r--indra/newview/llaccountingcostmanager.h4
-rw-r--r--indra/newview/llagentpicksinfo.h8
-rw-r--r--indra/newview/llagentwearables.h1
-rw-r--r--indra/newview/llappearancemgr.cpp1
-rw-r--r--indra/newview/llappearancemgr.h8
-rw-r--r--indra/newview/llappviewer.cpp85
-rw-r--r--indra/newview/llattachmentsmgr.h6
-rw-r--r--indra/newview/llautoreplace.h3
-rw-r--r--indra/newview/llavataractions.cpp2
-rw-r--r--indra/newview/llavatariconctrl.h11
-rw-r--r--indra/newview/llavatarpropertiesprocessor.h7
-rw-r--r--indra/newview/llavatarrenderinfoaccountant.h6
-rw-r--r--indra/newview/llavatarrendernotifier.h4
-rw-r--r--indra/newview/llchannelmanager.h6
-rw-r--r--indra/newview/llchicletbar.cpp2
-rw-r--r--indra/newview/llchicletbar.h5
-rw-r--r--indra/newview/llconversationlog.h3
-rw-r--r--indra/newview/lldaycyclemanager.h2
-rw-r--r--indra/newview/lldeferredsounds.h2
-rw-r--r--indra/newview/lldonotdisturbnotificationstorage.cpp3
-rw-r--r--indra/newview/lldonotdisturbnotificationstorage.h6
-rw-r--r--indra/newview/llenvmanager.h4
-rw-r--r--indra/newview/llestateinfomodel.h4
-rw-r--r--indra/newview/llexperiencelog.h3
-rw-r--r--indra/newview/llfacebookconnect.h5
-rw-r--r--indra/newview/llfavoritesbar.h12
-rw-r--r--indra/newview/llfeaturemanager.h26
-rw-r--r--indra/newview/llflickrconnect.h5
-rw-r--r--indra/newview/llfloaterbvhpreview.cpp2
-rw-r--r--indra/newview/llfloaterimcontainer.cpp2
-rw-r--r--indra/newview/llfloaternamedesc.cpp4
-rw-r--r--indra/newview/llfriendcard.h5
-rw-r--r--indra/newview/llgesturemgr.h4
-rw-r--r--indra/newview/llgroupmgr.h4
-rw-r--r--indra/newview/llhints.h1
-rw-r--r--indra/newview/llhudmanager.h4
-rw-r--r--indra/newview/llimagefiltersmanager.h5
-rw-r--r--indra/newview/llimview.h6
-rw-r--r--indra/newview/llinventoryicon.cpp3
-rw-r--r--indra/newview/llinventorymodelbackgroundfetch.h4
-rw-r--r--indra/newview/lllocationhistory.h2
-rw-r--r--indra/newview/lllogchat.cpp19
-rw-r--r--indra/newview/lllogininstance.h6
-rw-r--r--indra/newview/llmainlooprepeater.h3
-rw-r--r--indra/newview/llmarketplacefunctions.h13
-rw-r--r--indra/newview/llmaterialmgr.h4
-rw-r--r--indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp3
-rw-r--r--indra/newview/llmenuoptionpathfindingrebakenavmesh.h4
-rw-r--r--indra/newview/llmutelist.cpp29
-rw-r--r--indra/newview/llmutelist.h9
-rwxr-xr-x[-rw-r--r--]indra/newview/llnavigationbar.h7
-rw-r--r--indra/newview/llnotificationmanager.h6
-rw-r--r--indra/newview/llnotificationstorage.cpp7
-rw-r--r--indra/newview/lloutfitgallery.cpp2
-rw-r--r--indra/newview/lloutfitobserver.h5
-rw-r--r--indra/newview/llpaneleditwearable.cpp3
-rw-r--r--indra/newview/llpanelmaininventory.cpp2
-rw-r--r--indra/newview/llpanelsnapshotinventory.cpp6
-rw-r--r--indra/newview/llpanelsnapshotoptions.cpp6
-rw-r--r--indra/newview/llpanelteleporthistory.cpp4
-rw-r--r--indra/newview/llpaneltopinfobar.h6
-rw-r--r--indra/newview/llpathfindingmanager.cpp3
-rw-r--r--indra/newview/llpathfindingmanager.h6
-rw-r--r--indra/newview/llpathfindingpathtool.cpp1
-rw-r--r--indra/newview/llpathfindingpathtool.h6
-rw-r--r--indra/newview/llpersistentnotificationstorage.cpp5
-rw-r--r--indra/newview/llpersistentnotificationstorage.h4
-rw-r--r--indra/newview/llpresetsmanager.h6
-rw-r--r--indra/newview/llproductinforequest.h3
-rw-r--r--indra/newview/llrecentpeople.h1
-rw-r--r--indra/newview/llregioninfomodel.h3
-rw-r--r--indra/newview/llremoteparcelrequest.h3
-rw-r--r--indra/newview/llrootview.h4
-rw-r--r--indra/newview/llscenemonitor.h4
-rw-r--r--indra/newview/llscriptfloater.h1
-rw-r--r--indra/newview/llsearchhistory.h3
-rw-r--r--indra/newview/llselectmgr.h6
-rw-r--r--indra/newview/llsnapshotlivepreview.cpp2
-rw-r--r--indra/newview/llspeakers.h8
-rw-r--r--indra/newview/llspeakingindicatormanager.cpp6
-rw-r--r--indra/newview/llstartup.cpp3
-rw-r--r--indra/newview/llstylemap.h1
-rw-r--r--indra/newview/llsyntaxid.h5
-rw-r--r--indra/newview/llsyswellwindow.h1
-rw-r--r--indra/newview/llteleporthistory.h5
-rw-r--r--indra/newview/llteleporthistorystorage.h5
-rw-r--r--indra/newview/lltextureatlasmanager.h5
-rw-r--r--indra/newview/lltoolbrush.h2
-rw-r--r--indra/newview/lltoolcomp.cpp2
-rw-r--r--indra/newview/lltoolcomp.h28
-rw-r--r--indra/newview/lltooldraganddrop.h5
-rw-r--r--indra/newview/lltoolface.h4
-rw-r--r--indra/newview/lltoolfocus.h4
-rw-r--r--indra/newview/lltoolgrab.cpp52
-rw-r--r--indra/newview/lltoolgrab.h21
-rw-r--r--indra/newview/lltoolindividual.h4
-rw-r--r--indra/newview/lltoolmgr.h4
-rw-r--r--indra/newview/lltoolobjpicker.h2
-rw-r--r--indra/newview/lltoolpie.h2
-rw-r--r--indra/newview/lltoolpipette.h4
-rw-r--r--indra/newview/lltoolselectland.h4
-rw-r--r--indra/newview/lltransientfloatermgr.h4
-rw-r--r--indra/newview/lltwitterconnect.h4
-rw-r--r--indra/newview/llviewerassettype.cpp3
-rw-r--r--indra/newview/llviewerassetupload.cpp2
-rw-r--r--indra/newview/llvieweraudio.h6
-rw-r--r--indra/newview/llviewercamera.h3
-rw-r--r--indra/newview/llviewerfoldertype.cpp3
-rw-r--r--indra/newview/llviewerhelp.h2
-rw-r--r--indra/newview/llviewerinventory.cpp196
-rw-r--r--indra/newview/llviewerinventory.h2
-rw-r--r--indra/newview/llviewerjoystick.h6
-rw-r--r--indra/newview/llviewerkeyboard.cpp1
-rw-r--r--indra/newview/llviewermediafocus.h6
-rw-r--r--indra/newview/llviewermenu.cpp5
-rw-r--r--indra/newview/llviewermenufile.cpp4
-rw-r--r--indra/newview/llviewermessage.cpp4
-rw-r--r--indra/newview/llviewermessage.h1
-rw-r--r--indra/newview/llviewernetwork.cpp7
-rw-r--r--indra/newview/llviewernetwork.h9
-rw-r--r--indra/newview/llviewerobject.cpp11
-rw-r--r--indra/newview/llviewerparcelmgr.h5
-rw-r--r--indra/newview/llviewerpartsim.h3
-rw-r--r--indra/newview/llviewerstats.h8
-rw-r--r--indra/newview/llviewerstatsrecorder.h6
-rw-r--r--indra/newview/llviewertexturelist.h1
-rw-r--r--indra/newview/llviewerwindow.cpp24
-rw-r--r--indra/newview/llvocache.h8
-rw-r--r--indra/newview/llvoicechannel.h2
-rw-r--r--indra/newview/llvoiceclient.h10
-rw-r--r--indra/newview/llvoicevivox.h13
-rw-r--r--indra/newview/llwatchdog.h4
-rw-r--r--indra/newview/llwaterparammanager.h6
-rw-r--r--indra/newview/llwearableitemslist.h2
-rw-r--r--indra/newview/llwearablelist.h4
-rw-r--r--indra/newview/llwindebug.h1
-rw-r--r--indra/newview/llwlparammanager.h6
-rw-r--r--indra/newview/llworld.h2
-rw-r--r--indra/newview/llworldmap.h4
-rw-r--r--indra/newview/llworldmapmessage.h6
-rw-r--r--indra/newview/pipeline.cpp3
-rw-r--r--indra/newview/tests/llremoteparcelrequest_test.cpp3
-rw-r--r--indra/test/message_tut.cpp2
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 &center,
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 &region_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