llinitdestroyclass.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /**
  2. * @file llinitdestroyclass.h
  3. * @brief LLInitClass / LLDestroyClass mechanism
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #ifndef LL_LLINITDESTROYCLASS_H
  33. #define LL_LLINITDESTROYCLASS_H
  34. #include "boost/function.hpp"
  35. #include "boost/signals2.hpp"
  36. #include "llerror.h"
  37. #include "llsingleton.h" // Also includes <typeinfo>
  38. // LLCallbackRegistry is an implementation detail base class for
  39. // LLInitClassList and LLDestroyClassList. It is a very thin wrapper around a
  40. // boost.signals2 signal object.
  41. class LLCallbackRegistry
  42. {
  43. public:
  44. typedef boost::signals2::signal<void()> callback_signal_t;
  45. void registerCallback(const callback_signal_t::slot_type& slot)
  46. {
  47. mCallbacks.connect(slot);
  48. }
  49. void fireCallbacks()
  50. {
  51. mCallbacks();
  52. }
  53. private:
  54. callback_signal_t mCallbacks;
  55. };
  56. // LLInitClassList is the LLCallbackRegistry for LLInitClass. It stores the
  57. // registered initClass() methods. It must be an LLSingleton because
  58. // LLInitClass registers its initClass() method at static construction time
  59. // (before main()), requiring LLInitClassList to be fully constructed on
  60. // demand regardless of module initialization order.
  61. class LLInitClassList : public LLCallbackRegistry,
  62. public LLSingleton<LLInitClassList>
  63. {
  64. friend class LLSingleton<LLInitClassList>;
  65. private:
  66. LLInitClassList() {}
  67. };
  68. // LLDestroyClassList is the LLCallbackRegistry for LLDestroyClass. It stores
  69. // the registered destroyClass() methods. It must be an LLSingleton because
  70. // LLDestroyClass registers its destroyClass() method at static construction
  71. // time (before main()), requiring LLDestroyClassList to be fully constructed
  72. // on demand regardless of module initialization order.
  73. class LLDestroyClassList : public LLCallbackRegistry,
  74. public LLSingleton<LLDestroyClassList>
  75. {
  76. friend class LLSingleton<LLDestroyClassList>;
  77. private:
  78. LLDestroyClassList() {}
  79. };
  80. // LLRegisterWith is an implementation detail for LLInitClass and
  81. // LLDestroyClass. It is intended to be used as a static class member whose
  82. // constructor registers the specified callback with the LLMumbleClassList
  83. // singleton registry specified as the template argument.
  84. template<typename T>
  85. class LLRegisterWith
  86. {
  87. public:
  88. LLRegisterWith(boost::function<void()> func)
  89. {
  90. T::getInstance()->registerCallback(func);
  91. }
  92. // This avoids a MSVC bug where non-referenced static members are
  93. // "optimized" away even if their constructors have side effects
  94. void reference()
  95. {
  96. #if LL_WINDOWS && !LL_CLANG
  97. S32 dummy;
  98. dummy = 0;
  99. #endif
  100. }
  101. };
  102. // Derive MyClass from LLInitClass<MyClass> (the Curiously Recurring Template
  103. // Pattern) to ensure that the static method MyClass::initClass() will be
  104. // called (along with all other LLInitClass<T> subclass initClass() methods)
  105. // when someone calls LLInitClassList::getInstance()->fireCallbacks(). This
  106. // gives the application specific control over the timing of all such
  107. // initializations, without having to insert calls for every such class into
  108. // generic application code.
  109. template<typename T>
  110. class LLInitClass
  111. {
  112. public:
  113. LLInitClass() { sRegister.reference(); }
  114. public:
  115. // When this static member is initialized, the subclass initClass() method
  116. // is registered on LLInitClassList. See sRegister definition below.
  117. static LLRegisterWith<LLInitClassList> sRegister;
  118. private:
  119. // Provides a default initClass() method in case subclass misspells (or
  120. // omits) initClass(). This turns a potential build error into a fatal
  121. // runtime error.
  122. static void initClass()
  123. {
  124. llerrs << "No static initClass() method defined for "
  125. << typeid(T).name() << llendl;
  126. }
  127. };
  128. // Derive MyClass from LLDestroyClass<MyClass> (the Curiously Recurring
  129. // Template Pattern) to ensure that the static method MyClass::destroyClass()
  130. // will be called (along with other LLDestroyClass<T> subclass destroyClass()
  131. // methods) when someone calls
  132. // LLDestroyClassList::getInstance()->fireCallbacks().
  133. // This gives the application specific control over the timing of all such
  134. // cleanup calls, without having to insert calls for every such class into
  135. // generic application code.
  136. template<typename T>
  137. class LLDestroyClass
  138. {
  139. public:
  140. LLDestroyClass() { sRegister.reference(); }
  141. public:
  142. // When this static member is initialized, the subclass destroyClass()
  143. // method is registered on LLInitClassList. See sRegister definition below.
  144. static LLRegisterWith<LLDestroyClassList> sRegister;
  145. private:
  146. // Provides a default destroyClass() method in case subclass misspells (or
  147. // omits) destroyClass(). This turns a potential build error into a fatal
  148. // runtime error.
  149. static void destroyClass()
  150. {
  151. llerrs << "No static destroyClass() method defined for "
  152. << typeid(T).name() << llendl;
  153. }
  154. };
  155. // Here is where LLInitClass<T> specifies the subclass initClass() method.
  156. template <typename T> LLRegisterWith<LLInitClassList> LLInitClass<T>::sRegister(&T::initClass);
  157. // Here is where LLDestroyClass<T> specifies the subclass destroyClass() method
  158. template <typename T> LLRegisterWith<LLDestroyClassList> LLDestroyClass<T>::sRegister(&T::destroyClass);
  159. #endif // LL_LLINITDESTROYCLASS_H