MyGUI 3.4.3
MyGUI_Singleton.h
Go to the documentation of this file.
1/*
2 * This source file is part of MyGUI. For the latest info, see http://mygui.info/
3 * Distributed under the MIT License
4 * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
5 */
6
7#ifndef MYGUI_SINGLETON_H_
8#define MYGUI_SINGLETON_H_
9
10#include "MyGUI_Diagnostic.h"
11
12namespace MyGUI
13{
14
15#ifndef MYGUI_DONT_USE_OBSOLETE
16 template<class T>
17 class MYGUI_OBSOLETE("Singleton class is deprecated. Do not use singletons.") Singleton
18 {
19 public:
20 #if defined(__clang__)
21 // This constructor is called before the `T` object is fully constructed, and
22 // pointers are not dereferenced anyway, so UBSan shouldn't check vptrs.
23 __attribute__((no_sanitize("vptr")))
24 #endif
26 {
27 MYGUI_ASSERT(nullptr == msInstance, "Singleton instance " << getClassTypeName() << " already exsist");
28 msInstance = static_cast<T*>(this);
29 }
30
31 virtual ~Singleton()
32 {
33 if (nullptr == msInstance)
35 Critical,
36 "Destroying Singleton instance " << getClassTypeName() << " before constructing it.");
37 msInstance = nullptr;
38 }
39
40 static T& getInstance()
41 {
43 nullptr != getInstancePtr(),
44 "Singleton instance " << getClassTypeName() << " was not created");
45 return (*getInstancePtr());
46 }
47
48 static T* getInstancePtr()
49 {
50 return msInstance;
51 }
52
53 static std::string_view getClassTypeName()
54 {
55 return mClassTypeName;
56 }
57
58 private:
59 static T* msInstance;
60 static std::string_view mClassTypeName;
61 };
62#endif
63
64 /*
65 // Template Singleton class was replaces with a set of macroses, because there were too many issues with it,
66 // all appearing in different compilers:
67 // - incorrect exporting template class;
68 // - static variables in headers issues;
69 // - explicit specialization/implicit instantiation issues;
70 // - many other related compile errors.
71 // It is possible to move all template definitions into cpp code, but result looked even worse.
72
73 // Usage:
74
75 // in header
76 class MyClass
77 {
78 MYGUI_SINGLETON_DECLARATION(MyClass);
79
80 MyClass()
81 // ...
82 };
83
84 // in cpp
85 MYGUI_SINGLETON_DEFINITION(MyClass);
86
87 MyClass() : mSingletonHolder(this)
88 {
89 // ...
90 }
91*/
92
93 // proxy class to avoid calling initialiseSingleton/shutdownSingleton in constructor/destructor
94 template<class T>
96 {
97 public:
98 SingletonHolder(T* instance) :
99 mInstance(instance)
100 {
101 mInstance->initialiseSingleton();
102 }
104 {
105 mInstance->shutdownSingleton();
106 }
107
108 private:
109 T* mInstance;
110 };
111
112#define MYGUI_SINGLETON_DECLARATION(ClassName) \
113private: \
114 friend MyGUI::SingletonHolder<ClassName>; \
115 MyGUI::SingletonHolder<ClassName> mSingletonHolder; \
116 void initialiseSingleton(); \
117 void shutdownSingleton(); \
118\
119public: \
120 static ClassName& getInstance(); \
121 static ClassName* getInstancePtr(); \
122 static std::string_view getClassTypeName(); \
123 ClassName(const ClassName&) = delete; \
124 ClassName& operator=(const ClassName&) = delete
125
126#define MYGUI_SINGLETON_DEFINITION(ClassName) \
127 static ClassName* ClassName##Instance = nullptr; \
128 static std::string_view ClassName##ClassTypeName = #ClassName; \
129\
130 void ClassName::initialiseSingleton() \
131 { \
132 MYGUI_ASSERT( \
133 nullptr == ClassName##Instance, \
134 "Singleton instance " << getClassTypeName() << " already exsist"); \
135 ClassName##Instance = this; \
136 } \
137\
138 void ClassName::shutdownSingleton() \
139 { \
140 if (nullptr == ClassName##Instance) \
141 MYGUI_LOG(Critical, "Destroying Singleton instance " << getClassTypeName() << " before constructing it."); \
142 ClassName##Instance = nullptr; \
143 } \
144\
145 ClassName& ClassName::getInstance() \
146 { \
147 MYGUI_ASSERT(nullptr != getInstancePtr(), "Singleton instance " << getClassTypeName() << " was not created"); \
148 return (*getInstancePtr()); \
149 } \
150\
151 ClassName* ClassName::getInstancePtr() \
152 { \
153 return ClassName##Instance; \
154 } \
155\
156 std::string_view ClassName::getClassTypeName() \
157 { \
158 return ClassName##ClassTypeName; \
159 } \
160 static_assert(true, "require semicolon")
161
162} // namespace MyGUI
163
164#endif // MYGUI_SINGLETON_H_
#define MYGUI_ASSERT(exp, dest)
#define MYGUI_OBSOLETE(text)
#define MYGUI_LOG(level, text)
static T * getInstancePtr()
static std::string_view getClassTypeName()
static T & getInstance()