// Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 #pragma once #include "utils_global.h" #include #include #include #include namespace Utils { class Singleton; struct SingletonStaticData { Singleton *m_instance = nullptr; QMutex m_mutex; }; class QTCREATOR_UTILS_EXPORT Singleton { Q_DISABLE_COPY_MOVE(Singleton) public: static void deleteAll(); private: template friend class SingletonWithOptionalDependencies; Singleton() = default; virtual ~Singleton(); static void addSingleton(Singleton *singleton); static SingletonStaticData &staticData(std::type_index index); }; template class SingletonWithOptionalDependencies : public Singleton { public: Q_DISABLE_COPY_MOVE(SingletonWithOptionalDependencies) static SingletonSubClass *instance() { SingletonStaticData &data = staticData(); QMutexLocker locker(&data.m_mutex); if (data.m_instance == nullptr) { // instantiate all dependencies first if constexpr (sizeof...(Dependencies)) instantiateDependencies(); data.m_instance = new SingletonSubClass; // put instance into static list of registered instances addSingleton(data.m_instance); } return static_cast(data.m_instance); } protected: SingletonWithOptionalDependencies() = default; ~SingletonWithOptionalDependencies() override { SingletonStaticData &data = staticData(); QMutexLocker locker(&data.m_mutex); if (data.m_instance == this) data.m_instance = nullptr; } private: template static void instantiateDependencies() { static_assert ((... && std::is_base_of_v), "All Dependencies must derive from SingletonWithOptionalDependencies class."); (..., Dependency::instance()); } static SingletonStaticData &staticData() { static SingletonStaticData &data = Singleton::staticData(std::type_index(typeid(SingletonSubClass))); return data; } }; } // namespace Utils