在最近的一個項目中,我不得不創建一個Singleton類,經過在Google上大量的研究,我想出了這個模板類的定義。這個想法是從這個模板類派生,並使派生類的構造函數protected/private。它似乎工作得很好,但我只用它在一個項目中的單個類,所以我希望你們中的一些人可以指出,如果我在實現中犯了錯誤。那就是:C++單例模板類
/**
* @brief
* Singleton design pattern implementation using a dynamically allocated singleton instance.
*
* The SingletonDynamic class is intended for use as a base for classes implementing the Singleton
* design pattern and require lazy initialization of the singleton object. The default
* implementation is not thread-safe, however, the derived classes can make it so by reinitializing
* the function pointers SingletonDynamic<T>::pfnLockMutex, SingletonDynamic<T>::pfnUnlockMutex
* and SingletonDynamic<T>::pfnMemoryBarrier. The member function pointers are initialized by
* default to point to placeholder functions that do not perform any function. The derived class
* must provide alternate implementations for SingletonDynamic<T>::lock_mutex(),
* SingletonDynamic<T>::unlock_mutex() and SingletonDynamic<T>::memory_barrier() respectively
* and reinitialize the respective function pointer members to these alternate implementations.
*
* @tparam T
* The type name of the derived (singleton) class
*
* @note The derived class must have a no-throw default constructor and a no-throw destructor.
* @note The derived class must list this class as a friend, since, by necessity, the derived class'
* constructors must be protected/private.
*/
template< typename T >
class SingletonDynamic
{
public:
/**
* Factory function for vending mutable references to the sole instance of the singleton object.
*
* @return A mutable reference to the one and only instance of the singleton object.
*/
static T &instance()
{
return *SingletonDynamic<T>::get_instance();
}
/**
* Factory function for vending constant references to the sole instance of the singleton object.
*
* @return A constant reference to the one and only instance of the singleton object.
*/
static const T &const_instance()
{
return *SingletonDynamic<T>::get_instance();
}
protected:
/** Default constructor */
SingletonDynamic() {}
/** Destructor */
virtual ~SingletonDynamic()
{
delete SingletonDynamic<T>::pInstance_;
}
/** Defines an alias for a function pointer type for executing functions related to thread-safety */
typedef void(*coherence_callback_type)();
/**
* Pointer to a function that will lock a mutex denying access to threads other that the current
*
* @note The function must have the signature void foo()
* @note The derived class must never set this variable to NULL, doing so will cause a crash. The
* default value must be left unchanged if this functionality is not desired.
*/
static coherence_callback_type pfnLockMutex;
/**
* Pointer to a function that will unlock a mutex allowing access to other threads
*
* @note The function must have the signature void foo()
* @note The derived class must never set this variable to NULL, doing so will cause a crash. The
* default value must be left unchanged if this functionality is not desired.
*/
static coherence_callback_type pfnUnlockMutex;
/**
* Pointer to a function that executes a memory barrier instruction that prevents the compiler
* from reordering reads and writes across this boundary.
*
* @note The function must have the signature void foo()
* @note The derived class must never set this variable to NULL, doing so will cause a crash. The
* default value must be left unchanged if this functionality is not desired.
*/
static coherence_callback_type pfnMemoryBarrier;
private:
/** The sole instance of the singleton object */
static T *pInstance_;
/** Flag indicating whether the singleton object has been created */
static volatile bool flag_;
/** Private copy constructor to prevent copy construction */
SingletonDynamic(SingletonDynamic const &);
/** Private operator to prevent assignment */
SingletonDynamic &operator=(SingletonDynamic const &);
/**
* Fetches a pointer to the singleton object, after creating it if necessary
*
* @return A pointer to the one and only instance of the singleton object.
*/
static T *get_instance()
{
if(SingletonDynamic<T>::flag_ == false) {
/* acquire lock */
(*SingletonDynamic<T>::pfnLockMutex)();
if(SingletonDynamic<T>::pInstance_ == NULL) {
pInstance_ = new T();
}
/* release lock */
(*SingletonDynamic<T>::pfnUnlockMutex)();
/* enforce all prior I/O to be completed */
(*SingletonDynamic<T>::pfnMemoryBarrier)();
SingletonDynamic<T>::flag_ = true;
return SingletonDynamic<T>::pInstance_;
} else {
/* enforce all prior I/O to be completed */
(*SingletonDynamic<T>::pfnMemoryBarrier)();
return SingletonDynamic<T>::pInstance_;
}
}
/**
* Placeholder function for locking a mutex, thereby preventing access to other threads. This
* default implementation does not perform any function, the derived class must provide an
* implementation if this functionality is desired.
*/
inline static void lock_mutex()
{
/* default implementation does nothing */
return;
}
/**
* Placeholder function for unlocking a mutex, thereby allowing access to other threads. This
* default implementation does not perform any function, the derived class must provide an
* implementation if this functionality is desired.
*/
inline static void unlock_mutex()
{
/* default implementation does nothing */
return;
}
/**
* Placeholder function for executing a memory barrier instruction, thereby preventing the
* compiler from reordering read and writes across this boundary. This default implementation does
* not perform any function, the derived class must provide an implementation if this
* functionality is desired.
*/
inline static void memory_barrier()
{
/* default implementation does nothing */
return;
}
};
/* Initialize the singleton instance pointer */
template< typename T >
T *SingletonDynamic<T>::pInstance_ = NULL;
/* Initialize the singleton flag */
template< typename T >
volatile bool SingletonDynamic<T>::flag_ = false;
/* Initialize the function pointer that locks the mutex */
template< typename T >
typename SingletonDynamic<T>::coherence_callback_type SingletonDynamic<T>::pfnLockMutex
= &SingletonDynamic<T>::lock_mutex;
/* Initialize the function pointer that unlocks the mutex */
template< typename T >
typename SingletonDynamic<T>::coherence_callback_type SingletonDynamic<T>::pfnUnlockMutex
= &SingletonDynamic<T>::unlock_mutex;
/* Initialize the function pointer that executes the memory barrier instruction */
template< typename T >
typename SingletonDynamic<T>::coherence_callback_type SingletonDynamic<T>::pfnMemoryBarrier
= &SingletonDynamic<T>::memory_barrier;
我特別擔心在頭文件是否是靜態成員初始化將導致多個定義錯誤時,被包含在多個是從SingleDynamic派生的類的頭文件文件。我已經試過了,它似乎工作,但我不明白爲什麼它的工作:)。
在此先感謝, Ashish。
編輯:修改實施使用在接受的解決方案中建議的基於策略的設計。
/**
* This is the default ConcurrencyPolicy implementation for the SingletonDynamic class. This
* implementation does not provide thread-safety and is merely a placeholder. Classes deriving from
* SingletonDynamic must provide alternate ConcurrencyPolicy implementations if thread-safety is
* desired.
*/
struct DefaultSingletonConcurrencyPolicy
{
/**
* Placeholder function for locking a mutex, thereby preventing access to other threads. This
* default implementation does not perform any function, the derived class must provide an
* alternate implementation if this functionality is desired.
*/
static void lock_mutex()
{
/* default implementation does nothing */
return;
}
/**
* Placeholder function for unlocking a mutex, thereby allowing access to other threads. This
* default implementation does not perform any function, the derived class must provide an
* alternate implementation if this functionality is desired.
*/
static void unlock_mutex()
{
/* default implementation does nothing */
return;
}
/**
* Placeholder function for executing a memory barrier instruction, thereby preventing the
* compiler from reordering read and writes across this boundary. This default implementation does
* not perform any function, the derived class must provide an alternate implementation if this
* functionality is desired.
*/
static void memory_barrier()
{
/* default implementation does nothing */
return;
}
};
/**
* @brief
* Singleton design pattern implementation using a dynamically allocated singleton instance.
*
* The SingletonDynamic class is intended for use as a base for classes implementing the Singleton
* design pattern and that dynamic allocation of the singleton object. The default implementation
* is not thread-safe; however, the class uses a policy-based design pattern that allows the derived
* classes to achieve threaad-safety by providing an alternate implementation of the
* ConcurrencyPolicy.
*
* @tparam T
* The type name of the derived (singleton) class
* @tparam ConcurrencyPolicy
* The policy implementation for providing thread-safety
*
* @note The derived class must have a no-throw default constructor and a no-throw destructor.
* @note The derived class must list this class as a friend, since, by necessity, the derived class'
* constructors must be protected/private.
*/
template< typename T, typename ConcurrencyPolicy = DefaultSingletonConcurrencyPolicy >
class SingletonDynamic : public ConcurrencyPolicy
{
public:
/**
* Factory function for vending mutable references to the sole instance of the singleton object.
*
* @return A mutable reference to the one and only instance of the singleton object.
*/
static T &instance()
{
return *SingletonDynamic< T, ConcurrencyPolicy >::get_instance();
}
/**
* Factory function for vending constant references to the sole instance of the singleton object.
*
* @return A constant reference to the one and only instance of the singleton object.
*/
static const T &const_instance()
{
return *SingletonDynamic< T, ConcurrencyPolicy >::get_instance();
}
protected:
/** Default constructor */
SingletonDynamic() {}
/** Destructor */
virtual ~SingletonDynamic()
{
delete SingletonDynamic< T, ConcurrencyPolicy >::pInstance_;
}
private:
/** The sole instance of the singleton object */
static T *pInstance_;
/** Flag indicating whether the singleton object has been created */
static volatile bool flag_;
/** Private copy constructor to prevent copy construction */
SingletonDynamic(SingletonDynamic const &);
/** Private operator to prevent assignment */
SingletonDynamic &operator=(SingletonDynamic const &);
/**
* Fetches a pointer to the singleton object, after creating it if necessary
*
* @return A pointer to the one and only instance of the singleton object.
*/
static T *get_instance()
{
if(SingletonDynamic< T, ConcurrencyPolicy >::flag_ == false) {
/* acquire lock */
ConcurrencyPolicy::lock_mutex();
/* create the singleton object if this is the first time */
if(SingletonDynamic< T, ConcurrencyPolicy >::pInstance_ == NULL) {
pInstance_ = new T();
}
/* release lock */
ConcurrencyPolicy::unlock_mutex();
/* enforce all prior I/O to be completed */
ConcurrencyPolicy::memory_barrier();
/* set flag to indicate singleton has been created */
SingletonDynamic< T, ConcurrencyPolicy >::flag_ = true;
return SingletonDynamic< T, ConcurrencyPolicy >::pInstance_;
} else {
/* enforce all prior I/O to be completed */
ConcurrencyPolicy::memory_barrier();
return SingletonDynamic< T, ConcurrencyPolicy >::pInstance_;
}
}
};
/* Initialize the singleton instance pointer */
template< typename T, typename ConcurrencyPolicy >
T *SingletonDynamic< T , ConcurrencyPolicy >::pInstance_ = NULL;
/* Initialize the singleton flag */
template< typename T, typename ConcurrencyPolicy >
volatile bool SingletonDynamic< T , ConcurrencyPolicy >::flag_ = false;
[你做**不需要**單身人士。](http://jalf.dk/blog/2010/03/singletons-solving-problems-you-didnt-know-you-never-had-since -1995 /)不要使用單身。你想要一個全球的,所以使用全球。 – GManNickG 2010-08-09 22:06:09
我同意GMan不要使用singeltons。我不同意它們與全局變量相同(延遲初始化)。我討厭使用指針作爲表示,因爲它們不會自動刪除(在get_instance()中使用靜態函數變量(保持鎖定),這樣singleton將被正確刪除)。 PS。您需要在鎖內移動'flag_ = true;',否則您可能會創建多個線程來創建實例。 – 2010-08-09 23:33:20
@Martin:你可以偷獨立創作的解決方案來創建一個不錯的全局實用程序庫。它主要是混淆和不必要的限制性實例廢話。我正在考慮向Boost提交一個全球圖書館,因爲它缺少一個。 – GManNickG 2010-08-10 00:25:20