解析一个单例模式

该单例模式的例子来自《C++高级编程 第二版》

这个单例模式一点特殊之处就是它的析构部分,这里采用了一个Cleanup类来完成这一项工作。在Logger的instance()函数中,定义了一个static的Cleanup变量cleanup。因此不管instance()被调用多少次,只有一个cleanup。而程序结束时,这个static变量会自动销毁,然后就会调用cleanup的析构函数释放Logger中的指针成员pInstance所指的空间。

贴上代码:

Logger.h

#ifndef _LOGGER
#define _LOGGER

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <pthread.h>

class Logger
{
public:
	static const std::string kLogLevelDebug;
	static const std::string kLogLevelInfo;
	static const std::string kLogLevelError;
	// KEY
	static Logger& instance();
	// Logs a single message at the given log level
	void log(const std::string& inMessage,
			const std::string& inLogLevel);
	// Logs a vector of messages at the given log level
	void log(const std::vector<std::string>& inMessage,
			const std::string& inLogLevel);

protected:
	// Static variable for the one-and-only instance
	static Logger* pInstance;
	// Constant for the filename
	static const char* const kLogFileName;
	// Data member for the output stream
	std::ofstream mOutputStream;
	// Embedded class to make sure the single Logger
	// instance gets deleted on program shutdown.
	friend class Cleanup;
	class Cleanup
	{
	public:
		~Cleanup();
	};
	// Logs message. The thread should own a lock on sMutex
	// before calling this function
	void logHelper(const std::string& inMessage,
			const std::string& inLogLevel);

private:
	Logger();
	virtual ~Logger();
	// 复制构造函数
	Logger(const Logger&);
	Logger& operator=(const Logger&);
	static pthread_mutex_t sMutex;
};

#endif
Logger.cpp

#include <stdexcept>
#include "Logger.h"
using namespace std;

const string Logger::kLogLevelDebug = "DEBUG";
const string Logger::kLogLevelInfo = "INFO";
const string Logger::kLogLevelError = "ERROR";
const char* const Logger::kLogFileName = "log.out";
Logger* Logger::pInstance = NULL;
pthread_mutex_t Logger::sMutex = PTHREAD_MUTEX_INITIALIZER;

Logger& Logger::instance()
{
	// 我估计这是个bug
	static Cleanup cleanup;
	pthread_mutex_lock(&sMutex);
	if(pInstance == NULL)
	{
		pInstance = new Logger();
	}
	pthread_mutex_unlock(&sMutex);
	return *pInstance;
}

Logger::Cleanup::~Cleanup()
{
	pthread_mutex_lock(&sMutex);
	delete Logger::pInstance;
	Logger::pInstance = NULL;
	pthread_mutex_unlock(&sMutex);
}

Logger::~Logger()
{
	mOutputStream.close();
}

Logger::Logger()
{
	mOutputStream.open(kLogFileName, ios_base::app);
	if(!mOutputStream.good()){
		throw runtime_error("Unable to initialize the Logger!");
	}
}

void Logger::log(const string& inMessage, const string& inLogLevel)
{
	pthread_mutex_lock(&sMutex);
	logHelper(inMessage, inLogLevel);
	pthread_mutex_unlock(&sMutex);
}

void Logger::log(const vector<string>& inMessages, const string& inLogLevel)
{
	pthread_mutex_lock(&sMutex);
	for(size_t i=0; i < inMessages.size(); i++){
		logHelper(inMessages[i], inLogLevel);
	}
	pthread_mutex_unlock(&sMutex);
}

void Logger::logHelper(const string& inMessage, const string& inLogLevel)
{
	mOutputStream << inLogLevel << ":" << inMessage << endl;
}

测试代码test.cpp

//============================================================================
// Name        : C__TEST.cpp
// Author      : 
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <pthread.h>
#include <unistd.h>
#include "Logger.h"


void* LogMessage1(void* data)
{
	std::cout<< "111" << std::endl;
	Logger::instance().log("test t1", Logger::kLogLevelDebug);
	return ((void*)0);
}

void* LogMessage2(void* data)
{
	std::cout<< "111" << std::endl;
	Logger::instance().log("test t2", Logger::kLogLevelDebug);
	return ((void*)1);
}

int main() {
	/*
	pthread_t t1,t2;
	pthread_create(&t1, NULL, LogMessage1, NULL);
	pthread_create(&t2, NULL, LogMessage2, NULL);
	*/

	//Logger::instance().log("test message", Logger::kLogLevelDebug);
	Logger::instance().log("new message", Logger::kLogLevelDebug);


	sleep(2);
	std::cout << "!!!Hello World!!!" << std::endl; // prints !!!Hello World!!!
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值