Singleton.h 3.5 KB

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