GMP 0.3.0
Generative Metaprogramming library for C++
Loading...
Searching...
No Matches
singleton.hpp
Go to the documentation of this file.
1// ___ __ __ ___
2// / __| \/ | _ \ GMP(Generative Metaprogramming)
3// | (_ | |\/| | _/ version 0.3.0
4// \___|_| |_|_| https://github.com/lkimuk/gmp
5//
6// SPDX-FileCopyrightText: 2020-2026 Miles Li <https://www.cppmore.com/>
7// SPDX-License-Identifier: MIT
8//
9// This file is part of the GMP (Generative Metaprogramming) library.
10// Full project source: https://github.com/lkimuk/gmp
11//
12// This singleton implementation was originally written by the same author
13// for the okdp library in 2020 and later adapted for GMP:
14// https://github.com/lkimuk/okdp
15
16#ifndef GMP_DP_SINGLETON_HPP_
17#define GMP_DP_SINGLETON_HPP_
18
19#include <cstdlib>
20#include <new>
21
22#include <gmp/dp/lock.hpp>
23
24namespace gmp {
25
54template <typename T, bool LongLifeTime = false> class singleton;
55
65template <typename T> class singleton<T, false> {
66public:
77 template <typename... Args> static T& instance(Args&&... args) {
78 static T obj(std::forward<Args>(args)...);
79 return obj;
80 }
81
82protected:
83 singleton() = default;
84 virtual ~singleton() {}
85
86private:
87 singleton(const singleton&) = delete;
88 singleton& operator=(const singleton&) = delete;
89 singleton(singleton&&) = delete;
90 singleton& operator=(singleton&&) = delete;
91};
92
101template <typename T> class singleton<T, true> {
102public:
110 template <typename... Args> static T& instance(Args&&... args) {
111 if (!pInstance_) {
112 // DCL
113 lock_.lock();
114
115 if (!pInstance_) {
116 destroyed_ ? on_dead_reference(std::forward<Args>(args)...)
117 : create(std::forward<Args>(args)...);
118 }
119
120 lock_.unlock();
121 }
122
123 return *pInstance_;
124 }
125
126private:
127 template <typename... Args> static void create(Args&&... args) {
128 static T obj(std::forward<Args>(args)...);
129 pInstance_ = &obj;
130 }
131
132 template <typename... Args> static void on_dead_reference(Args&&... args) {
133 create(std::forward<Args>(args)...);
134 new (pInstance_) T(std::forward<Args>(args)...);
135 std::atexit(kill_singleton);
136 destroyed_ = false;
137 }
138
139 static void kill_singleton() {
140 pInstance_->~singleton();
141 }
142
143 singleton(const singleton&);
144 singleton& operator=(const singleton&);
145 singleton(singleton&&);
146 singleton& operator=(singleton&&);
147
148 static dp::spin_lock lock_;
149
150protected:
151 singleton() = default;
152 virtual ~singleton() {
153 pInstance_ = nullptr;
154 destroyed_ = true;
155 }
156
157 static T* pInstance_;
158 static bool destroyed_;
159};
160
161template<typename T> T* singleton<T, true>::pInstance_ = nullptr;
162template<typename T> bool singleton<T, true>::destroyed_ = false;
163template<typename T> dp::spin_lock singleton<T, true>::lock_;
164
181#define GMP_DISABLE_CONSTRUCTION(Class) \
182private: \
183 friend class gmp::singleton<Class>; \
184 Class() = default;
185
188} // namespace gmp
189
190#endif // GMP_DP_SINGLETON_HPP_
A minimal spin lock built on std::atomic_flag.
Definition lock.hpp:39
static T & instance(Args &&... args)
Get the singleton instance.
Definition singleton.hpp:77
static T & instance(Args &&... args)
Get the singleton instance, recreating it if necessary.
CRTP-based singleton helper with optional dead-reference recovery.
Definition singleton.hpp:54
consteval auto enum_values()
Get all enumerator values of an enumeration type at compile-time.
Definition meta.hpp:155
Definition lock.hpp:21