您的位置:首页 > 其它

一种线程安全的单例模式(10.4.1更新)

2009-11-21 16:50 330 查看
旧版本:

#include <memory>

// 同步对象
class Mutex
{
public:
Mutex()
{
cout << "initial mutex" << endl;
}
~Mutex()
{
cout << "uninitial mutex" << endl;
}
void lock()
{
cout << "lock" << endl;
}
void unlock()
{
cout << "unlock" << endl;
}
};

// 同步资源管理对象
class Guard
{
public:
Guard(Mutex& mtx):
m_mtx(mtx)
{
m_mtx.lock();
}
~Guard()
{
m_mtx.unlock();
}

private:
Mutex   &m_mtx;
};

// 辅助类; 针对每一个会使用的类型都提供一个锁, 这个锁在进入main之前由主线程创建,
// 最后也由主线程销毁; 创建和销毁绝无线程竞争
template<typename T>
struct SingletonHelper
{
static Mutex   cs_mtx;
};
template<typename T>
Mutex SingletonHelper<T>::cs_mtx;

// 针对每一个类提供一个单例访问点; 如果从不访问, 则不会创建多余对象
template<typename T>
T& getInstance()
{
// 智能指针, 保证能够在程序退出时销毁对象, 确保释放跨进程资源
// 由主线程销毁, 绝对安全
// 创建对象时因为可能是多线程同时访问getInstance造成, 所以存在竞争, 由后面的代码解决
static std::auto_ptr<T>  ls_object;
// 后期getInstance调用ls_object.get()非空, 最初可能为空
if (ls_object.get() == NULL)
{
// 由于这个锁, 进入这里的多线程会被限制为轮流进入
Guard grd(SingletonHelper<T>::cs_mtx);
// 第一进入的线程负责创建对象, 后来的线程直接判断为非空
if (ls_object.get() == NULL)
{
// 第一批调用getInstance的线程中, 只有一个能执行这行代码
ls_object.reset(T::createInstance());
}
}
return *ls_object;
}

class Singleton
{
public:
// 公开方法
void method1()
{
cout << "method1 call" << endl;
}

// 为了getInstance能析构
// 因为所有的构造函数已被私有, 所以只要不delete &getInstance();就安全
~Singleton()
{
cout << "last destruct" << endl;
}

private:
// 避免多余的创建
Singleton(int p1, const char *p2)
{
cout << "first construct" << endl;
}
// 禁止拷贝
Singleton& operator = (const Singleton&);
Singleton(const Singleton&);

// 提供给getInstance获取对象
static Singleton* createInstance()
{
return new Singleton('p1', "p2");
}
// 对getInstance放开权限
friend Singleton& getInstance<Singleton>();
};

template<int iIndex>
class Customer
{
public:
Customer(int i, const Singleton&)
{
cout << "customer " << iIndex << '-' << i << " visit" << endl;
}
};
// 全局对象的访问
Customer<0> g_cstm(1, getInstance<Singleton>());

int main()
{
// 全部对象的访问
Customer<1> cstm2(1, getInstance<Singleton>());
getInstance<Singleton>().method1();
Customer<1> cstm3(2, getInstance<Singleton>());
}


我自己使用的版本:

需要boost中的几个组件

#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

#include <windows.h>

namespace Scan
{
typedef unsigned int uint32;

/**
@brief 类分配器

有特殊用处的类应该特化它
*/
template<typename T>
struct ClassAllocator
{
static T* alloc()
{
return new T;
}
static void unalloc(T *p)
{
delete p;
}
};

/**
@brief 资源管理类

保证在析构时调用某函数
*/
class ResGuard
{
public:
/**
@brief 构造函数

@param p 调用函数的参数; 可以是类指针
@param f 要调用的函数; 可以是类成员函数
*/
template<typename T, typename FunType>
ResGuard(FunType f, T *p):
m_f(boost::bind(f, p)){}
~ResGuard()
{
m_f();
}

private:
/**
@brief 用boost::function来解耦
*/
boost::function<void(void)> m_f;
};

class ISyncObject
{
public:
virtual ~ISyncObject() = 0{}

virtual bool lock(uint32 waitTime = -1) = 0;
virtual void unlock() = 0;
};

class SingleLocker
{
public:
SingleLocker(ISyncObject *o):
m_guard(&ISyncObject::unlock, o)
{
o->lock();
}
SingleLocker(ISyncObject &o):
m_guard(&ISyncObject::unlock, &o)
{
o.lock();
}

private:
ResGuard    m_guard;
};

namespace Windows
{
/**
@brief 临界区对象

同一线程不会在同一对象上递归锁住; 即, 临界区对象对每个线程有计数
*/
class CriticalSection:
public ISyncObject
{
public:
CriticalSection();
~CriticalSection();

bool lock(uint32 waitTime = -1);
void unlock();

private:
CRITICAL_SECTION m_cs;
};

CriticalSection::CriticalSection()
{
InitializeCriticalSection(&m_cs);
}

CriticalSection::~CriticalSection()
{
DeleteCriticalSection(&m_cs);
}

bool CriticalSection::lock(uint32 waitTime/* = -1*/)
{
EnterCriticalSection(&m_cs);
return true;
}

void CriticalSection::unlock()
{
LeaveCriticalSection(&m_cs);
}
}

/**
@brief 单例模式

使用它有两个步骤:
1. 继承; class T: public Singleton<T>{}
2. 私有化构造函数, 并添加友元; friend struct classAllocator<T>;
*/
template<typename T, typename MutexType = Windows::CriticalSection>
class ISingleton
{
public:
static T& getSingleton()
{
return *getSingletonPtr();
}

static T* getSingletonPtr()
{
static boost::shared_ptr<T> cs_object;
if (cs_object.get() == NULL)
{
SingleLocker locker(cs_synObject);
if (cs_object.get() == NULL)
{
cs_object =
boost::shared_ptr<T>(
ClassAllocator<T>::alloc(),
&ClassAllocator<T>::unalloc);
}
}
return cs_object.get();
}

protected:
~ISingleton(){}

private:
static MutexType cs_synObject;
};

template<typename T, typename MutexType>
MutexType ISingleton<T, MutexType>::cs_synObject;
}


上面代码的头文件下载(含有一个简单的测试):

http://download.csdn.net/source/2192413
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: