Re: Singleton: type name is not allowed
On Feb 25, 5:21 pm, "srimk...@gmail.com" <srimk...@gmail.com> wrote:
Dear All.
[...]
Now I wish to perform sole instance for below statement (i) using
above Singleton Instance() API call, originialy NonP is basically a
class.
Do you want a generic Singleton class that you can use to create
singletons in your App?
If Yes, you can construct one on the following lines that i am using
on *WINDOWS* platform; you can modify it using preprocessor for
different platforms (Ex. to use POSIX APIs) or just ignore the
locks!.
-->header "Singleton.h"
/
***************************************************************************=
****
NOTE: THIS IS NOT A MEYER'S IMPLEMENTATION OF SINGLETON. THAT VERSION
THOUGH
PERFECTLY O.K. HAS U.B. IF TWO STATIC OBJECTS S1 AND S2 ARE USED IN
THE
INITIALIZATION. S1 IS THE SINGELTON AND USES S2 WHICH IS JUST ANOTHER
STATIC
OBJECT FOR INITIALIZATION. BUT S1 GETS INITIALIZED FIRST FOLLOWED BY
S2. THE
DESTRUCTION OF S2 HAPPENS BEFORE S1, THUS IF S1 USES S2 ANYWHERE AFTER
S2's
DESTRUCTION WE HAVE A POTENTIALLY UNSOLVABLE PROBLEM IN C++. SO HEAP
ALLOCATED
SINGLETONS ARE GENERALLY PREFERRED. EVEN IF S2 WERE DECLARED FIRST TO
CONTROL
THE ORDER OF INITIALIZATION, IT MAY NOT WORK IN MULTI-THREADED
ENVIRONMENTS
LEADING TO SUBTLE/NASTY BUGS. HENCE THIS IMPLEMENTATION.
***************************************************************************=
*****/
// header that defines a generic singleton
#ifndef __SINGLETON_H__
#include <Windows.h>
// we first need the synchronization mechanism in C++ as it does not
have
// built-in multi-threading runtime and atomic locks
class CriticalSection{
public:
explicit CriticalSection(){
InitializeCriticalSection(&cs);
}
~CriticalSection(){
DeleteCriticalSection(&cs);
}
inline
void Enter(){
EnterCriticalSection(&cs);
}
inline
void Leave(){
LeaveCriticalSection(&cs);
}
private:
// prevent copying and use of free
void free(size_t siz);
CriticalSection& operator =(const CriticalSection& ); // no
assignment
CriticalSection(const CriticalSection& );// copy ctor
CRITICAL_SECTION cs;
};
// wrapper for locking
class Lock
{
public:
Lock(CriticalSection& aCS):CS(aCS) {
CS.Enter();
}
~Lock() {
CS.Leave();
}
private:
CriticalSection& CS;
};
// create the Singleton class using templates
template<class T>
class TSingleton{
public:
static T& getInstance(); // the global access method
protected: // no direct instantiation but can be subclassed
explicit TSingleton(){
}
virtual ~TSingleton(){
}
private:
// no copying business
TSingleton& operator =(const TSingleton& );
TSingleton(const TSingleton& );
// no freeing also
void free(size_t siz);
// create a friendly class that manages the singleton access
class AutomaticInstance;
friend class AutomaticInstance;
class AutomaticInstance
{
public:
AutomaticInstance():p(NULL) {}
~AutomaticInstance() {delete p;}
void set(T* ap) {p=ap;}
T* get() const {return p;}
private:
T* volatile p; // avoid compiler optimizations
};
static AutomaticInstance TheInstancePointer;
static CriticalSection InstanceCreationCritical;
};
// this is the heart of singleton implementation.
// it creates the ONE AND ONLY instance
template<class T>
T& TSingleton<T>::getInstance(){
if(!TheInstancePointer.get()){ // if the instance does not already
exist
Lock cslock(InstanceCreationCritical); // enter CS for synched
access
if(!TheInstancePointer.get()) // necessary check !!
TheInstancePointer.set(new T);
// Lock released here -- by its dtor
}
return *(TheInstancePointer.get());
}
// define the static variables
template<class T>
typename TSingleton<T>::AutomaticInstance
TSingleton<T>::TheInstancePointer;
template<class T>
CriticalSection TSingleton<T>::InstanceCreationCritical;
#define __SINGLETON_H__
#endif
-->The implementation file Main.cpp
#include "Singleton.h"
#include <iostream>
class MySingleton : private TSingleton<MySingleton> {
friend class TSingleton<MySingleton>;
public:
using TSingleton<MySingleton>::getInstance; // make the instance
getter visible ...
void Hello() {
std::cout<<"[Hello]\n";
}
protected:
MySingleton() {}
};
int main(){
MySingleton &m = MySingleton::getInstance();
m.Hello();
// check if different addresses are returned ??
if (&MySingleton::getInstance() != &MySingleton::getInstance())
std::cout<<"[OOPS! FAKE SINGLETON]";
return 0;
}
NOTE: This solution may not be perfect, there are many ways of
implementing singletons, ...
HTH
Abhay