In a recent project, I had to create a Singleton class, and after a lot of searching on Google, I came up with a definition for this template. The idea is to get this template class and make a protected / private constructor of the derived class. It seems to work well, but I used it with only one class in one project, so I was hoping some of you might indicate if I made any errors in the implementation. There he is:
template< typename T >
class SingletonDynamic
{
public:
static T &instance()
{
return *SingletonDynamic< T >::get_instance();
}
static const T &const_instance()
{
return *SingletonDynamic< T >::get_instance();
}
protected:
SingletonDynamic() {}
virtual ~SingletonDynamic()
{
delete SingletonDynamic< T >::pInstance_;
}
typedef void(*coherence_callback_type)();
static coherence_callback_type pfnLockMutex;
static coherence_callback_type pfnUnlockMutex;
static coherence_callback_type pfnMemoryBarrier;
private:
static T *pInstance_;
static volatile bool flag_;
SingletonDynamic( SingletonDynamic const & );
SingletonDynamic &operator=( SingletonDynamic const & );
static T *get_instance()
{
if( SingletonDynamic< T >::flag_ == false ) {
(*SingletonDynamic< T >::pfnLockMutex)();
if( SingletonDynamic< T >::pInstance_ == NULL ) {
pInstance_ = new T();
}
(*SingletonDynamic< T >::pfnUnlockMutex)();
(*SingletonDynamic< T >::pfnMemoryBarrier)();
SingletonDynamic< T >::flag_ = true;
return SingletonDynamic< T >::pInstance_;
} else {
(*SingletonDynamic< T >::pfnMemoryBarrier)();
return SingletonDynamic< T >::pInstance_;
}
}
inline static void lock_mutex()
{
return;
}
inline static void unlock_mutex()
{
return;
}
inline static void memory_barrier()
{
return;
}
};
template< typename T >
T *SingletonDynamic<T>::pInstance_ = NULL;
template< typename T >
volatile bool SingletonDynamic<T>::flag_ = false;
template< typename T >
typename SingletonDynamic<T>::coherence_callback_type SingletonDynamic<T>::pfnLockMutex
= &SingletonDynamic<T>::lock_mutex;
template< typename T >
typename SingletonDynamic<T>::coherence_callback_type SingletonDynamic<T>::pfnUnlockMutex
= &SingletonDynamic<T>::unlock_mutex;
template< typename T >
typename SingletonDynamic<T>::coherence_callback_type SingletonDynamic<T>::pfnMemoryBarrier
= &SingletonDynamic<T>::memory_barrier;
I am particularly concerned about the initialization of static members in the header file and whether this will cause multiple determination errors if the header file of the class that is derived from SingleDynamic is included in several files. I already tried this and it seems to work, but I can’t understand why its work :).
Thanks in advance, Ashish.
EDIT: , , .
struct DefaultSingletonConcurrencyPolicy
{
static void lock_mutex()
{
return;
}
static void unlock_mutex()
{
return;
}
static void memory_barrier()
{
return;
}
};
template< typename T, typename ConcurrencyPolicy = DefaultSingletonConcurrencyPolicy >
class SingletonDynamic : public ConcurrencyPolicy
{
public:
static T &instance()
{
return *SingletonDynamic< T, ConcurrencyPolicy >::get_instance();
}
static const T &const_instance()
{
return *SingletonDynamic< T, ConcurrencyPolicy >::get_instance();
}
protected:
SingletonDynamic() {}
virtual ~SingletonDynamic()
{
delete SingletonDynamic< T, ConcurrencyPolicy >::pInstance_;
}
private:
static T *pInstance_;
static volatile bool flag_;
SingletonDynamic( SingletonDynamic const & );
SingletonDynamic &operator=( SingletonDynamic const & );
static T *get_instance()
{
if( SingletonDynamic< T, ConcurrencyPolicy >::flag_ == false ) {
ConcurrencyPolicy::lock_mutex();
if( SingletonDynamic< T, ConcurrencyPolicy >::pInstance_ == NULL ) {
pInstance_ = new T();
}
ConcurrencyPolicy::unlock_mutex();
ConcurrencyPolicy::memory_barrier();
SingletonDynamic< T, ConcurrencyPolicy >::flag_ = true;
return SingletonDynamic< T, ConcurrencyPolicy >::pInstance_;
} else {
ConcurrencyPolicy::memory_barrier();
return SingletonDynamic< T, ConcurrencyPolicy >::pInstance_;
}
}
};
template< typename T, typename ConcurrencyPolicy >
T *SingletonDynamic< T , ConcurrencyPolicy >::pInstance_ = NULL;
template< typename T, typename ConcurrencyPolicy >
volatile bool SingletonDynamic< T , ConcurrencyPolicy >::flag_ = false;