ALib C++ Library
Library Version: 2510 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/// This chapter, among others, provides further explanations.
37 export module ALib.Singletons;
38 import ALib.Lang;
39# if ALIB_FEAT_SINGLETON_MAPPED
40# if ALIB_DEBUG && ALIB_STRINGS
41 import ALib.Strings;
42# endif
43# if ALIB_MONOMEM
44 import ALib.Monomem;
45# if ALIB_CONTAINERS
47# endif
48# endif
49# endif
50#else
51# include "ALib.Lang.H"
52# if ALIB_FEAT_SINGLETON_MAPPED
53# if ALIB_DEBUG
54# include "ALib.Strings.H"
55# endif
56# if ALIB_MONOMEM
57# include "ALib.Monomem.H"
58# if ALIB_CONTAINERS
60# endif
61# endif
62# endif
63#endif
64
65// ========================================== Exports ==========================================
66#if ALIB_FEAT_SINGLETON_MAPPED && !DOXYGEN
67namespace alib::singletons::hidden {
68# if ALIB_MONOMEM && ALIB_CONTAINERS
69 extern HashMap<MonoAllocator, lang::TypeFunctors::Key, void *,
70 lang::TypeFunctors::Hash,
71 lang::TypeFunctors::EqualTo,
72 lang::Caching::Auto,
73 Recycling::None > singletonMap;
74# else
75 extern std::unordered_map< lang::TypeFunctors::Key, void *,
76 lang::TypeFunctors::Hash,
77 lang::TypeFunctors::EqualTo > singletonMap;
78# endif
79# if !ALIB_MONOMEM && !ALIB_SINGLE_THREADED
80 extern std::mutex singletonMapMutex; // if monomem is included, we use lock of global allocator
81# endif
82 extern ALIB_DLL void *getSingleton(const std::type_info &type);
83 extern ALIB_DLL void storeSingleton(const std::type_info &type, void *theSingleton);
84 extern ALIB_DLL void removeSingleton(const std::type_info &type);
85}
86#endif
87
89//==================================================================================================
90/// This class implements the "singleton pattern" for C++ using a common templated approach.
91/// In case of Windows OS and DLL usage, the class overcomes the problem of having
92/// a global data segment per DLL in addition to the one associated with the process that is using
93/// the DLL.
94///
95/// All details about implementation and usage of this class is provided in the module's
96/// \ref alib_mod_singletons "Programmer's Manual".
97///
98/// @tparam TDerivedClass Template parameter that denotes the name of the class that implements
99/// the singleton.
100//==================================================================================================
101template<typename TDerivedClass>
103 public:
104 #include "ALib.Lang.CIFunctions.H"
105 /// Creates (if not done, yet) and returns the singleton of type \p{TDerivedClass}.
106 /// @return The singleton instance.
107 static TDerivedClass &GetSingleton() {
108 #if !ALIB_FEAT_SINGLETON_MAPPED
109 // local static atomic instance of the singleton
110 static TDerivedClass singleton;
111 return singleton;
112 #else
113 #if ALIB_SINGLE_THREADED
114 using TSingletonStorage = TDerivedClass *;
115 #else
116 using TSingletonStorage = std::atomic<TDerivedClass *>;
117 #endif
118
119 // local static atomic pointer to the singleton (initialized once)
120 static TSingletonStorage singleton = nullptr;
121
122 // already created and known?
123 TDerivedClass *result = singleton;
124 if (result != nullptr)
125 return *result;
126
127 // create it
128 {
129 // for debug purposes, mapped singletons may be used with single-threaded
130 // applications. Still we do not lock then.
131 #if !ALIB_SINGLE_THREADED
132 # if ALIB_MONOMEM
134 # else
135 std::lock_guard<std::mutex> guard(hidden::singletonMapMutex);
136 # endif
137 #endif
138
139 // try loading from static map
140 void *storedSingleton = hidden::getSingleton(typeid(TDerivedClass));
141 if (storedSingleton != nullptr) {
142 singleton = dynamic_cast<TDerivedClass *>(
143 reinterpret_cast<Singleton<TDerivedClass> *>(storedSingleton));
144 return *singleton;
145 }
146
147 // create and store in map
148 auto *firstInstance = new TDerivedClass();
149 hidden::storeSingleton(typeid(TDerivedClass),
150 dynamic_cast<Singleton<TDerivedClass> *>(firstInstance));
151
152 // In debug mode, do not set this singleton right away. This "simulates"
153 // a windows DLL/Exec scope change
154 #if ALIB_DEBUG
155 return *firstInstance;
156 #else
157 return *(singleton = firstInstance);
158 #endif
159 }
160 #endif
161 }
162
163 #include "ALib.Lang.CIMethods.H"
164
165 /// Virtual destructor.
166 virtual ~Singleton() {
167 #if ALIB_FEAT_SINGLETON_MAPPED
168 #if !ALIB_SINGLE_THREADED
169 # if ALIB_MONOMEM
171 # else
172 std::lock_guard<std::mutex> guard(hidden::singletonMapMutex);
173 # endif
174 #endif
175 hidden::removeSingleton(typeid(TDerivedClass));
176 #endif
177 }
178}; // class Singleton
179
180//==================================================================================================
181/// Deletes the singletons.
182/// Upon exit of the process, programmers might want to explicitly free the hash table to avoid
183/// the detection of memory leaks by metrics tools like \http{Valgrind,valgrind.org/}.
184/// (Otherwise this can be omitted, as the memory is cleaned by the OS probably much faster when a
185/// process exits).
186///
187/// The \ref alib_mod_bs "standard bootstrap" code of \alib, hence the (overloaded)
188/// functions \ref alib::Shutdown will call this function.
189///
190/// \note This method is not thread-safe and hence must be called only on termination of the process
191/// when all threads that are using singletons are terminated.
192//==================================================================================================
193ALIB_DLL void shutdown();
194} // namespace [alib::singletons]
195
196ALIB_EXPORT namespace alib {
197/// Type alias in namespace \b alib.
198template<typename T>
200} // namespace [alib]
201
202//==================================================================================================
203//====== Debug functions
204//==================================================================================================
205#if ALIB_FEAT_SINGLETON_MAPPED && ALIB_DEBUG
207
208
209#if ALIB_MONOMEM && ALIB_CONTAINERS
210/// This debug helper function returns a type map with void pointers to all singletons.
211///
212/// The function may be used to investigate which singleton objects are created within a
213/// process and the point in (run-) time of creation.
214///
215/// \note
216/// This method is available only with debug-builds of %ALib and if
217/// code selection symbol \ref ALIB_FEAT_SINGLETON_MAPPED evaluates to true.<br>
218///
219/// \note
220/// If the \alibbuild includes \alib_strings then a simple dumping method is available with
221/// #DbgGetSingletons(NAString&).
222///
223/// \attention
224/// If modules \alib_monomem and \alib_containers are not included in the \alibbuild, then the
225/// result type of this method changes to <c>std::unordered_map<TypeKey, void*>&</c>.
226///
227/// @return A map of singleton types with void pointers to the singletons.
228//==============================================================================================
231 lang::TypeFunctors::Hash,
232 lang::TypeFunctors::EqualTo,
234 Recycling::None> &DbgGetSingletons();
235#else
236ALIB_DLL std::unordered_map<lang::TypeFunctors::Key, void *,
237 lang::TypeFunctors::Hash,
238 lang::TypeFunctors::EqualTo> &DbgGetSingletons();
239#endif
240
241#if ALIB_STRINGS
242/// This debug function writes all type names and addresses of each currently defined
243/// instance of class
244/// \alib{singletons;Singleton}
245/// into the given AString.<br>
246///
247/// \note
248/// This method is available only
249/// - with \ref ALIB_DEBUG "debug-builds" of the software,
250/// - if module \ref alib::strings "ALib Strings" is included in the \alibbuild, and
251/// - if code selection symbol \ref ALIB_FEAT_SINGLETON_MAPPED is \c true.
252///
253/// \note
254/// In case module <b>%ALib Strings</b> is not available, then alternative method
255/// \alib{singletons;DbgGetSingletons} can be used. This returns a list of
256/// \c std::type_info structs together with (void-) pointers to the singletons.
257///
258/// @param target The target string to write the list of singletons to.
259///
260/// @return The number of singletons written.
261 ALIB_DLL int DbgGetSingletons(NAString & target);
262#endif
263
264} // namespace [alib::singletons]
265#endif
static TDerivedClass & GetSingleton()
virtual ~Singleton()
Virtual destructor.
#define ALIB_DLL
Definition alib.inl:496
#define ALIB_LOCK_RECURSIVE_WITH(lock)
Definition alib.inl:1323
#define ALIB_EXPORT
Definition alib.inl:488
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.