单例模式-通用写法1

首先,基于懒汉式写法,基于线程安全,因此,需要加锁,具体如下:

1.互斥锁写成类,实现自动加锁和解锁(criticalSection.h)

 

#ifndef __criticalSection_h__INCLUDED__
#define __criticalSection_h__INCLUDED__
#include <errno.h>              // EBUSY...and the other errnos

extern "C"
{
#include <pthread.h>            // pthread_mutex_t
}


namespace cmn
{

class PThreadMutex
{
public:

explicit PThreadMutex(
    pthread_mutex_t & mutex_r
    ):
    isAcquired_m( false ),
    mutex_rm    ( mutex_r )
{
    beginCriticalSection();
};

virtual ~PThreadMutex()
{
    endCriticalSection();
    if ( isAcquired_m )
    {
        // endCriticalSection() failed.  This is a serious
        // error.
        return;
    }
};

void beginCriticalSection()
{
    int result = pthread_mutex_lock( &mutex_rm );

    switch ( result )
    {
    case 0:       // success
    {
        isAcquired_m = true;
        return;
    }
    case EINVAL:  // not initialized
    case EDEADLK: // already locked by this thread
    default:      // should never happen
    {
        // TODO SOFTWARE1(result);
        isAcquired_m = false;
        return;
    }}

}//beginCriticalSection

void endCriticalSection()
{
    if (!isAcquired_m)
    {
        return;
    }
    int result = pthread_mutex_unlock( &mutex_rm );
    switch ( result )
    {
        case 0:       // success
        {
            isAcquired_m = false;
            return;
        }
        case EINVAL:  // not initialized
        case EPERM:   // not locked by this thread
        default:      // should never happen
        {
            // TODO SOFTWARE1(result);
            return;
        }
    }

}//endCriticalSection

private:

    bool              isAcquired_m;
    pthread_mutex_t & mutex_rm;

}; //PThreadMutex

};// namespace cmn

#endif //__criticalSection_h__INCLUDED__

2. 懒汉式单例模式(singletonHolder.h)

#ifndef __singletonHolder_h__INCLUDED__
#define __singletonHolder_h__INCLUDED__
#include "criticalSection.h"      // cmn::PThreadMutex

namespace cmn
{
   template < class T >
   class SingletonHolder
   {
   public:
      static T & getInstance();
      // deleteInstance() shoule be used for debugging only.

      // Calling this will "empty" the singleton, however a subsequent call
      // to getInstance will recreate a brand new singleton.

      static void deleteInstance();

   private:
      // prevent accidental construction
      SingletonHolder( );
      SingletonHolder( const SingletonHolder & );

      static T * volatile instance_spm;

   public:
      static pthread_mutex_t mutex_sm;

   };

   template < class T >
   T & SingletonHolder<T>::getInstance()
   {
      // use the "double checked locking pattern"
      if ( !instance_spm )
      {
         cmn::PThreadMutex lock(mutex_sm);
         if ( !instance_spm )
         {
            instance_spm = new T;
         }
      }
      return *instance_spm;

   }//getInstance

   template < class T >
   void SingletonHolder<T>::deleteInstance()
   {
      // use the "double checked locking pattern"
      if ( instance_spm )
      {
         cmn::PThreadMutex lock(mutex_sm);
         if ( instance_spm )
         {
            delete instance_spm;
            instance_spm = 0;
         }
      }

   }//deleteInstance


// We want to define a macro for use of this template. Mainly to simplify
// the declaration of the static members...
#define SINGLETON_HOLDER_INIT( name ) \
   template class cmn::SingletonHolder<name>; \
   template<> name* volatile cmn::SingletonHolder<name>::instance_spm = 0; \
   template<> pthread_mutex_t cmn::SingletonHolder<name>::mutex_sm \
                = PTHREAD_MUTEX_INITIALIZER;


} // namespace cmn

#endif //__singletonPerProcess_h__INCLUDED__

测试代码如下:

#include <iostream>
#include "singletonHolder.h"
#include "criticalSection.h"

using namespace std;
class Server;
#define mdfServer_s ServerHandle::getInstance()
typedef cmn::SingletonHolder<Server> ServerHandle;
SINGLETON_HOLDER_INIT(Server)
class Server
{
public:
    friend class cmn::SingletonHolder<Server>;
     void print(){cout<<i<<endl;}
private:
    Server();
    ~Server();
    int i ;
};

Server::Server():i(0){}

Server::~Server(){}

int main()
{
    (void)mdfServer_s;
    mdfServer_s.print();
    return 0;
}

结果输出:0

 

posted @ 2021-03-19 19:16  白伟碧一些小心得  阅读(50)  评论(0编辑  收藏  举报