将设计模式运用于游戏设计:将日志做成单件
来源:互联网 发布:html js页面传值 编辑:程序博客网 时间:2024/05/18 16:38
在游戏程序中日志显得非常重要,例如在调试AI的时候需要连续跟踪AI状态的变化,在非正常的函数返回点记录状态信息等等。但是这一系列的log如果没有统一管理那么将变得很混乱,而且在多线程的情况下有可能会出现同步问题。为此专门用单件的模式制作了一个日志类,希望能派的上用场。不多说了,直接贴代码,原理很简单,关键地方有注释。
log.h
#include <windows.h>
#include <fstream>
class CSynObj
{
public:
CSynObj()
{
InitializeCriticalSection(&m_cs);
}
~CSynObj()
{
DeleteCriticalSection(&m_cs);
}
void Lock()
{
EnterCriticalSection(&m_cs);
}
void UnLock()
{
LeaveCriticalSection(&m_cs);
}
private:
CRITICAL_SECTION m_cs;
};
class CLock
{
public:
CLock(CSynObj& synchobject)
:refSynchObject(synchobject)
{
refSynchObject.Lock();
}
virtual ~CLock()
{
refSynchObject.UnLock();
}
protected:
CSynObj& refSynchObject;
};
enum LOG_TARGET_E
{
LOG_TARGET_SCREEN = 1,
LOG_TARGET_FILE = 2,
};
class CLog
{
private:
~CLog();
CLog();
CLog(const CLog& rhs) {}
CLog& operator = (const CLog& rhs) {}
static CLog* m_pLog;
static CSynObj m_Lock;
std::ofstream m_OutFile;
void GetSysTime(SYSTEMTIME* lpSysTime);
void FormatAllTime(const SYSTEMTIME& refSysTime, std::string& strOut);
public:
void Write(char* pMsg, int nTarget);
static CLog* GetInstance();
// 摧毁singleton的入口
static void DestroyInstance();
};
__inline void DEBUG_MSG(LPSTR filename, int lineno, LPSTR linedesc, DWORD dwErrCode, int nOutPutTarget = LOG_TARGET_SCREEN|LOG_TARGET_FILE)
{
char cTemp[256];
sprintf( cTemp, "%lu error on %d line in %s file: %s", dwErrCode, lineno, filename, linedesc );
CLog* pLog = CLog::GetInstance();
pLog->Write( cTemp, nOutPutTarget );
}
#include <fstream>
class CSynObj
{
public:
CSynObj()
{
InitializeCriticalSection(&m_cs);
}
~CSynObj()
{
DeleteCriticalSection(&m_cs);
}
void Lock()
{
EnterCriticalSection(&m_cs);
}
void UnLock()
{
LeaveCriticalSection(&m_cs);
}
private:
CRITICAL_SECTION m_cs;
};
class CLock
{
public:
CLock(CSynObj& synchobject)
:refSynchObject(synchobject)
{
refSynchObject.Lock();
}
virtual ~CLock()
{
refSynchObject.UnLock();
}
protected:
CSynObj& refSynchObject;
};
enum LOG_TARGET_E
{
LOG_TARGET_SCREEN = 1,
LOG_TARGET_FILE = 2,
};
class CLog
{
private:
~CLog();
CLog();
CLog(const CLog& rhs) {}
CLog& operator = (const CLog& rhs) {}
static CLog* m_pLog;
static CSynObj m_Lock;
std::ofstream m_OutFile;
void GetSysTime(SYSTEMTIME* lpSysTime);
void FormatAllTime(const SYSTEMTIME& refSysTime, std::string& strOut);
public:
void Write(char* pMsg, int nTarget);
static CLog* GetInstance();
// 摧毁singleton的入口
static void DestroyInstance();
};
__inline void DEBUG_MSG(LPSTR filename, int lineno, LPSTR linedesc, DWORD dwErrCode, int nOutPutTarget = LOG_TARGET_SCREEN|LOG_TARGET_FILE)
{
char cTemp[256];
sprintf( cTemp, "%lu error on %d line in %s file: %s", dwErrCode, lineno, filename, linedesc );
CLog* pLog = CLog::GetInstance();
pLog->Write( cTemp, nOutPutTarget );
}
log.cpp
#include <iostream>
#include <log.h>
CLog* CLog::m_pLog = NULL;
CSynObj CLog::m_Lock;
CLog::~CLog()
{
m_OutFile.close();
}
CLog::CLog()
{
m_OutFile.open( "Log.txt", std::ios::app );
atexit( CLog::DestroyInstance );
}
void CLog::GetSysTime(SYSTEMTIME* lpSysTime)
{
//获得系统时间
FILETIME CurFileTime;
::GetSystemTimeAsFileTime(&CurFileTime);
::FileTimeToLocalFileTime(&CurFileTime, &CurFileTime);
::FileTimeToSystemTime(&CurFileTime, lpSysTime);
}
void CLog::FormatAllTime(const SYSTEMTIME& refSysTime, std::string& strOut)
{
//系统时间转换成字符串
char cBuffer[MAX_PATH*2];
sprintf(cBuffer,"%d-%02d-%02d %02d:%02d:%02d",
refSysTime.wYear, refSysTime.wMonth, refSysTime.wDay , refSysTime.wHour , refSysTime.wMinute , refSysTime.wSecond);
strOut = cBuffer;
}
void CLog::Write(char* pMsg, int nTarget)
{
// 区间锁,在同一时刻只允许一个线程进行写文件或屏幕
CLock Lock( CLog::m_Lock );
SYSTEMTIME Systime;
std::string strTime;
GetSysTime( &Systime );
FormatAllTime( Systime, strTime );
if( nTarget & LOG_TARGET_FILE )
m_OutFile << strTime.c_str() << ": " << pMsg << std::endl;
if( nTarget & LOG_TARGET_SCREEN )
std::cout << pMsg << std::endl;
}
CLog* CLog::GetInstance()
{
// 双次检测的好处
// 1:防止多线程同时进入new CLog;
// 2:临界区写在第二次判断,提高了效率
if( !m_pLog )
{
CLock Lock( CLog::m_Lock );
if( !m_pLog )
m_pLog = new CLog;
}
return m_pLog;
}
// 与GetInstance对应,给CLog一个delete的机会
void CLog::DestroyInstance()
{
delete m_pLog;
m_pLog = NULL;
}
int main()
{
atexit( CLog::DestroyInstance );
DEBUG_MSG( __FILE__, __LINE__, "main()", 0 );
getchar();
return 0;
}
#include <log.h>
CLog* CLog::m_pLog = NULL;
CSynObj CLog::m_Lock;
CLog::~CLog()
{
m_OutFile.close();
}
CLog::CLog()
{
m_OutFile.open( "Log.txt", std::ios::app );
atexit( CLog::DestroyInstance );
}
void CLog::GetSysTime(SYSTEMTIME* lpSysTime)
{
//获得系统时间
FILETIME CurFileTime;
::GetSystemTimeAsFileTime(&CurFileTime);
::FileTimeToLocalFileTime(&CurFileTime, &CurFileTime);
::FileTimeToSystemTime(&CurFileTime, lpSysTime);
}
void CLog::FormatAllTime(const SYSTEMTIME& refSysTime, std::string& strOut)
{
//系统时间转换成字符串
char cBuffer[MAX_PATH*2];
sprintf(cBuffer,"%d-%02d-%02d %02d:%02d:%02d",
refSysTime.wYear, refSysTime.wMonth, refSysTime.wDay , refSysTime.wHour , refSysTime.wMinute , refSysTime.wSecond);
strOut = cBuffer;
}
void CLog::Write(char* pMsg, int nTarget)
{
// 区间锁,在同一时刻只允许一个线程进行写文件或屏幕
CLock Lock( CLog::m_Lock );
SYSTEMTIME Systime;
std::string strTime;
GetSysTime( &Systime );
FormatAllTime( Systime, strTime );
if( nTarget & LOG_TARGET_FILE )
m_OutFile << strTime.c_str() << ": " << pMsg << std::endl;
if( nTarget & LOG_TARGET_SCREEN )
std::cout << pMsg << std::endl;
}
CLog* CLog::GetInstance()
{
// 双次检测的好处
// 1:防止多线程同时进入new CLog;
// 2:临界区写在第二次判断,提高了效率
if( !m_pLog )
{
CLock Lock( CLog::m_Lock );
if( !m_pLog )
m_pLog = new CLog;
}
return m_pLog;
}
// 与GetInstance对应,给CLog一个delete的机会
void CLog::DestroyInstance()
{
delete m_pLog;
m_pLog = NULL;
}
int main()
{
atexit( CLog::DestroyInstance );
DEBUG_MSG( __FILE__, __LINE__, "main()", 0 );
getchar();
return 0;
}
- 将设计模式运用于游戏设计:将日志做成单件
- 将设计模式运用于游戏设计:适配器模式
- 将设计模式运用于游戏设计:工厂方法
- 设计模式-单件
- 【设计模式】单件
- 设计模式---单件
- 设计模式------单件模式
- 设计模式--单件模式
- 设计模式 -- 单件模式
- 设计模式:单件模式
- 设计模式-单件模式
- 设计模式-单件模式
- 设计模式 单件模式
- 设计模式:单件模式
- 设计模式----单件模式
- 设计模式--单件模式
- 设计模式-单件模式
- 设计模式--单件模式
- ASIHTTPRequest系列(一):同步和异步请求 .
- 第十一周第四天 自定义函数
- 小白学Linux之gcc的一些常见用法
- 测试的几个方面
- GridView数据导出
- 将设计模式运用于游戏设计:将日志做成单件
- js滚动字幕3
- Apache2服务器因为端口被占用导致无法访问的解决方法
- hdu 1325 is it a tree? 5.1.3
- 一步一步写算法(之 A*算法)
- ASIHTTPRequest系列(二):文件下载 .
- 将设计模式运用于游戏设计:适配器模式
- 如何在Xcode下使用SVN?
- ASIHTTPRequest系列(三):文件上传 .