类单例的实现。(一个单例的线程安全日志类)

单例类是一个不允许定义类实例的特殊类。它在某些情况下是非常有用的。例如在多线程程序下写运行日志的类,如果允许类的多个实例同时写日志,则存在线程安全性问题(对同一日志文件读/写操作不能很好的互斥)。下面以代码为例,展示单例的线程安全日志类实现。(代码已封装好,可复用)

 

C++专有下的单例实现

log.h

#pragma once #ifdef LOG_EXPORTS #define LOG_API __declspec(dllexport) #else #define LOG_API __declspec(dllimport) #endif #include #include // This class is exported from the Log.dll class LOG_API CLog { public: static CLog& GetInstance(); public: // 添加日志 int AddLog(char* pszLogTxt); // 设置日志文件存放路径 void SetLogPath(const char* szLogPath); // 清空日志文件 int ClearLog(); protected: char m_szLogPath[MAX_PATH]; FILE* m_pLogFile; // 构造线程安全类 CRITICAL_SECTION m_cs; private: CLog(); ~CLog(); };

 

log.cpp

#include "stdafx.h" #include "Log.h" #include // This is the constructor of a class that has been exported. // see Log.h for the class definition CLog::CLog() { // 默认放在程序运行目录下 char szConfigPath[MAX_PATH]={0}; //获取EXE全路径 char szExePath[MAX_PATH]={0}; GetModuleFileNameA( NULL, (LPCH)szExePath, MAX_PATH ); char *tmp=szExePath; while(strchr(tmp,'//') != NULL) //截取全路径名 { tmp = strchr(tmp,'//') + 1; } szExePath[strlen(szExePath) - strlen(tmp)] = '/0'; sprintf( m_szLogPath,"%srun.log", szExePath ); m_pLogFile = NULL; InitializeCriticalSection(&m_cs); } CLog::~CLog() { }; int CLog::AddLog(char* pszLogTxt) { time_t t = time(0); char szTime[MAX_PATH]; strftime( szTime, sizeof(szTime), "%Y/%m/%d %X",localtime(&t) ); EnterCriticalSection(&m_cs); m_pLogFile = fopen(m_szLogPath, "a+"); fprintf(m_pLogFile, "[%s]: %s/n", szTime, pszLogTxt); fclose(m_pLogFile); LeaveCriticalSection(&m_cs); return 0; } void CLog::SetLogPath(const char* szLogPath) { strcpy(m_szLogPath, szLogPath); } int CLog::ClearLog() { EnterCriticalSection(&m_cs); m_pLogFile = fopen(m_szLogPath, "w"); fclose(m_pLogFile); LeaveCriticalSection(&m_cs); return 0; } CLog& CLog::GetInstance() { static CLog instance; return instance; }

 

其他通用实现(C++代码示例)

log.h

#pragma once #ifdef LOG_EXPORTS #define LOG_API __declspec(dllexport) #else #define LOG_API __declspec(dllimport) #endif #include #include // This class is exported from the Log.dll class LOG_API CLog { public: static CLog* GetInstance(); public: // 添加日志 int AddLog(char* pszLogTxt); // 设置日志文件存放路径 void SetLogPath(const char* szLogPath); // 清空日志文件 int ClearLog(); protected: char m_szLogPath[MAX_PATH]; FILE* m_pLogFile; // 构造线程安全类 CRITICAL_SECTION m_cs; private: CLog(); ~CLog(); static CLog* m_pLog; };

 

log.cpp

#include "stdafx.h" #include "Log.h" #include CLog* CLog::m_pLog = NULL; // This is the constructor of a class that has been exported. // see Log.h for the class definition CLog::CLog() { // 默认放在程序运行目录下 char szConfigPath[MAX_PATH]={0}; //获取EXE全路径 char szExePath[MAX_PATH]={0}; GetModuleFileNameA( NULL, (LPCH)szExePath, MAX_PATH ); char *tmp=szExePath; while(strchr(tmp,'//') != NULL) //截取全路径名 { tmp = strchr(tmp,'//') + 1; } szExePath[strlen(szExePath) - strlen(tmp)] = '/0'; sprintf( m_szLogPath,"%srun.log", szExePath ); m_pLogFile = NULL; InitializeCriticalSection(&m_cs); } CLog::~CLog() { if(m_pLog) { delete m_pLog; m_pLog = NULL; } }; int CLog::AddLog(char* pszLogTxt) { time_t t = time(0); char szTime[MAX_PATH]; strftime( szTime, sizeof(szTime), "%Y/%m/%d %X",localtime(&t) ); EnterCriticalSection(&m_cs); m_pLogFile = fopen(m_szLogPath, "a+"); fprintf(m_pLogFile, "[%s]: %s/n", szTime, pszLogTxt); fclose(m_pLogFile); LeaveCriticalSection(&m_cs); return 0; } void CLog::SetLogPath(const char* szLogPath) { strcpy(m_szLogPath, szLogPath); } int CLog::ClearLog() { EnterCriticalSection(&m_cs); m_pLogFile = fopen(m_szLogPath, "w"); fclose(m_pLogFile); LeaveCriticalSection(&m_cs); return 0; } CLog* CLog::GetInstance() { if(NULL == m_pLog) { m_pLog = new CLog; } return m_pLog; }

你可能感兴趣的