BsModule.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. //__________________________ Banshee Project - A modern game development toolkit _________________________________//
  2. //_____________________________________ www.banshee-project.com __________________________________________________//
  3. //________________________ Copyright (c) 2014 Marko Pintera. All rights reserved. ________________________________//
  4. #pragma once
  5. #include "BsPrerequisitesUtil.h"
  6. #include "BsException.h"
  7. namespace BansheeEngine
  8. {
  9. /**
  10. * @brief Represents one engine module. Essentially it is a specialized type of singleton.
  11. * Module must be manually started up and shut down before and after use.
  12. */
  13. template <class T>
  14. class Module
  15. {
  16. public:
  17. /**
  18. * @brief Returns a reference to the module instance. Module has to have been started up
  19. * first otherwise an exception will be thrown.
  20. */
  21. static T& instance()
  22. {
  23. if(isShutDown())
  24. {
  25. BS_EXCEPT(InternalErrorException,
  26. "Trying to access a module but it hasn't been started up yet.");
  27. }
  28. if (isDestroyed())
  29. {
  30. BS_EXCEPT(InternalErrorException,
  31. "Trying to access a destroyed module.");
  32. }
  33. return *_instance();
  34. }
  35. /**
  36. * @brief Returns a pointer to the module instance. Module has to have been started up
  37. * first otherwise an exception will be thrown.
  38. */
  39. static T* instancePtr()
  40. {
  41. if (isShutDown())
  42. {
  43. BS_EXCEPT(InternalErrorException,
  44. "Trying to access a module but it hasn't been started up yet.");
  45. }
  46. if (isDestroyed())
  47. {
  48. BS_EXCEPT(InternalErrorException,
  49. "Trying to access a destroyed module.");
  50. }
  51. return _instance();
  52. }
  53. /**
  54. * @brief Constructs and starts the module using the specified parameters.
  55. */
  56. template<class ...Args>
  57. static void startUp(Args &&...args)
  58. {
  59. if (!isShutDown())
  60. BS_EXCEPT(InternalErrorException, "Trying to start an already started module.");
  61. _instance() = bs_new<T>(std::forward<Args>(args)...);
  62. isShutDown() = false;
  63. ((Module*)_instance())->onStartUp();
  64. }
  65. /**
  66. * @brief Constructs and starts a specialized type of the module. Provided type
  67. * must derive from type the Module is initialized with.
  68. */
  69. template<class SubType, class ...Args>
  70. static void startUp(Args &&...args)
  71. {
  72. static_assert(std::is_base_of<T, SubType>::value, "Provided type is not derived from type the Module is initialized with.");
  73. if (!isShutDown())
  74. BS_EXCEPT(InternalErrorException, "Trying to start an already started module.");
  75. _instance() = bs_new<SubType>(std::forward<Args>(args)...);
  76. isShutDown() = false;
  77. ((Module*)_instance())->onStartUp();
  78. }
  79. /**
  80. * @brief Shuts down this module and frees any resources it is using.
  81. */
  82. static void shutDown()
  83. {
  84. if (isShutDown())
  85. {
  86. BS_EXCEPT(InternalErrorException,
  87. "Trying to shut down an already shut down module.");
  88. }
  89. ((Module*)_instance())->onShutDown();
  90. bs_delete(_instance());
  91. isShutDown() = true;
  92. }
  93. /**
  94. * @brief Query if the module has been started.
  95. */
  96. static bool isStarted()
  97. {
  98. return !isShutDown() && !isDestroyed();
  99. }
  100. protected:
  101. Module()
  102. {
  103. }
  104. virtual ~Module()
  105. {
  106. _instance() = nullptr;
  107. isDestroyed() = true;
  108. }
  109. Module(const Module&) { }
  110. Module& operator=(const Module&) { return *this; }
  111. /**
  112. * @brief Override if you want your module to be notified once it has been constructed and started.
  113. *
  114. * @note Useful when your module is polymorphic and you cannot perform
  115. * some implementation specific initialization in constructor itself.
  116. */
  117. virtual void onStartUp() {}
  118. /**
  119. * @brief Override if you want your module to be notified just before it is deleted.
  120. *
  121. * @note Useful when your module is polymorphic and you might want to perform some
  122. * kind of clean up perhaps overriding that of a base class.
  123. */
  124. virtual void onShutDown() {}
  125. /**
  126. * @brief Returns a singleton instance of this module. Throws an exception
  127. * if module is not yet initialized.
  128. */
  129. static T*& _instance()
  130. {
  131. static T* inst = nullptr;
  132. return inst;
  133. }
  134. /**
  135. * @brief Checks has the Module been shut down.
  136. *
  137. * @note If module was never even started, this will return false.
  138. */
  139. static bool& isDestroyed()
  140. {
  141. static bool inst = false;
  142. return inst;
  143. }
  144. /**
  145. * @brief Checks has the Module been started up.
  146. */
  147. static bool& isShutDown()
  148. {
  149. static bool inst = true;
  150. return inst;
  151. }
  152. };
  153. }