Singleton.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Util/Assert.h>
  7. #include <AnKi/Util/Thread.h>
  8. #include <utility>
  9. namespace anki
  10. {
  11. /// @addtogroup util_patterns
  12. /// @{
  13. /// This template makes a class singleton
  14. template<typename T>
  15. class Singleton
  16. {
  17. public:
  18. using Value = T;
  19. // Non copyable
  20. Singleton(const Singleton&) = delete;
  21. Singleton& operator=(const Singleton&) = delete;
  22. // Non constructable
  23. Singleton() = delete;
  24. ~Singleton() = delete;
  25. /// Get instance
  26. static Value& get()
  27. {
  28. return *(m_instance ? m_instance : (m_instance = new Value));
  29. }
  30. /// Cleanup
  31. static void destroy()
  32. {
  33. if(m_instance)
  34. {
  35. delete m_instance;
  36. }
  37. }
  38. private:
  39. static Value* m_instance;
  40. };
  41. template<typename T>
  42. typename Singleton<T>::Value* Singleton<T>::m_instance = nullptr;
  43. /// This template makes a class with a destructor with arguments singleton
  44. template<typename T>
  45. class SingletonInit
  46. {
  47. public:
  48. using Value = T;
  49. // Non copyable
  50. SingletonInit(const SingletonInit&) = delete;
  51. SingletonInit& operator=(const SingletonInit&) = delete;
  52. // Non constructable
  53. SingletonInit() = delete;
  54. ~SingletonInit() = delete;
  55. /// Init the singleton
  56. template<typename... TArgs>
  57. static void init(TArgs... args)
  58. {
  59. ANKI_ASSERT(m_instance == nullptr);
  60. m_instance = new Value(std::forward<TArgs>(args)...);
  61. }
  62. /// Get instance
  63. static Value& get()
  64. {
  65. ANKI_ASSERT(m_instance != nullptr);
  66. return *m_instance;
  67. }
  68. /// Cleanup
  69. static void destroy()
  70. {
  71. if(m_instance)
  72. {
  73. delete m_instance;
  74. }
  75. }
  76. static Bool isInitialized()
  77. {
  78. return m_instance != nullptr;
  79. }
  80. private:
  81. static Value* m_instance;
  82. };
  83. template<typename T>
  84. typename SingletonInit<T>::Value* SingletonInit<T>::m_instance = nullptr;
  85. /// This template makes a class singleton with thread local instance
  86. template<typename T>
  87. class SingletonThreadLocal
  88. {
  89. public:
  90. using Value = T;
  91. // Non copyable
  92. SingletonThreadLocal(const SingletonThreadLocal&) = delete;
  93. SingletonThreadLocal& operator=(const SingletonThreadLocal&) = delete;
  94. // Non constructable
  95. SingletonThreadLocal() = delete;
  96. ~SingletonThreadLocal() = delete;
  97. /// Get instance
  98. static Value& get()
  99. {
  100. return *(m_instance ? m_instance : (m_instance = new Value));
  101. }
  102. /// Cleanup
  103. void destroy()
  104. {
  105. if(m_instance)
  106. {
  107. delete m_instance;
  108. }
  109. }
  110. private:
  111. static thread_local Value* m_instance;
  112. };
  113. template<typename T>
  114. thread_local typename SingletonThreadLocal<T>::Value* SingletonThreadLocal<T>::m_instance = nullptr;
  115. /// This template makes a class with a destructor with arguments singleton
  116. template<typename T>
  117. class SingletonThreadsafe
  118. {
  119. public:
  120. using Value = T;
  121. // Non copyable
  122. SingletonThreadsafe(const SingletonThreadsafe&) = delete;
  123. SingletonThreadsafe& operator=(const SingletonThreadsafe&) = delete;
  124. // Non constructable
  125. SingletonThreadsafe() = delete;
  126. ~SingletonThreadsafe() = delete;
  127. /// Get instance
  128. static Value& get()
  129. {
  130. LockGuard<Mutex> lock(m_mtx);
  131. return *(m_instance ? m_instance : (m_instance = new Value));
  132. }
  133. /// Cleanup
  134. static void destroy()
  135. {
  136. LockGuard<Mutex> lock(m_mtx);
  137. if(m_instance)
  138. {
  139. delete m_instance;
  140. }
  141. }
  142. private:
  143. static Value* m_instance;
  144. static Mutex m_mtx;
  145. };
  146. template<typename T>
  147. typename SingletonThreadsafe<T>::Value* SingletonThreadsafe<T>::m_instance = nullptr;
  148. template<typename T>
  149. Mutex SingletonThreadsafe<T>::m_mtx;
  150. /// @}
  151. } // end namespace anki