BsModule.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #pragma once
  2. #include "BsPrerequisitesUtil.h"
  3. #include "BsException.h"
  4. namespace BansheeEngine
  5. {
  6. /** @addtogroup General
  7. * @{
  8. */
  9. /**
  10. * Represents one engine module. Essentially it is a specialized type of singleton. Module must be manually started up
  11. * and shut down before and after use.
  12. */
  13. template <class T>
  14. class Module
  15. {
  16. public:
  17. /**
  18. * Returns a reference to the module instance. Module has to have been started up first otherwise an exception will
  19. * 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. * Returns a pointer to the module instance. Module has to have been started up first otherwise an exception will
  37. * 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. /** Constructs and starts the module using the specified parameters. */
  54. template<class ...Args>
  55. static void startUp(Args &&...args)
  56. {
  57. if (!isShutDown())
  58. BS_EXCEPT(InternalErrorException, "Trying to start an already started module.");
  59. _instance() = bs_new<T>(std::forward<Args>(args)...);
  60. isShutDown() = false;
  61. ((Module*)_instance())->onStartUp();
  62. }
  63. /**
  64. * Constructs and starts a specialized type of the module. Provided type must derive from type the Module is
  65. * initialized with.
  66. */
  67. template<class SubType, class ...Args>
  68. static void startUp(Args &&...args)
  69. {
  70. static_assert(std::is_base_of<T, SubType>::value, "Provided type is not derived from type the Module is initialized with.");
  71. if (!isShutDown())
  72. BS_EXCEPT(InternalErrorException, "Trying to start an already started module.");
  73. _instance() = bs_new<SubType>(std::forward<Args>(args)...);
  74. isShutDown() = false;
  75. ((Module*)_instance())->onStartUp();
  76. }
  77. /** Shuts down this module and frees any resources it is using. */
  78. static void shutDown()
  79. {
  80. if (isShutDown() || isDestroyed())
  81. {
  82. BS_EXCEPT(InternalErrorException,
  83. "Trying to shut down an already shut down module.");
  84. }
  85. ((Module*)_instance())->onShutDown();
  86. bs_delete(_instance());
  87. isDestroyed() = true;
  88. }
  89. /** Query if the module has been started. */
  90. static bool isStarted()
  91. {
  92. return !isShutDown() && !isDestroyed();
  93. }
  94. protected:
  95. Module()
  96. {
  97. }
  98. virtual ~Module()
  99. {
  100. _instance() = nullptr;
  101. isDestroyed() = true;
  102. }
  103. Module(const Module&) { }
  104. Module& operator=(const Module&) { return *this; }
  105. /**
  106. * Override if you want your module to be notified once it has been constructed and started.
  107. *
  108. * @note Useful when your module is polymorphic and you cannot perform some implementation specific
  109. * initialization in constructor itself.
  110. */
  111. virtual void onStartUp() {}
  112. /**
  113. * Override if you want your module to be notified just before it is deleted.
  114. *
  115. * @note Useful when your module is polymorphic and you might want to perform some kind of clean up perhaps
  116. * overriding that of a base class.
  117. */
  118. virtual void onShutDown() {}
  119. /** Returns a singleton instance of this module. */
  120. static T*& _instance()
  121. {
  122. static T* inst = nullptr;
  123. return inst;
  124. }
  125. /**
  126. * Checks has the Module been shut down.
  127. *
  128. * @note If module was never even started, this will return false.
  129. */
  130. static bool& isDestroyed()
  131. {
  132. static bool inst = false;
  133. return inst;
  134. }
  135. /** Checks has the Module been started up. */
  136. static bool& isShutDown()
  137. {
  138. static bool inst = true;
  139. return inst;
  140. }
  141. };
  142. /** @} */
  143. }