HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Thread safe templatized singleton class

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
singletonthreadtemplatizedsafeclass

Problem

#include "stdafx.h"
#include 
#include 
#include 
#include 
#include 
template  
class Singleton
{
    //thread safe atomic variable to check whether client is creating more than  one instance
    static std::atomic_flag flag ;
public:
    static T& getinstance()
    {
        //I am delibreatly allocating it on heap so that I would not worry about its time of deinitilization 
        //static variable initialization is thread safe
        static T * t = new T();
        return *t;
}
    //exception class- kept it as Internal
    class SingletonException : public std::runtime_error
    {
    public:
    SingletonException(const std::string& exString) :std::runtime_error(exString)
        {

        }
    };
protected:
    Singleton()
    {       
        if (flag.test_and_set())
        {
        std::ostringstream  ex;
            ex 
std::atomic_flag  Singleton::flag;
class Myclass: Singleton
{
    public:
        Myclass()
        {
        }
public:
    friend Singleton;
};
int main()
{
try
    {
        Singleton::getinstance();
        Myclass obj;
        Singleton::getinstance();
    }
    catch (const Singleton::SingletonException& ex)
    {
        std::cout << ex.what();
    }
    getchar();
    return 0;
}


Few points:

  • I am inheriting it so that I can mark delete copy/move operations, but inheritance is mandatory



  • This template class should be kept as friend class of client class



  • If more than one object is created then it will throw exception provided client has inherited from it.



It is more like code review. But do you think it is really thread safe GOOD singleton.

Solution

Don't use the Singleton pattern


But do you think it is really thread safe good singleton?

Please excuse my pedantry and let me say that the only good use of the Singleton pattern is to not use it at all. This is not to say that a program should never have just a single instance of a class. On the contrary, it is a perfectly reasonable thing at times. Just don't couple the “unique object” property to the type itself as the pattern does. Instead, write a normal class with a public constructor and let another class provide a unique instance of it. The internet is full of rants about the Singleton pattern and good reasons why not to use it so I'll leave it at that.

Watch your #includes

If you're using the typeid operator, you must #include the ` header first.

The
#include "stdafx.h", on the contrary, is non-portable and annoying. Get rid of it.

For
std::runtime_error, you don't need the but the header.

Use vertical and horizontal white-space for better readability

It might be just an artifact of copying and pasting your code from your editor into the web browser but as it stands, your code is not very well formatted.

I would put a blank line between functions and classes as well as after the
#include directives at the top. The only blank line in your code is – in an empty function body.

There are many opinions about the optimal amount of horizontal space you use to indent your code and I'm okay with most styles. What is not okay is inconsistency. Pick one style and stick to it. Some lines of your code appear completely off. For example, the closing brace of
Singleton::getinstance (looks as if it were the end of the class) or the try in main.

Any decent editor can re-indent the code for you at the press of a button.

What's this
std::atomic_flag?

I'm not sure what problem exactly the
Singleton::flag member is supposed to solve but I'm pretty sure that there's a better way. If you don't want client code to instantiate your singleton class directly (which, as mentioned, is a poor decision, but ignore that for now) just make the constructor private. Then the compiler can enforce at compile-time that nobody except the singleton provider instantiates it. This is much better than checking at run-time and crashing the program.

Reconsider the heap allocation

I don't see why you have to allocate your singleton instance dynamically. The only situation where I could imagine a problem with static deinitialization is if you refer to the object from within a function registered as an
std::atexit handler. On the contrary, dynamically allocating the object and then “leaking” it might cause leak detectors such as Valgrind to give you “false” positives that obscure more severe issues with your code. I prefer code to always clean up everything such that it is Valgrind clean. If you're writing a library, it is even more frustrating for your users to get leaks reported that they cannot do anything about.

Returning a reference is fine

I see many Singleton implementations for C++
returning a pointer just because they can. I like your choice of using a reference better.

You don't need an empty destructor

Your inline definition of a non-
virtual empty destructor adds nothing. It might only confuse people whether you might have actually forgotten to put a delete of the instance there. (In which case it would of course have been better to use a std::unique_ptr and again write no destructor.)

Make
deleted member functions public

It might sound counter-intuitive at first but making
deleted members functions public gives you better error messages. It also makes sense if you think about it: The fact that your type is not copyable is part of its public interface.

Did you mean
MyClass to inherit privately from Singleton?

I think it would be less surprising if you'd inherit
publicly because then you could also say MyClass::getinstance() instead of the more verbose and less intuitive Singleton::getinstance().

The code in
MyClass is completely redundant

If you delete everything inside the
MyClass body, your program does the exact same thing. I'm sure that you did intend something by writing it but made some mistake (such as accidentally making the constructor public) that renders it useless as it stands.

Get rid of the
getchar abomination in main

Don't make your program block on an I/O operation just because you want the terminal emulator window stay open. Instead, learn how to use the emulator such that the window stays open even after the program finished.

If you really want it, it should be
std::getchar and you need the header.

How I would do it

Putting the previous advice together, I would solve the problem like this.

``
template
struct singleton_provider
{
static T&
instance()
{
static T theinstance {};
return theinstance;
}
};

struct my_class
{
my_class(const my_class&) = delete;
my_class& operator=(const my_clas

Code Snippets

template <typename T>
struct singleton_provider
{
  static T&
  instance()
  {
    static T theinstance {};
    return theinstance;
  }
};

struct my_class
{
  my_class(const my_class&) = delete;
  my_class& operator=(const my_class&) = delete;
};

using my_class_provider = singleton_provider<my_class>;

Context

StackExchange Code Review Q#140907, answer score: 6

Revisions (0)

No revisions yet.