Cbeam
Loading...
Searching...
No Matches
singleton.hpp
Go to the documentation of this file.
1/*
2Copyright (c) 2025 acrion innovations GmbH
3Authors: Stefan Zipproth, s.zipproth@acrion.ch
4
5This file is part of Cbeam, see https://github.com/acrion/cbeam and https://cbeam.org
6
7Cbeam is offered under a commercial and under the AGPL license.
8For commercial licensing, contact us at https://acrion.ch/sales. For AGPL licensing, see below.
9
10AGPL licensing:
11
12Cbeam is free software: you can redistribute it and/or modify
13it under the terms of the GNU Affero General Public License as published by
14the Free Software Foundation, either version 3 of the License, or
15(at your option) any later version.
16
17Cbeam is distributed in the hope that it will be useful,
18but WITHOUT ANY WARRANTY; without even the implied warranty of
19MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20GNU Affero General Public License for more details.
21
22You should have received a copy of the GNU Affero General Public License
23along with Cbeam. If not, see <https://www.gnu.org/licenses/>.
24*/
25
26#pragma once
27
28#include <cbeam/error/runtime_error.hpp> // for cbeam::error:runtime_error
29#include <cbeam/logging/log_manager.hpp> // for CBEAM_LOG_DEBUG
30
31#include <cassert> // for assert
32
33#include <map> // for std::map, std::operator!=, std::_Rb_tree_iterator
34#include <memory> // for std::unique_ptr, std::allocator, std::shared_ptr, std::make_shared, std::make_unique
35#include <mutex> // for std::mutex, std::lock_guard
36#include <string> // for std::string, std::operator+, std::basic_string, std::char_traits
37#include <utility> // for std::pair, std::forward
38#include <vector> // for std::vector
39
40namespace cbeam::lifecycle
41{
51 {
52 public:
53 virtual ~singleton_control() = default;
54
62 static void reset()
63 {
64 CBEAM_LOG_DEBUG("cbeam::lifecycle::singleton_control::reset");
65
66 std::lock_guard<std::mutex> lock(_mutex);
67 _shutdown = true;
68 for (auto& instance : _instances)
69 {
70 instance.second->release_instance();
71 instance.second.reset();
72 }
73 _instances.clear();
74 }
75
82 static void set_operational()
83 {
84 CBEAM_LOG_DEBUG("cbeam::lifecycle::singleton_control::set_operational");
85 _shutdown = false;
86 }
87
88 protected:
93 virtual void release_instance() = 0;
94
95 static inline std::map<std::string, std::unique_ptr<singleton_control>> _instances;
96 static inline std::mutex _mutex;
97 static inline bool _shutdown{false};
98 };
99
151 template <typename T, typename... Args>
153 {
154 private:
155 struct private_construction_tag
156 {
157 };
158
159 public:
163 singleton(private_construction_tag, const std::string& name, Args... args)
164 : _name{name}
165 , _instance{std::make_shared<T>(std::forward<Args>(args)...)}
166 {
167 CBEAM_LOG_DEBUG("cbeam::lifecycle::singleton construction: " + _name);
168 }
169
170 ~singleton() noexcept override
171 {
172 CBEAM_LOG_DEBUG("cbeam::lifecycle::singleton destruction: " + _name);
173 }
174
186 static std::shared_ptr<T> get(const std::string& name, Args... args)
187 {
188 if (_shutdown)
189 {
190 CBEAM_LOG_DEBUG("cbeam::lifecycle::singleton::get: " + name + ": refused to create an instance because singleton_control::reset() "
191 "had been called. Use singleton_control::set_operational() to enable again.");
192 return nullptr;
193 }
194 std::lock_guard<std::mutex> lock(_mutex);
195
196 auto& base_instance = _instances[name];
197 const bool create_base_instance = !base_instance;
198
199 if (create_base_instance)
200 {
201 base_instance = std::make_unique<singleton>(private_construction_tag{}, name, std::forward<Args>(args)...);
202 }
203
204 auto derived_instance = dynamic_cast<singleton*>(base_instance.get());
205
206 if (derived_instance)
207 {
208 return derived_instance->_instance;
209 }
210 else
211 {
212 if (create_base_instance)
213 {
214 base_instance.reset();
215 }
216 throw cbeam::error::runtime_error("cbeam::lifecycle::singleton: incompatible singleton type requested.");
217 }
218 }
219
227 static void release(const std::string& name)
228 {
229 CBEAM_LOG_DEBUG("cbeam::lifecycle::singleton::release: " + name);
230 std::lock_guard<std::mutex> lock(_mutex);
231
232 auto it = _instances.find(name);
233 if (it != _instances.end())
234 {
235 it->second.reset();
236 _instances.erase(it);
237 }
238 }
239
240 protected:
244 void release_instance() override
245 {
246 CBEAM_LOG_DEBUG("cbeam::lifecycle::singleton::release_instance: " + _name);
247 _instance.reset();
248 }
249
250 private:
251 singleton(const singleton&) = delete;
252 singleton(singleton&&) = delete;
253 singleton& operator=(const singleton&) = delete;
254 singleton& operator=(singleton&&) = delete;
255
256 std::string _name;
257 std::shared_ptr<T> _instance;
258 };
259}
A Cbeam-specific runtime error that also acts like std::runtime_error.
Definition runtime_error.hpp:46
Definition singleton.hpp:153
static void release(const std::string &name)
Explicitly removes the named singleton instance from the global map.
Definition singleton.hpp:227
singleton(private_construction_tag, const std::string &name, Args... args)
Internal constructor. Use get() to create a new instance.
Definition singleton.hpp:163
static std::shared_ptr< T > get(const std::string &name, Args... args)
Retrieves (or creates) the shared instance of type T by name.
Definition singleton.hpp:186
~singleton() noexcept override
Definition singleton.hpp:170
void release_instance() override
Called by singleton_control::reset() to release the managed resource.
Definition singleton.hpp:244
#define CBEAM_LOG_DEBUG(s)
Logs a debug message if CBEAM_DEBUG_LOGGING is enabled.
Definition log_manager.hpp:138
Manages the lifecycle of singletons, item registries, and scoped variables. This namespace introduces...
Definition item_registry.hpp:38
Base class for controlling the lifecycle of all singleton instances across different types.
Definition singleton.hpp:51
static std::map< std::string, std::unique_ptr< singleton_control > > _instances
Definition singleton.hpp:95
static bool _shutdown
Definition singleton.hpp:97
static void reset()
Resets (shuts down) all stored singleton instances.
Definition singleton.hpp:62
static std::mutex _mutex
Definition singleton.hpp:96
virtual void release_instance()=0
Releases the internal resource of the derived singleton. Called during a global reset.
static void set_operational()
Ends the shut-down state and allows singletons to be created again.
Definition singleton.hpp:82