Skip to content
Snippets Groups Projects
Commit 8c146685 authored by Jeremie Deray's avatar Jeremie Deray
Browse files

add singleton.h

parent 0d91788d
No related branches found
No related tags found
1 merge request!99Wolf logging macro
/**
* \file singleton.h
*
* Created on: Aug 31, 2016
* \author: Jeremie Deray
*/
#ifndef WOLF_SINGLETON_H_
#define WOLF_SINGLETON_H_
#include <memory>
namespace wolf {
namespace internal {
/**
* \brief A thread-safer Singleton implementation with
* argument forwarding.
**/
template <class T>
class Singleton
{
/**
* \brief Custom deleter to by-pass private destructor issue.
  • Is your issue similar to this? In problem.cpp:

    ProblemPtr Problem::create(FrameStructure _frame_structure)
    {
        ProblemPtr p(new Problem(_frame_structure)); // We use `new` and not `make_shared` since the Problem constructor is private and cannot be passes to `make_shared`.
        p->setup();
        return p->shared_from_this();
    }

    Explanation:

    • Problem (in short, P) has three shared_ptr to H, T and M, and each of these has a weak_ptr to P.
    • For the sake of a good user API, I want all these pointers to be valid just after creating P.
    • At construction time, shared_from_this() does not work
      • Therefore, I cannot link H, T, M to P when I am constructing P:
        • H::problem_ptr = shared_from_this(); does not work!
    • Solution: make constructor P() private, and write a factory method P::create() as in the code above
      • New Issue: To construct a ProblemPtr (aka shared_ptr<P>), I cannot use make_shared<P>, because it needs to call P() , and it is private:
        • ProblemPtr p = make_shared<P>(_frame_structure) does not work!
        • Solution: I call the shared_ptr constructor with the new syntax and not the make_shared:
          • ProblemPtr p(new Problem(_frame_structure)); works!
  • Please register or sign in to reply
**/
struct Deleter;
using SingletonOPtr = std::unique_ptr<T, Deleter>;
public:
template <typename... Args>
static T& get(Args&&... args)
{
static SingletonOPtr instance_(new T(args...));
return *instance_;
}
constexpr Singleton(const Singleton&) = delete;
//constexpr Singleton(const Singleton&&) = delete;
constexpr Singleton& operator=(const Singleton&) = delete;
//constexpr Singleton& operator=(const Singleton&&) = delete;
protected:
Singleton() = default;
virtual ~Singleton() = default;
};
template <class T>
struct Singleton<T>::Deleter
{
void operator()( const T* const p )
{
delete p;
}
};
} // namespace internal
} // namespace wolf
#endif /* WOLF_SINGLETON_H_ */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment