ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
singletons.hpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_singletons of the \aliblong.
4///
5/// Copyright 2013-2026 A-Worx GmbH, Germany.
6/// Published under #"mainpage_license".
7//==================================================================================================
8
9#if ALIB_FEAT_SINGLETON_MAPPED && !DOXYGEN
10namespace alib::singletons::hidden {
11# if ALIB_MONOMEM && ALIB_CONTAINERS
12 extern HashMap<MonoAllocator, lang::TypeFunctors::Key, void *,
13 lang::TypeFunctors::Hash,
14 lang::TypeFunctors::EqualTo,
15 lang::Caching::Auto,
16 Recycling::None > singletonMap;
17# else
18 extern std::unordered_map< lang::TypeFunctors::Key, void *,
19 lang::TypeFunctors::Hash,
20 lang::TypeFunctors::EqualTo > singletonMap;
21# endif
22# if !ALIB_MONOMEM && !ALIB_SINGLE_THREADED
23 extern std::mutex singletonMapMutex; // if monomem is included, we use lock of global allocator
24# endif
25 extern ALIB_DLL void *getSingleton(const std::type_info &type);
26 extern ALIB_DLL void storeSingleton(const std::type_info &type, void *theSingleton);
27 extern ALIB_DLL void removeSingleton(const std::type_info &type);
28}
29#endif
30
32//==================================================================================================
33/// This class implements the "singleton pattern" for C++ using a common templated approach.
34/// In case of Windows OS and DLL usage, the class overcomes the problem of having
35/// a global data segment per DLL in addition to the one associated with the process that is using
36/// the DLL.
37///
38/// All details about implementation and usage of this class is provided in the module's
39/// #"alib_mod_singletons;Programmer's Manual".
40///
41/// @tparam TDerivedClass Template parameter that denotes the name of the class that implements
42/// the singleton.
43//==================================================================================================
44template<typename TDerivedClass>
45class Singleton {
46 public:
48 /// Creates (if not done, yet) and returns the singleton of type \p{TDerivedClass}.
49 /// @return The singleton instance.
50 static TDerivedClass &GetSingleton() {
51 #if !ALIB_FEAT_SINGLETON_MAPPED
52 // local static atomic instance of the singleton
53 static TDerivedClass singleton;
54 return singleton;
55 #else
56 #if ALIB_SINGLE_THREADED
57 using TSingletonStorage = TDerivedClass *;
58 #else
59 using TSingletonStorage = std::atomic<TDerivedClass *>;
60 #endif
61
62 // local static atomic pointer to the singleton (initialized once)
63 static TSingletonStorage singleton = nullptr;
64
65 // already created and known?
66 TDerivedClass *result = singleton;
67 if (result != nullptr)
68 return *result;
69
70 // create it
71 {
72 // for debug purposes, mapped singletons may be used with single-threaded
73 // applications. Still we do not lock then.
74 #if !ALIB_SINGLE_THREADED
75 # if ALIB_MONOMEM
77 # else
78 std::lock_guard<std::mutex> guard(hidden::singletonMapMutex);
79 # endif
80 #endif
81
82 // try loading from static map
83 void *storedSingleton = hidden::getSingleton(typeid(TDerivedClass));
84 if (storedSingleton != nullptr) {
85 singleton = dynamic_cast<TDerivedClass *>(
86 static_cast<Singleton<TDerivedClass> *>(storedSingleton));
87 return *singleton;
88 }
89
90 // create and store in map
91 auto* firstInstance = new TDerivedClass();
92 hidden::storeSingleton(typeid(TDerivedClass),
93 dynamic_cast<Singleton<TDerivedClass> *>(firstInstance));
94
95 // In debug mode, do not set this singleton right away. This "simulates"
96 // a windows DLL/Exec scope change
97 #if ALIB_DEBUG
98 return *firstInstance;
99 #else
100 return *(singleton = firstInstance);
101 #endif
102 }
103 #endif
104 }
105
106 #include "ALib.Lang.CIMethods.H"
107
108 /// Virtual destructor.
109 virtual ~Singleton() {
110 #if ALIB_FEAT_SINGLETON_MAPPED
111 #if !ALIB_SINGLE_THREADED
112 # if ALIB_MONOMEM
114 # else
115 std::lock_guard<std::mutex> guard(hidden::singletonMapMutex);
116 # endif
117 #endif
118 hidden::removeSingleton(typeid(TDerivedClass));
119 #endif
120 }
121}; // class Singleton
122
123//==================================================================================================
124/// Deletes the singletons.
125/// Upon exit of the process, programmers might want to explicitly free the hash table to avoid
126/// the detection of memory leaks by metrics tools like \http{Valgrind,valgrind.org/}.
127/// (Otherwise this can be omitted, as the memory is cleaned by the OS probably much faster when a
128/// process exits).
129///
130/// The #"alib_mod_bs;standard bootstrap" code of \alib, hence the (overloaded)
131/// functions #"alib::Shutdown;2" will call this function.
132///
133/// \note This method is not thread-safe and hence must be called only on termination of the process
134/// when all threads that are using singletons are terminated.
135//==================================================================================================
136ALIB_DLL void shutdown();
137} // namespace [alib::singletons]
138
139ALIB_EXPORT namespace alib {
140/// Type alias in namespace #"%alib".
141template<typename T>
143} // namespace [alib]
144
145//==================================================================================================
146//====== Debug functions
147//==================================================================================================
148#if ALIB_FEAT_SINGLETON_MAPPED && ALIB_DEBUG
150
151
152#if ALIB_MONOMEM && ALIB_CONTAINERS
153/// This debug helper function returns a type map with void pointers to all singletons.
154///
155/// The function may be used to investigate which singleton objects are created within a
156/// process and the point in (run-) time of creation.
157///
158/// \note
159/// This method is available only with debug-builds of \alib and if
160/// code selection macro #"ALIB_FEAT_SINGLETON_MAPPED" evaluates to true.<br>
161///
162/// \note
163/// If the \alibbuild includes \alib_strings then a simple dumping method is available with
164/// #"DbgGetSingletons(NAString&)".
165///
166/// \attention
167/// If modules \alib_monomem and \alib_containers are not included in the \alibbuild, then the
168/// result type of this method changes to <c>std::unordered_map<TypeKey, void*>&</c>.
169///
170/// @return A map of singleton types with void pointers to the singletons.
171//==================================================================================================
174 lang::TypeFunctors::Hash,
175 lang::TypeFunctors::EqualTo,
177 Recycling::None> &DbgGetSingletons();
178#else
179ALIB_DLL std::unordered_map<lang::TypeFunctors::Key, void *,
180 lang::TypeFunctors::Hash,
181 lang::TypeFunctors::EqualTo> &DbgGetSingletons();
182#endif
183
184#if ALIB_STRINGS
185/// This debug function writes all type names and addresses of each currently defined
186/// instance of class
187/// #"Singleton"
188/// into the given AString.<br>
189///
190/// \note
191/// This method is available only
192/// - with #"ALIB_DEBUG;debug-builds" of the software,
193/// - if module \alib_strings is included in the \alibbuild, and
194/// - if code selection macro #"ALIB_FEAT_SINGLETON_MAPPED" is \c true.
195///
196/// \note
197/// In case module <b>ALib Strings</b> is not available, then the alternative method
198/// #"DbgGetSingletons()" can be used. This returns a list of
199/// \c std::type_info structs together with (void-) pointers to the singletons.
200///
201/// @param target The target string to write the list of singletons to.
202///
203/// @return The number of singletons written.
205#endif
206
207} // namespace [alib::singletons]
208#endif
#define ALIB_DLL
#define ALIB_LOCK_RECURSIVE_WITH(lock)
#define ALIB_EXPORT
static TDerivedClass & GetSingleton()
virtual ~Singleton()
Virtual destructor.
HashTable< TAllocator, TPairDescriptor< TKey, TMapped >, THash, TEqual, THashCaching, TRecycling > HashMap
@ Auto
Auto/default mode.
RecursiveLock GLOBAL_ALLOCATOR_LOCK
HashMap< MonoAllocator, lang::TypeFunctors::Key, void *, lang::TypeFunctors::Hash, lang::TypeFunctors::EqualTo, lang::Caching::Auto, Recycling::None > & DbgGetSingletons()
Definition alox.cpp:14
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
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".
const ::std::type_info * Key
The key type.