ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
singletons.mpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of the \aliblong.
4/// With supporting legacy or module builds, .mpp-files are either recognized by the build-system
5/// as C++20 Module interface files, or are included by the
6/// \ref alib_manual_modules_impludes "import/include headers".
7///
8/// \emoji :copyright: 2013-2025 A-Worx GmbH, Germany.
9/// Published under \ref mainpage_license "Boost Software License".
10//==================================================================================================
11#if !defined(ALIB_C20_MODULES) || ((ALIB_C20_MODULES != 0) && (ALIB_C20_MODULES != 1))
12# error "Symbol ALIB_C20_MODULES has to be given to the compiler as either 0 or 1"
13#endif
14#if ALIB_C20_MODULES
15 module;
16#endif
17//========================================= Global Fragment ========================================
19
20#if ALIB_FEAT_SINGLETON_MAPPED
21# if !ALIB_MONOMEM || !ALIB_CONTAINERS
22# include <unordered_map>
23# endif
24# if !ALIB_MONOMEM
25# include <mutex>
26# endif
27#endif
28
29//============================================== Module ============================================
30#if ALIB_C20_MODULES
31/// This is a C++ Module of the \aliblong. Due to the dual-compile option - as either
32/// C++20 Modules or legacy C++ inclusion, the C++20 Module names are not of further interest
33/// or use.<br>
34/// In general, the names equal the names of the header files listed in the chapter
35/// \ref alib_manual_modules_impludes of the \alib User Manual.
36///
37 /// @see The documentation of the <em><b>"ALib Module"</b></em> given with the corresponding
38 /// Programmer's Manual \alib_singletons.
39 export module ALib.Singletons;
40 import ALib.Lang;
41# if ALIB_FEAT_SINGLETON_MAPPED
42# if ALIB_DEBUG && ALIB_STRINGS
43 import ALib.Strings;
44# endif
45# if ALIB_MONOMEM
46 import ALib.Monomem;
47# if ALIB_CONTAINERS
48 import ALib.Containers.HashTable;
49# endif
50# endif
51# endif
52#else
53# include "ALib.Lang.H"
54# if ALIB_FEAT_SINGLETON_MAPPED
55# if ALIB_DEBUG
56# include "ALib.Strings.H"
57# endif
58# if ALIB_MONOMEM
59# include "ALib.Monomem.H"
60# if ALIB_CONTAINERS
62# endif
63# endif
64# endif
65#endif
66
67//============================================= Exports ============================================
68#if ALIB_FEAT_SINGLETON_MAPPED && !DOXYGEN
69namespace alib::singletons::hidden {
70# if ALIB_MONOMEM && ALIB_CONTAINERS
71 extern HashMap<MonoAllocator, lang::TypeFunctors::Key, void *,
72 lang::TypeFunctors::Hash,
73 lang::TypeFunctors::EqualTo,
74 lang::Caching::Auto,
75 Recycling::None > singletonMap;
76# else
77 extern std::unordered_map< lang::TypeFunctors::Key, void *,
78 lang::TypeFunctors::Hash,
79 lang::TypeFunctors::EqualTo > singletonMap;
80# endif
81# if !ALIB_MONOMEM && !ALIB_SINGLE_THREADED
82 extern std::mutex singletonMapMutex; // if monomem is included, we use lock of global allocator
83# endif
84 extern ALIB_DLL void *getSingleton(const std::type_info &type);
85 extern ALIB_DLL void storeSingleton(const std::type_info &type, void *theSingleton);
86 extern ALIB_DLL void removeSingleton(const std::type_info &type);
87}
88#endif
89
91//==================================================================================================
92/// This class implements the "singleton pattern" for C++ using a common templated approach.
93/// In case of Windows OS and DLL usage, the class overcomes the problem of having
94/// a global data segment per DLL in addition to the one associated with the process that is using
95/// the DLL.
96///
97/// All details about implementation and usage of this class is provided in the module's
98/// \ref alib_mod_singletons "Programmer's Manual".
99///
100/// @tparam TDerivedClass Template parameter that denotes the name of the class that implements
101/// the singleton.
102//==================================================================================================
103template<typename TDerivedClass>
105 public:
106 #include "ALib.Lang.CIFunctions.H"
107 /// Creates (if not done, yet) and returns the singleton of type \p{TDerivedClass}.
108 /// @return The singleton instance.
109 static TDerivedClass &GetSingleton() {
110 #if !ALIB_FEAT_SINGLETON_MAPPED
111 // local static atomic instance of the singleton
112 static TDerivedClass singleton;
113 return singleton;
114 #else
115 #if ALIB_SINGLE_THREADED
116 using TSingletonStorage = TDerivedClass *;
117 #else
118 using TSingletonStorage = std::atomic<TDerivedClass *>;
119 #endif
120
121 // local static atomic pointer to the singleton (initialized once)
122 static TSingletonStorage singleton = nullptr;
123
124 // already created and known?
125 TDerivedClass *result = singleton;
126 if (result != nullptr)
127 return *result;
128
129 // create it
130 {
131 // for debug purposes, mapped singletons may be used with single-threaded
132 // applications. Still we do not lock then.
133 #if !ALIB_SINGLE_THREADED
134 # if ALIB_MONOMEM
136 # else
137 std::lock_guard<std::mutex> guard(hidden::singletonMapMutex);
138 # endif
139 #endif
140
141 // try loading from static map
142 void *storedSingleton = hidden::getSingleton(typeid(TDerivedClass));
143 if (storedSingleton != nullptr) {
144 singleton = dynamic_cast<TDerivedClass *>(
145 reinterpret_cast<Singleton<TDerivedClass> *>(storedSingleton));
146 return *singleton;
147 }
148
149 // create and store in map
150 auto *firstInstance = new TDerivedClass();
151 hidden::storeSingleton(typeid(TDerivedClass),
152 dynamic_cast<Singleton<TDerivedClass> *>(firstInstance));
153
154 // In debug mode, do not set this singleton right away. This "simulates"
155 // a windows DLL/Exec scope change
156 #if ALIB_DEBUG
157 return *firstInstance;
158 #else
159 return *(singleton = firstInstance);
160 #endif
161 }
162 #endif
163 }
164
165 #include "ALib.Lang.CIMethods.H"
166
167 /// Virtual destructor.
168 virtual ~Singleton() {
169 #if ALIB_FEAT_SINGLETON_MAPPED
170 #if !ALIB_SINGLE_THREADED
171 # if ALIB_MONOMEM
173 # else
174 std::lock_guard<std::mutex> guard(hidden::singletonMapMutex);
175 # endif
176 #endif
177 hidden::removeSingleton(typeid(TDerivedClass));
178 #endif
179 }
180}; // class Singleton
181
182//==================================================================================================
183/// Deletes the singletons.
184/// Upon exit of the process, programmers might want to explicitly free the hash table to avoid
185/// the detection of memory leaks by metrics tools like \http{Valgrind,valgrind.org/}.
186/// (Otherwise this can be omitted, as the memory is cleaned by the OS probably much faster when a
187/// process exits).
188///
189/// The \ref alib_mod_bs "standard bootstrap" code of \alib, hence the (overloaded)
190/// functions \ref alib::Shutdown will call this function.
191///
192/// \note This method is not thread-safe and hence must be called only on termination of the process
193/// when all threads that are using singletons are terminated.
194//==================================================================================================
195ALIB_DLL void shutdown();
196} // namespace [alib::singletons]
197
198ALIB_EXPORT namespace alib {
199/// Type alias in namespace \b alib.
200template<typename T>
202} // namespace [alib]
203
204//==================================================================================================
205//====== Debug functions
206//==================================================================================================
207#if ALIB_FEAT_SINGLETON_MAPPED && ALIB_DEBUG
209
210
211#if ALIB_MONOMEM && ALIB_CONTAINERS
212/// This debug helper function returns a type map with void pointers to all singletons.
213///
214/// The function may be used to investigate which singleton objects are created within a
215/// process and the point in (run-) time of creation.
216///
217/// \note
218/// This method is available only with debug-builds of %ALib and if
219/// code selection symbol \ref ALIB_FEAT_SINGLETON_MAPPED evaluates to true.<br>
220///
221/// \note
222/// If the \alibbuild includes \alib_strings then a simple dumping method is available with
223/// #DbgGetSingletons(NAString&).
224///
225/// \attention
226/// If modules \alib_monomem and \alib_containers are not included in the \alibbuild, then the
227/// result type of this method changes to <c>std::unordered_map<TypeKey, void*>&</c>.
228///
229/// @return A map of singleton types with void pointers to the singletons.
230//==================================================================================================
233 lang::TypeFunctors::Hash,
234 lang::TypeFunctors::EqualTo,
236 Recycling::None> &DbgGetSingletons();
237#else
238ALIB_DLL std::unordered_map<lang::TypeFunctors::Key, void *,
239 lang::TypeFunctors::Hash,
240 lang::TypeFunctors::EqualTo> &DbgGetSingletons();
241#endif
242
243#if ALIB_STRINGS
244/// This debug function writes all type names and addresses of each currently defined
245/// instance of class
246/// \alib{singletons;Singleton}
247/// into the given AString.<br>
248///
249/// \note
250/// This method is available only
251/// - with \ref ALIB_DEBUG "debug-builds" of the software,
252/// - if module \ref alib::strings "ALib Strings" is included in the \alibbuild, and
253/// - if code selection symbol \ref ALIB_FEAT_SINGLETON_MAPPED is \c true.
254///
255/// \note
256/// In case module <b>%ALib Strings</b> is not available, then alternative method
257/// \alib{singletons;DbgGetSingletons} can be used. This returns a list of
258/// \c std::type_info structs together with (void-) pointers to the singletons.
259///
260/// @param target The target string to write the list of singletons to.
261///
262/// @return The number of singletons written.
263 ALIB_DLL int DbgGetSingletons(NAString & target);
264#endif
265
266} // namespace [alib::singletons]
267#endif
static TDerivedClass & GetSingleton()
virtual ~Singleton()
Virtual destructor.
#define ALIB_DLL
Definition alib.inl:503
#define ALIB_LOCK_RECURSIVE_WITH(lock)
Definition alib.inl:1340
#define ALIB_EXPORT
Definition alib.inl:497
HashTable< TAllocator, TPairDescriptor< TKey, TMapped >, THash, TEqual, THashCaching, TRecycling > HashMap
@ Auto
Auto/default mode.
ALIB_DLL RecursiveLock GLOBAL_ALLOCATOR_LOCK
HashMap< MonoAllocator, lang::TypeFunctors::Key, void *, lang::TypeFunctors::Hash, lang::TypeFunctors::EqualTo, lang::Caching::Auto, Recycling::None > & DbgGetSingletons()
singletons::Singleton< T > Singleton
Type alias in namespace alib.
strings::TAString< nchar, lang::HeapAllocator > NAString
Type alias in namespace alib.
containers::HashMap< TAllocator, TKey, TMapped, THash, TEqual, THashCaching, TRecycling > HashMap
Type alias in namespace alib.
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
const ::std::type_info * Key
The key type.