2010-04-20

How to create a fast thread-safe singleton initialization in C++

1st: We need a lock. On windows it can use critical sections. Keywords: critical section, lock
class Lock {
    CRITICAL_SECTION mSection;
public:
    Lock(){ InitializeCriticalSection(&mSection); }
    ~Lock(){ DeleteCriticalSection(&mSection); }
    void Acquire(){ EnterCriticalSection(&mSection); }
    void Release(){ LeaveCriticalSection(&mSection); }
};
2nd: We need a guard for the lock. Just for convenience and to be foolproof. Keyword: RAII, guard. See also: auto_ptr.
class Guard {
    Lock *pLock;
public:
    Guard(Lock &lock)
    : pLock(&lock)
    { pLock->Acquire(); }
    ~Guard(){ pLock->Release(); }
};
3rd: We can get down to business with our singleton. Do not forget to hide the default constructors and the '=' operator. Keywords: singleton, multi-thread, thread-safe, storage, operator overloading.

singleton.h:
class Singleton {
public:
    static Singleton *GetInstance();
    // other public members
private:
    Singleton();
    ~Singleton();
    Singleton(const Singleton&);
    const Singleton& operator=(const Singleton&);

    static Singleton* pInstance;
    static Lock instanceLock;
    // other private members
};
singleton.cpp:
#include "singleton.h"

// Storage place for static members:
Singleton* Singleton::pInstance = 0;
Lock Singleton::instanceLock;

Singleton::Singleton(){ /* as you wish */ }
Singleton::~Singleton(){ /* as you wish */ }

Singleton* Singleton::GetInstance()
{
    if(pInstance)
        return pInstane;
    Guard g(instanceLock);
    if(!pInstance)
        pInstance = new Singleton();
    return pInstance;
}

Feel free to search the web for the keywords, or any word you read here.

No comments:

Post a Comment