#include "of_def.hpp"
#include <cassert>
#include <iostream>
#include <memory>
#include <mutex>

namespace ofen {
template <typename T> class OfSingleton
{
public:
    OfSingleton(const OfSingleton&) = delete;
    OfSingleton& operator=(const OfSingleton&) = delete;

    static std::shared_ptr<T> getInstance()
    {
        std::call_once(init_flag, []() { instance.reset(new T()); });
        return instance;
    }

protected:
    OfSingleton() = default;
    virtual ~OfSingleton() = default;

private:
    static std::shared_ptr<T> instance;
    static std::once_flag init_flag;
};

template <typename T> std::shared_ptr<T> OfSingleton<T>::instance = nullptr;
template <typename T> std::once_flag OfSingleton<T>::init_flag;
}   // namespace ofen