Gray C++ Libraries  0.0.2
A set of C++ libraries for MSVC, GNU on Windows, WinCE, Linux
cSingleton.h
Go to the documentation of this file.
1 //
6 //
7 
8 #ifndef _INC_cSingleton_H
9 #define _INC_cSingleton_H
10 #ifndef NO_PRAGMA_ONCE
11 #pragma once
12 #endif
13 
14 #include "cNonCopyable.h"
15 #include "cThreadLock.h"
16 #include "cUnitTestDecl.h"
17 #include "cTypeInfo.h"
18 #include "cHeapObject.h"
19 #include "cObject.h"
20 #include "cDebugAssert.h"
21 
22 namespace Gray
23 {
24 #ifdef _MSC_VER
25 #pragma warning(disable:4355) // disable the warning regarding 'this' pointers being used in base member initializer list. Singletons rely on this action
26 #endif
27 
28  template <class TYPE>
30  {
37 
38  protected:
39  static TYPE* sm_pThe;
40  private:
42 
43  protected:
44  cSingletonStatic(TYPE* pObject) noexcept
45  {
48  DEBUG_ASSERT(pObject != nullptr, "cSingletonStatic");
49  if (sm_pThe != nullptr)
50  {
51  // THIS SHOULD NOT HAPPEN! Find who else is creating this singleton!
52  DEBUG_ASSERT(sm_pThe == nullptr, "cSingletonStatic");
53  return;
54  }
55  sm_pThe = pObject;
56  DEBUG_ASSERT(sm_pThe == this, "cSingletonStatic");
57  }
58  virtual ~cSingletonStatic() noexcept
59  {
61  if (sm_pThe != nullptr)
62  {
63  DEBUG_ASSERT(sm_pThe == this, "~cSingletonStatic");
64  sm_pThe = nullptr;
65  }
66  }
67 
68  public:
69  // the singleton accessor
70  static inline bool isSingleCreated() noexcept
71  {
72  return sm_pThe != nullptr;
73  }
74  static inline TYPE* get_SingleU() noexcept
75  {
77  return sm_pThe;
78  }
79  static inline TYPE* get_Single()
80  {
83  return sm_pThe; // get_SingleU()
84  }
85  template <class TYPE2>
86  static TYPE2* GRAYCALL get_SingleCast() // ASSUME TYPE2 derived from TYPE?
87  {
88  // DYNPTR_CAST or CHECKPTR_CAST for up-cast to some other type.
89  return CHECKPTR_CAST(TYPE2, get_Single());
90  }
91  static inline TYPE& I() noexcept
92  {
94  return *get_Single();
95  }
96  };
97 
98  template <class TYPE> TYPE* cSingletonStatic<TYPE>::sm_pThe = nullptr; // assume this is always set before any usage.
99 
100  class GRAYCORE_LINK cSingletonRegister : public CObject, public cHeapObject // IHeapObject
101  {
107 
108  friend class cSingletonManager;
109 
110  protected:
111 #ifndef UNDER_CE
112  HMODULE m_hModuleLoaded;
113 #endif
114  public:
116  protected:
117  cSingletonRegister(const TYPEINFO_t& rAddrCode) noexcept;
118  virtual ~cSingletonRegister();
119  void RegisterSingleton();
120  public:
121  static void GRAYCALL ReleaseModule(HMODULE hMod);
123  };
124 
125  template <class TYPE>
126  class cSingleton : public cSingletonStatic<TYPE>, public cSingletonRegister
127  {
137 
139 
140  protected:
141  cSingleton(TYPE* pObject, const TYPEINFO_t& rAddrCode = typeid(TYPE)) noexcept
142  : cSingletonStatic<TYPE>(pObject)
143  , cSingletonRegister(rAddrCode) // track the module for the codes implementation.
144  {
147  }
148  virtual ~cSingleton()
149  {
152  }
153 
154  public:
156  {
160 
162  {
163  // Double Check Lock for multi threaded
164  cThreadGuardFast threadguard(cSingletonRegister::sm_LockSingle); // thread sync critical section.
166  {
167  DEBUG_CHECK(!TYPE::isSingleCreated()); // SUPER_t::sm_pThe
168  new TYPE(); // assume it calls its constructor properly and sets sm_pThe
169  DEBUG_CHECK(TYPE::isSingleCreated()); // SUPER_t::sm_pThe
170  SUPER_t::sm_pThe->RegisterSingleton(); // Register only if i know it is dynamic. Not static.
171  }
172  }
173  return SUPER_t::sm_pThe;
174  }
175 
176  template <class TYPE2>
177  static TYPE2* GRAYCALL get_SingleT() // ASSUME TYPE2 derived from TYPE
178  {
182 
184  {
185  // Double Check Lock for multi threaded
186  cThreadGuardFast threadguard(cSingletonRegister::sm_LockSingle); // thread sync critical section.
188  {
189  ASSERT(!TYPE2::isSingleCreated()); // SUPER_t::sm_pThe
190  TYPE2* p = new TYPE2();
191  ASSERT(p == SUPER_t::sm_pThe);
192  ASSERT(TYPE2::isSingleCreated()); // SUPER_t::sm_pThe
193  SUPER_t::sm_pThe->RegisterSingleton(); // Register only if i know it is dynamic. Not static.
194  }
195  }
196  return CHECKPTR_CAST(TYPE2, SUPER_t::sm_pThe);
197  }
198 
199  static TYPE& GRAYCALL I()
200  {
202  return *get_Single();
203  }
204  };
205 }
206 
207 #endif // _INC_cSingleton_H
#define GRAYCORE_LINK
Definition: GrayCore.h:47
#define GRAYCALL
declare calling convention for static functions so everyone knows the arg passing scheme....
Definition: GrayCore.h:36
#define CHECKPTR_CAST(t, p)
Definition: PtrCast.h:50
#define TYPE
Definition: StrT.cpp:38
#define ASSERT(exp)
Definition: cDebugAssert.h:87
#define DEBUG_CHECK(exp)
Definition: cDebugAssert.h:90
#define DEBUG_ASSERT(exp, sDesc)
Definition: cDebugAssert.h:93
#define NonCopyable_IMPL(_TYPE)
Definition: cNonCopyable.h:34
#define UNITTEST_FRIEND(n)
Define this in the class body to be unit tested. Allow the unit test to access private/protected stuf...
Definition: cUnitTestDecl.h:17
Definition: cObject.h:67
Definition: cHeapObject.h:38
Definition: cLocker.h:72
Definition: cSingleton.h:101
static cThreadLockFast sm_LockSingle
common lock for all cSingleton.
Definition: cSingleton.h:115
cSingletonRegister(const TYPEINFO_t &rAddrCode) noexcept
Definition: cSingleton.cpp:103
HMODULE m_hModuleLoaded
What modules loaded this ? So singletons can be destroyed if DLL/SO unloads.
Definition: cSingleton.h:112
Definition: cSingleton.h:30
static TYPE * sm_pThe
pointer to the one and only object of this TYPE. ASSUME automatically init to = nullptr.
Definition: cSingleton.h:39
cSingletonStatic(TYPE *pObject) noexcept
Definition: cSingleton.h:44
static bool isSingleCreated() noexcept
Definition: cSingleton.h:70
static TYPE * get_SingleU() noexcept
Definition: cSingleton.h:74
static TYPE * get_Single()
Definition: cSingleton.h:79
static TYPE2 *__stdcall get_SingleCast()
Definition: cSingleton.h:86
virtual ~cSingletonStatic() noexcept
Definition: cSingleton.h:58
static TYPE & I() noexcept
Definition: cSingleton.h:91
Definition: cSingleton.h:127
virtual ~cSingleton()
Definition: cSingleton.h:148
static TYPE &__stdcall I()
Definition: cSingleton.h:199
static TYPE2 *__stdcall get_SingleT()
Definition: cSingleton.h:177
cSingleton(TYPE *pObject, const TYPEINFO_t &rAddrCode=typeid(TYPE)) noexcept
Definition: cSingleton.h:141
static TYPE *__stdcall get_Single()
Definition: cSingleton.h:155
Definition: cThreadLock.h:205
< The main namespace for all Core functions.
Definition: GrayCore.cpp:14
std::type_info TYPEINFO_t
Definition: cTypeInfo.h:29