83 lines
2.5 KiB
C++
83 lines
2.5 KiB
C++
#ifndef CORE_SINGLETON_H
|
|
#define CORE_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
|