From 9f962c03bf9080d67a8ea10aa53289c841fea781 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 27 May 2015 16:41:10 -0400
Subject: [PATCH] MAINT-5232: Extract LLInitClass, LLDestroyClass from
 llui/llui.h to a new llcommon/llinitdestroyclass.h. This mechanism is so
 general -- but has so many related moving parts -- that (a) it deserves to be
 in a header file all its own, instead of conflated with llui.h, and (b) it
 should be in llcommon where anyone can use it. It has no dependencies
 whatsoever on llui or anything viewer-specific. In this very changeset we
 changed one #include "llui.h" whose comment admits that it was only dragged
 in for LLDestroyClass.

---
 indra/llcommon/CMakeLists.txt       |   1 +
 indra/llcommon/llinitdestroyclass.h | 134 ++++++++++++++++++++++++++++
 indra/llui/llspellcheck.h           |   1 +
 indra/llui/llui.h                   |  89 ------------------
 indra/newview/llagentwearables.h    |   1 +
 indra/newview/llfavoritesbar.h      |   1 +
 indra/newview/llhints.h             |   1 +
 indra/newview/llimview.h            |   1 +
 indra/newview/llnavigationbar.h     |   1 +
 indra/newview/llpaneltopinfobar.h   |   1 +
 indra/newview/llsearchhistory.h     |   1 +
 indra/newview/llsyswellwindow.h     |   1 +
 indra/newview/llviewerinventory.h   |   2 +-
 13 files changed, 145 insertions(+), 90 deletions(-)
 create mode 100644 indra/llcommon/llinitdestroyclass.h

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index d2d507d6766..de5aa0fde44 100755
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -162,6 +162,7 @@ set(llcommon_HEADER_FILES
     llhash.h
     llheartbeat.h
     llindexedvector.h
+    llinitdestroyclass.h
     llinitparam.h
     llinstancetracker.h
     llkeythrottle.h
diff --git a/indra/llcommon/llinitdestroyclass.h b/indra/llcommon/llinitdestroyclass.h
new file mode 100644
index 00000000000..ca5c3f07de8
--- /dev/null
+++ b/indra/llcommon/llinitdestroyclass.h
@@ -0,0 +1,134 @@
+/**
+ * @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 "llerror.h"
+#include "llsingleton.h"
+#include <boost/function.hpp>
+#include <boost/signals2/signal.hpp>
+#include <typeinfo>
+
+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);
+
+#endif /* ! defined(LL_LLINITDESTROYCLASS_H) */
diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h
index 4ab80195ead..5ecc9aa1106 100755
--- a/indra/llui/llspellcheck.h
+++ b/indra/llui/llspellcheck.h
@@ -29,6 +29,7 @@
 
 #include "llsingleton.h"
 #include "llui.h"
+#include "llinitdestroyclass.h"
 #include <boost/signals2.hpp>
 
 class Hunspell;
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index c727f75c4fa..d7151dbee99 100755
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -344,95 +344,6 @@ class LLUI
 
 // 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/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 10044820208..7dc23c6402b 100755
--- 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/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index a370724947d..574617fa631 100755
--- 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;
diff --git a/indra/newview/llhints.h b/indra/newview/llhints.h
index ebffe561b95..dd6195a9ce3 100755
--- 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/llimview.h b/indra/newview/llimview.h
index f92eff48458..79be6fd9d3a 100755
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -33,6 +33,7 @@
 
 #include "lllogchat.h"
 #include "llvoicechannel.h"
+#include "llinitdestroyclass.h"
 
 class LLAvatarName;
 class LLFriendObserver;
diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h
index 7878bab24ed..de12a39547c 100755
--- a/indra/newview/llnavigationbar.h
+++ b/indra/newview/llnavigationbar.h
@@ -29,6 +29,7 @@
 
 #include "llpanel.h"
 #include "llbutton.h"
+#include "llinitdestroyclass.h"
 
 class LLLocationInputCtrl;
 class LLMenuGL;
diff --git a/indra/newview/llpaneltopinfobar.h b/indra/newview/llpaneltopinfobar.h
index f37bd9c0488..274d70c6f9d 100755
--- 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;
diff --git a/indra/newview/llsearchhistory.h b/indra/newview/llsearchhistory.h
index 3309a8fcac0..ade81675c21 100755
--- 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"
 
 /**
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
index 71b41476f53..cff3711bb9f 100755
--- 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/llviewerinventory.h b/indra/newview/llviewerinventory.h
index ca925656003..78b61d4fbc6 100755
--- 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
 
-- 
GitLab