Singleton pattern

From QtCentreWiki

Jump to:navigation, search

Singleton Pattern

A Singleton Pattern is intended to limit a class to one instance only, for example a class to encapsulate global variables. However, be careful when using a singleton. It's considered "bad practice" in a lot of cases for a good reason: you may as well just use global functions!

Implementation

There are different Singleton implementations around, each has a its own background. We are only going to take a look at the most basic, thread-safe implementation. Be aware that you should check for a std::bad_alloc exception to unlock the mutex in case new fails. We are also using double-checked locking as locking and unlocking a mutex is expensive and would significantly slow down a call to Singleton::instance().

// Singleton.h:
 
#include <QMutex>
 
class Singleton
{
public:
    static Singleton* instance()
    {
        static QMutex mutex;
        if (!m_Instance)
        {
            mutex.lock();
 
            if (!m_Instance)
                m_Instance = new Singleton;
 
            mutex.unlock();
        }
 
        return m_Instance;
    }
 
    static void drop()
    {
        static QMutex mutex;
        mutex.lock();
        delete m_Instance;
        m_Instance = 0;
        mutex.unlock();
    }
 
private:
    Singleton() {}
 
    Singleton(const Singleton &); // hide copy constructor
    Singleton& operator=(const Singleton &); // hide assign op
                                 // we leave just the declarations, so the compiler will warn us 
                                 // if we try to use those two functions by accident
 
    static Singleton* m_Instance;
};
 
 
// Singleton.cpp:
 
#include "Singleton.h"
 
Singleton* Singleton::m_Instance = 0;

Template-based Approach

There is a second, rather simple approach to providing a generic wrapper for Singletons. This one basically just provides the code to handle a singleton, but by using C++ templates, you can make any class a singleton without having to modify it.

// singleton.h
 
#ifndef SINGLETON_H
#define SINGLETON_H
 
#include <QObject>
 
template <class T>
class Singleton
{
public:
    static T& Instance()
    {
        static T _instance; // create static instance of our class
        return _instance;   // return it
    }
 
private:
    Singleton();	// hide constructor
    ~Singleton();	// hide destructor
    Singleton(const Singleton &); // hide copy constructor
    Singleton& operator=(const Singleton &); // hide assign op
};
#endif
 
 
 
// mycode.cpp
 
#include "singleton.h"
#include "MySingletonClass.h"
 
MySingletonClass *singleton = &Singleton<MySingletonClass>::Instance();
 
singleton->storeInfo();

Further Reading