Kylin/Universal/Singleton.h
2023-07-21 11:21:16 +08:00

83 lines
2.5 KiB
C++

#ifndef SINGLETON_H
#define SINGLETON_H
#include "BoostLog.h"
#include <boost/assert.hpp>
#include <memory>
namespace Amass {
using GlobalInstance = std::true_type;
using LocalInstance = std::false_type;
struct Construct {};
struct Reference {};
struct Register {};
template <typename T, typename Style = LocalInstance>
class Singleton;
template <typename T>
class Singleton<T, LocalInstance> {
public:
template <typename Invoke = Reference, typename InstanceType = T, typename... Args>
static std::shared_ptr<T> instance(Args &&...args) {
// LOG(debug) << typeid(T).name() << " address: " << (size_t)&m_instance;
static_assert(std::is_base_of_v<T, InstanceType>, "InstanceType must be child of T ...");
if constexpr (std::is_same_v<Invoke, Construct>) {
if (!m_instance.expired()) {
throw std::runtime_error("an instance have constructed ...");
}
auto instance = std::shared_ptr<T>(new InstanceType(std::forward<Args>(args)...));
m_instance = instance;
return instance;
} else if constexpr (std::is_same_v<Invoke, Reference>) {
return m_instance.expired() ? nullptr : m_instance.lock();
} else if constexpr (std::is_same_v<Invoke, Register>) {
static_assert(sizeof...(args) == 1, "args must equal to 1...");
m_instance = std::get<0>(std::forward_as_tuple(args)...);
return std::get<0>(std::forward_as_tuple(args)...);
} else {
static_assert(!std::is_same_v<Invoke, GlobalInstance>, "Can not to it!");
}
}
static std::weak_ptr<T> weakPointer() {
return m_instance;
}
private:
Singleton() = delete;
~Singleton() = delete;
Singleton(const Singleton &) = delete;
Singleton &operator=(const Singleton &) = delete;
private:
inline static std::weak_ptr<T> m_instance;
};
template <typename T>
class Singleton<T, GlobalInstance> {
public:
template <typename... Args>
static T *instance(Args &&...args) {
if (!m_value) {
m_value.reset(new T(std::forward<Args>(args)...));
}
return m_value.get();
}
private:
Singleton() = delete;
~Singleton() = delete;
Singleton(const Singleton &) = delete;
Singleton &operator=(const Singleton &) = delete;
private:
inline static std::shared_ptr<T> m_value;
};
} // namespace Amass
#endif // SINGLETON_H