#ifdef BASE_LIB_EXPORT_API
# define BASE_LIB_EXPORT __declspec(dllexport)
#else
# define BASE_LIB_EXPORT __declspec(dllimport)
#endif
/** @class
* @brief 禁止拷贝和拷贝构造
*
* 子类使用的模型
* class Foo : private CNoncopyable
* {
* ...
* };
*/
//!! PCLint [error 1509: (Warning -- base class destructor for class 'CNoncopyable' is not virtual)]
//lint -esym(1509, CNoncopyable)
class BASE_LIB_EXPORT CNoncopyable
{
protected:
CNoncopyable() {}
~CNoncopyable() {}
private:
// 将拷贝构造和赋值操作符声明为私有类型
CNoncopyable(const CNoncopyable&);
const CNoncopyable& operator= (const CNoncopyable&);
};
/** @class
* @brief 设计模式的单件模式,用来取代全局变量
*
* 全局只有一份内存,当需要使用的时候才被分配内存
* 使用的时候通过函数Instance()获取对象的引用
*
*
* 2016/09/09 从boost切换为std后,单件有BUG
* 线程1进入Instance,调用static std::mutex mutex;初始化切换到线程2
* 线程2不会再进行static,会直接使用mutex,此时mutex未初始化完成,会崩溃
* boost不会,boost中初始化mutex是不允许被中断切换的
* 修改方法,将static变量从函数中移除,这样和全局变量一样,在程序启动时,就会优先初始化完成
* 单件模式,基类使用的模型
* class MyClass : public CSingleton<MyClass>
* {
* friend class CSingleton<MyClass>;
* private:
* MyClass() {}
* public:
* ...
* };
*/
//!! PCLint [error 1509: (Warning -- base class destructor for class 'CSingleton' is not virtual)]
//lint -esym(1509, CSingleton)
template <class T>
class CSingleton : private CNoncopyable
{
public:
// 访问单件的唯一方式
static T& Instance();
protected:
CSingleton() {}
static std::unique_ptr<T> s_instance_;
static std::mutex mutex_;
};
template<class T>
std::unique_ptr<T> CSingleton<T>::s_instance_;
template<class T>
std::mutex CSingleton<T>::mutex_;
/** @fn T& CSingleton<T>::Instance()
* @brief 获取实例的接口
* @param void
* @return T& 对象的引用
*/
template <class T>
inline T& CSingleton<T>::Instance()
{
if (s_instance_.get() == NULL)
{
std::unique_lock<std::mutex> lock(mutex_); //! 加锁避免同时被创建两个实例
//! CSingleton<T>作用域下互斥量,不需要担心不同类型之间的互斥
if (s_instance_.get() == NULL) // 第二次判断的目的在于不被多线程重复创建
{
s_instance_ = std::unique_ptr<T>(new T);
}
}
return *s_instance_.get();
}