UML软件工程组织

服务器公共库开发--线程安全的singleton类, 可配置的线程锁管理类

 

2008-10-27 来源:cppblog.com

 

在服务器开发中,大量的使用了singleton模式, 以我的工作为例, 用于打印log的类是一个singleton, 内存池管理器是一个singleton...虽然singleton模式实现起来不难, 但是为了避免重复开发, 我还是决定应该把这个类的实现单独拿出来,同时, singleton类还需要支持多线程,但是我从来不写多线程的服务器程序, 对多线程的支持可以通过预编译宏来实现.我把操作多线程锁, 以及singleton类都放在这篇文章中, 多线程锁仅支持linux.

threadmutex.h

/********************************************************************
    created:    2008/08/01
    filename:     threadmutex.h
    author:        Lichuang
                
    purpose:    线程锁类, 由是否定义宏__USE_THREAD__来决定是否使用该类
*********************************************************************/


#ifndef __THREAD_MUTEX_H__
#define __THREAD_MUTEX_H__

#ifdef __USE_THREAD__
    #include <pthread.h>
    
    
#define THREAD_LOCK(tThreadMutex)     tThreadMutex.Lock()
    
#define THREAD_UNLOCK(tThreadMutex)   tThreadMutex.UnLock()
#else
    
#define THREAD_LOCK(tThreadMutex)     
    
#define THREAD_UNLOCK(tThreadMutex)   
#endif

class CThreadMutex
{
public:
    CThreadMutex();
    ~CThreadMutex();
    
int Lock();
    
int UnLock();

private:
#ifdef __USE_THREAD__
    pthread_mutex_t  m_tThreadMutex;
#endif
};

#endif /* __THREAD_MUTEX_H__ */
 

threadmutex.cpp

/********************************************************************
    created:    2008/08/01
    filename:     threadmutex.h
    author:        Lichuang
                
    purpose:    线程锁类, 由是否定义宏__USE_THREAD__来决定是否使用该
                线程锁类
*********************************************************************/


#include "threadmutex.h"

#ifdef __USE_THREAD__

CThreadMutex::CThreadMutex()
{        
    ::pthread_mutex_init(&m_tThreadMutex, NULL);
}

CThreadMutex::~CThreadMutex()
{  
    ::pthread_mutex_destroy(&m_tThreadMutex);
}

int CThreadMutex::Lock()
{
    
return ::pthread_mutex_lock(&m_tThreadMutex);
}

int CThreadMutex::UnLock()
{
    
return ::pthread_mutex_unlock(&m_tThreadMutex);
}

#else

CThreadMutex::CThreadMutex()
{        
}

CThreadMutex::~CThreadMutex()
{  
}

int CThreadMutex::Lock()
{
    
return 0;
}

int CThreadMutex::UnLock()
{
    
return 0;
}

#endif
 

singleton.h

/********************************************************************
    created:    2008/08/01
    filename:     singleton.h
    author:        Lichuang
                
    purpose:    实现单件模式的虚拟基类, 其它需要实现为singleton的类可以
                继承自这个类
                支持多线程, 采用智能指针实现自动回收内存
*********************************************************************/


#ifndef __SINGLETON_H__
#define __SINGLETON_H__

#include <memory>
#include "threadmutex.h"

using namespace std;

#define DECLARE_SINGLETON_CLASS( type ) \
        friend 
class auto_ptr< type >;  \
        friend 
class CSingleton< type >;

template <
class T>
class CSingleton
{
public:
    
static T* GetInstance();

protected:
    CSingleton()
    {
    }
    
virtual ~CSingleton()
    {
    }

protected:    
    friend 
class auto_ptr<CSingleton>;

    
static auto_ptr<T> m_pInstance;
    
static CThreadMutex m_tThreadMutex;
};

template <
class T>
auto_ptr<T> CSingleton<T>::m_pInstance;

template <
class T>
CThreadMutex CSingleton<T>::m_tThreadMutex;

template <
class T>
inline T* CSingleton<T>::GetInstance()
{
    
if (0 == m_pInstance.get())
    {
        THREAD_LOCK(m_tThreadMutex);
        
if (0 == m_pInstance.get())
        {
            m_pInstance.reset(::
new T);
        }
        THREAD_UNLOCK(m_tThreadMutex);
    }

    
return m_pInstance.get();
}

#endif /* __SINGLETON_H__ */
 

使用示例:


#include <iostream>
#include "singleton.h"

using namespace std;

class CTestSingleton
    : 
public CSingleton<CTestSingleton>
{
public:

    
void Set(int a)
    {
        m_a = a;
    }
    
int Get()
    {
        
return m_a;
    }

private:
    CTestSingleton()
        : m_a(0)
    {

    }
    DECLARE_SINGLETON_CLASS(CTestSingleton)
private:
    
int m_a;
};

int main()
{
    
if (NULL == CTestSingleton::GetInstance())
    {
        cout << "GetInstance() error!" << endl;
    }

    cout << "before set: " << CTestSingleton::GetInstance()->Get() << endl;

    CTestSingleton::GetInstance()->Set(100);

    cout << "after set: " << CTestSingleton::GetInstance()->Get() << endl;

    
return 0;
}