pthread_once单例模式

实现一个单例模式需要: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 messages
	void log(const std::vector<std::string>& inMessage,
			const std::string& inLogLevel);

private:
	// Static variable for the one-and-only instance
	static Logger* pInstance;
	// Constant for the filename
	static const char* kLogFileName;
	// Data member for the output stream
	std::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;
}


展开阅读全文

没有更多推荐了,返回首页