⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xytrace.cpp

📁 trace c++ thread,用于c++处理多线程工作
💻 CPP
字号:

#include "XYTrace.h"

// private helper class
class XYTraceHelper
{
	// friend functions of this class
	friend void SetTraceFilePrefix(LPCTSTR strFilePrefix);
	friend void SetTraceLevel(const int nLevel);
	friend void WriteTrace(const int nLevel, LPCTSTR strFormat, ...);
	// internal data members
	HANDLE	m_hFile;
	int m_nLevel;
	long m_nThreadId;
	TCHAR* m_pTraceFilePrefix;
	SYSTEMTIME m_timeStart;
	// close the current trace file
	void CloseTraceFile()
	{
		if(m_hFile) ::CloseHandle(m_hFile);
		m_hFile = NULL;
	}
	// open a new trace file
	HANDLE OpenTraceFile()
	{
		// construct the new trace file path
		TCHAR strFilePath[1001];
		SYSTEMTIME sysTime;
		::GetLocalTime(&sysTime);
		_stprintf
		(
			strFilePath,
			_T("%s_%04d%02d%02d_%02d%02d%02d_%X.txt"),
			m_pTraceFilePrefix?m_pTraceFilePrefix:_T("Trace"),
			sysTime.wYear,
			sysTime.wMonth,
			sysTime.wDay,
			sysTime.wHour,
			sysTime.wMinute,
			sysTime.wSecond,
			::GetCurrentProcessId()
		);
		// create the new trace file
		m_hFile = CreateFile
		(
			strFilePath,
			GENERIC_WRITE,
			FILE_SHARE_READ,
			NULL,
			CREATE_ALWAYS,
			FILE_ATTRIBUTE_NORMAL,
			NULL
		);
		// if successful, save the start time variable
		if(m_hFile) m_timeStart = sysTime;
		// return the file handle
		return m_hFile;
	}
	// set lock to gain exclusive access to trace
	// functions
	void Lock()
	{
		long nThreadId = ::GetCurrentThreadId();
		while(m_nThreadId!=nThreadId)
		{
			// keep trying until successfully completed the operation
			::InterlockedCompareExchange((void**)&m_nThreadId, (void*)nThreadId, 0);
			if(m_nThreadId==nThreadId) break;
			::Sleep(25);
		}
	}
	// release lock so that other threads can access 
	// trace functions
	void Unlock()
	{
		// only the thread that set the lock can release it
		::InterlockedCompareExchange((void**)&m_nThreadId, 0, (void*)::GetCurrentThreadId());
	}
	// set the current trace level
	void SetTraceLevel(const int nLevel) { m_nLevel = nLevel>0?nLevel:0; }
	// set the trace file name prefix
	void SetTraceFilePrefix(LPCTSTR strFilePrefix)
	{
		// close existing trace file first
		CloseTraceFile();
		// copy the file name prefix
		int nSize = strFilePrefix?_tcslen(strFilePrefix):0;
		delete []m_pTraceFilePrefix;
		m_pTraceFilePrefix = new TCHAR[nSize+1];
		_tcscpy(m_pTraceFilePrefix, nSize>0?strFilePrefix:_T(""));
	}
public:
	// constructor and destructor
	XYTraceHelper()
	{
		m_hFile = NULL;
		m_nLevel = 0;
		m_nThreadId = 0;
		m_pTraceFilePrefix = NULL;
	}
	~XYTraceHelper()
	{
		CloseTraceFile();
		delete []m_pTraceFilePrefix;
	}
};

// the one and only instance of XYTraceHelper
XYTraceHelper theHelper;

void SetTraceFilePrefix(LPCTSTR strFilePrefix)
{
	// set lock
	theHelper.Lock();
	// set trace file name prefix
	theHelper.SetTraceFilePrefix(strFilePrefix);
	// release lock
	theHelper.Unlock();
}

void SetTraceLevel(const int nLevel)
{
	// set lock
	theHelper.Lock();
	// set trace level
	theHelper.SetTraceLevel(nLevel);
	// release lock
	theHelper.Unlock();
}

void WriteTrace(const int nLevel, LPCTSTR strFormat, ...)
{
	// if the specified trace level is greater than
	// the current trace level, return immediately
	if(theHelper.m_nLevel==0||nLevel>theHelper.m_nLevel) return;
	// set lock
	theHelper.Lock();
	try
	{
		// get local time
		SYSTEMTIME sysTime;
		::GetLocalTime(&sysTime);
		// get trace file handle	
		HANDLE hFile = theHelper.m_hFile;
		// open the trace file if not already open
		if(hFile==NULL) hFile = theHelper.OpenTraceFile();
		// if it is already a new day, close the old
		// trace file and open a new one
		else if
		(
			sysTime.wYear!=theHelper.m_timeStart.wYear||
			sysTime.wMonth!=theHelper.m_timeStart.wMonth||
			sysTime.wDay!=theHelper.m_timeStart.wDay)
		{
			theHelper.CloseTraceFile();
			theHelper.OpenTraceFile();
		}
		// write the trace message
		if(hFile)
		{
			// declare buffer (default max buffer size = 32k)
			const int nMaxSize = 32*1024;
			TCHAR pBuffer[nMaxSize+51];
			// print time stamp and thread id to buffer
			int nPos = _stprintf
			(
				pBuffer,
				_T("%02d:%02d:%02d_%03d_%X: "), 
				sysTime.wHour,
				sysTime.wMinute,
				sysTime.wSecond,
				sysTime.wMilliseconds,
				theHelper.m_nThreadId
			);
			// print the trace message to buffer
			va_list args;
			va_start(args, strFormat);
			nPos += _vsntprintf(pBuffer+nPos,nMaxSize,strFormat,args);
			va_end(args);
			// print the end of the line to buffer
			_stprintf(pBuffer+nPos,_T("\r\n"));
			// write the buffer to the trace file
			DWORD dwBytes;
			::WriteFile(hFile,pBuffer,_tcslen(pBuffer),&dwBytes,NULL);
		}
	}
	catch(...)
	{
		// add code to handle exception (if needed)
	}
	// release lock
	theHelper.Unlock();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -