pthread_once单例模式

来源:互联网 发布:高校党员网络教育 编辑:程序博客网 时间:2024/05/03 17:59

实现一个单例模式需要:1>私有的构造函数。2>一个静态方法,返回这个唯一实例的引用。3>一个指针静态变量。4>选择一个解决多线程问题的方法。

1.把构造函数声明为私有,则只有Singleton类内的可以调用构造函数。

2.用静态方法来实例化这个对象,并返回这个对象。

3.利用一个静态变量来记录Singleton类的唯一实例。

4.解决多线程问题的方法如下


在陈硕的《Linux多线程服务端编程》上的使用pthread_once实现的单例模式

关于pthread_once的内容可以看:pthread_once

在static T& instance()中使用pthread_once()调用init,会保证init()只会调用一次。


template<typename T>class Singleton : boost::noncopyable{public:    static T& instance(){        pthread_once(&once_, &Singleton::init);        return *value;    }private:    Singleton();    ~Singleton();    static void init()    {        value_ = new T();    }private:    static pthread_once_t ponce_;    static T* value_;};template<typename T>pthread_once_t Singleton<T>::ponce_ = PTHREAD_ONCE_INIT;template<typename T>T* Singleton<T>::value_ = NULL;
在C++中,std::call_once和std::once_flag代替了上面的pthread_once和pthread_once_t。

自己根据上面思路改编的一个C++单例模式:

Logger.h

#ifndef _LOGGER#define _LOGGER#include <iostream>#include <fstream>#include <vector>#include <string>#include <mutex>#include <thread>class Logger{public:static const std::string kLogLevelDebug;static const std::string kLogLevelInfo;static const std::string kLogLevelError;//static Logger& instance();//Logs a single message void log(const std::string& inMessage,const std::string& inLogLevel);//Logs a vector of messagesvoid log(const std::vector<std::string>& inMessage,const std::string& inLogLevel);private:// Static variable for the one-and-only instancestatic Logger* pInstance;// Constant for the filenamestatic const char* kLogFileName;// Data member for the output streamstd::ofstream mOutputStream;// Logs message.void logHelper(const std::string& inMessage,const std::string& inLogLevel);static void init();private:Logger();~Logger();Logger(const Logger&);Logger& operator=(const Logger&);static std::mutex sMutex;static std::once_flag mOnceFlag;};#endif
Logger.cpp

#include "Logger.h"using namespace std;const string Logger::kLogLevelDebug = "DEBUG";const string Logger::kLogLevelInfo = "INFO";const string Logger::kLogLevelError = "ERROR";const char* Logger::kLogFileName = "log.out";Logger* Logger::pInstance = NULL;once_flag Logger::mOnceFlag;mutex Logger::sMutex;void Logger::init(){pInstance = new Logger();}Logger& Logger::instance(){call_once(Logger::mOnceFlag, &Logger::init);//pthread_once(&ponce_, &Logger::init);return *pInstance;}Logger::~Logger(){mOutputStream.close();}Logger::Logger(){mOutputStream.open(kLogFileName, ios_base::app);if(!mOutputStream.good()){cout<<"Unable to initialize the Logger!"<<endl;}}void Logger::log(const string& inMessage, const string& inLogLevel){lock_guard<mutex> lck(Logger::sMutex);logHelper(inMessage, inLogLevel);}void Logger::log(const vector<string>& inMessages, const string& inLogLevel){lock_guard<mutex> lck(Logger::sMutex);for(size_t i=0; i<inMessages.size(); i++){logHelper(inMessages[i], inLogLevel);}}void Logger::logHelper(const string& inMessage, const string& inLogLevel){mOutputStream<<inLogLevel<<":"<<inMessage<<endl;}


0 0