C语言封装线程与日志类

折腾了两天,查半天资料还是不如自己动动手。如题这是两个很常见的问题,虽然很多语言都封装了线程,但是让自己写一个还是比较麻烦的,这儿做一个简单的demo,大家可以去完善。

WriLog.h

#pragma once

#include <queue>
#include <time.h>

#ifdef WRILOGDLL
#define WRILOGAPI __declspec(dllexport)
#else
#define WRILOGAPI __declspec(dllimport)
#endif

//日志工具包
#define MAX_MSG_TEXT	1024*10
#define MAX_MSG_TITLE	1024

//日志消息结构体
struct LogMessage
{
	char msgText[MAX_MSG_TEXT];	//日志消息信息
	char msgType[256];		//消息类型
	int level;			//消息级别
};

//消息队列,使用到了stl的队列
class CLogQueue
{
private:
	std::queue<LogMessage *> m_queue;
	CRITICAL_SECTION cs;
public:
	CLogQueue();
	~CLogQueue();

	void Lock();
    void UnLock();
	LogMessage *pop();
	void push(LogMessage *new_value);
	BOOL empty() const;
	int  size();
};

//简单的线程类 有时间再完整的封装这个类
class WRILOGAPI CMyThread
{
public:
	HANDLE hThread;	
	DWORD threadID;

public:
	BOOL	m_terminated;	//是否终止
	BOOL	m_finished;	//是否结束
	BOOL	m_running;	//是否运行

public:
	CMyThread(void);
	~CMyThread(void);

	 enum ThreadState
	 {
		 Runing		=	0x00, //运行状态
		 Finished	=	0x01, //完成
	 };

	 virtual void Execute(void)=0;	//线程不能实例化,必须要继承实现该函数

	//获取线程状态
	ThreadState	GetThreadState();

	//线程操作
	BOOL	Start();
	BOOL	Suspend();
    	BOOL	Resume();
	void	Stop();

	void	Terminate();	//结束线程
};

class WRILOGAPI CWriteLog: public CMyThread
{
private:
	char m_filePath[256];	//路径
	char m_fileName[256];	//文件名
	int	 m_level;	//日志级别,这个一般从配置里面读取

	char m_curDate[256];	//当前日期
public:
	CWriteLog(const char *pLogName, const char *path);
	~CWriteLog(void);

	enum LogLevel{
		Error	=	0x00,	//错误 级别最高,默认输出
		Warning =	0x01,	//警告
		Hint	=	0x02,	//提示
		Normal	=	0x03,	//一般
		Debug	=	0x04,	//调试
	};

	CLogQueue m_logList;

	void SetLevel(int level=0);
	void AddLog(const char *msgText, const char *msgType, int level = 0);
	void WriteLog(LogMessage *msg);

	void Execute(void); 
};

//线程函数
DWORD WINAPI ThreadProc(void *pMyThread);
//这儿可以再封装一个函数,客户端不用手动实例化日志类,直接调用这个函数写日志
//extern "C" void WRILOGAPI WriteLog(const char *str, int level = 0);


简单的头文件大概就是这样,实现部分如下:

LogUtil.cpp

#include "StdAfx.h"
#include "WriLog.h"

///CLogQueue//

CLogQueue::CLogQueue()
{
	InitializeCriticalSection(&cs);
}

CLogQueue::~CLogQueue()
{
	DeleteCriticalSection(&cs);
}

void CLogQueue::Lock()
{
	EnterCriticalSection(&cs);
}

void CLogQueue::UnLock()
{
	LeaveCriticalSection(&cs);
}

LogMessage *CLogQueue::pop()
{
	LogMessage *res = NULL;
	if(!m_queue.empty())
	{
		Lock();
		res=m_queue.front();
		m_queue.pop();
		UnLock();
	}
	return res;
}

void CLogQueue::push(LogMessage *new_value)
{
	Lock();
	m_queue.push(new_value);
	UnLock();
}

BOOL CLogQueue::empty() const
{
	return m_queue.empty();
}

int  CLogQueue::size()
{
	return m_queue.size();
}


/CMyThread///

CMyThread::CMyThread(void)
{
	m_terminated = false;
	m_finished = false;
	m_running = false;
	hThread = ::CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)ThreadProc, this, 0, &threadID); 
}

CMyThread::~CMyThread(void)
{
}

void CMyThread::Terminate()
{
	m_terminated = true;
}

DWORD WINAPI ThreadProc(void *pMyThread)
{
	CMyThread *thread = (CMyThread *)pMyThread;
	
	//判断是否终止
	if(!thread->m_terminated)
	{
		thread->Execute();
	}

	//线程执行完毕后这儿需要根据设置来判断是否进行清理工作,对于线程类来说,线程执行完了类也就可以释放了,这个随你喜欢

	return 0;
}


WriLog.cpp

// WriLog.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include "direct.h"
#include "WriLog.h"

CWriteLog::CWriteLog(const char *pLogName, const char *path)
{ 
	memset(m_filePath, 0, 256);
	memset(m_fileName, 0, 256);
	memset(m_curDate, 0, 256);
	m_level = 0;

	if(pLogName)
		strncpy(m_fileName, pLogName, strlen(pLogName));
	if(path)
		strncpy(m_filePath, path, strlen(path));

	time_t timep;  
    	struct tm *p;  
    	time(&timep);  
    	p =localtime(&timep); 
	strftime(m_curDate, 256, "%Y-%m-%d", p);  
}


CWriteLog::~CWriteLog(void)
{
	while(m_logList.size()>0)
	{
		LogMessage *msg;
		msg = m_logList.pop();
		delete msg;
	}
}

void CWriteLog::SetLevel(int level)
{
	m_level = level;
}

void CWriteLog::AddLog(const char *msgText, const char *msgType, int level)
{
	LogMessage *msg;
	msg = new LogMessage();
	memset(msg, 0, sizeof(LogMessage));
	if(msgText && strlen(msgText)>0)
		strncpy(msg->msgText, msgText, strlen(msgText));
	else{
		delete msg;
		return;
	}
	if(msgType && strlen(msgType)>0)
		strncpy(msg->msgType, msgType, strlen(msgType));
	msg->level = level;

	m_logList.push(msg);
}

void CWriteLog::WriteLog(LogMessage *msg)
{
	if(NULL == msg)
		return;

	//如果当前日志级别比配置的大,则不写入
	if(msg->level > m_level)
		return;

	char fullPath[MAX_MSG_TITLE];	//完整路径 D:\test\filename_error_2016-5-11.log
	memset(fullPath, 0, MAX_MSG_TITLE);
	if(strcmp(msg->msgType, "")>0){
		strcat(fullPath, m_filePath);
		strcat(fullPath, "\\");
		strcat(fullPath, m_fileName);
		strcat(fullPath, "_");
		strcat(fullPath, msg->msgType);
		strcat(fullPath, "_");
		strcat(fullPath, m_curDate);
		strcat(fullPath, ".log");
	}
	else{
		strcat(fullPath, m_filePath);
		strcat(fullPath, "\\");
		strcat(fullPath, m_fileName);
		strcat(fullPath, "_");
		strcat(fullPath, m_curDate);
		strcat(fullPath, ".log");
	}

	char title[256];
	memset(title, 0, 256);
	time_t timep;  
    struct tm *p;  
    time(&timep);  
    p =localtime(&timep); 
	strftime(title, 256, "%X.", p);  

	FILE *pFile;
	if(pFile = fopen(fullPath, "a+"))
	{

		fputs(title, pFile);			//写入标题,这儿仅写入时间
		fprintf(pFile,"%d:", threadID);		//写入线程ID
		fputs(msg->msgText, pFile);		//写入消息
		fprintf(pFile,"\n");			//换行

		fclose(pFile); 
	}
}

void CWriteLog::Execute(void)
{
	LogMessage *msg;
	msg = m_logList.pop();
	while(!m_terminated)
	{
		if(NULL != msg)
		{
			WriteLog(msg);
			delete msg;
		}
		//这儿应该用事件处理waitforsingle..,避免浪费cpu
		Sleep(10);
		msg = m_logList.pop();
	}
}


一个简单的封装就完成了,下面是demo:

CWriteLog *m_pLog;
 m_pLog = new CWriteLog("监控日志", "c:\\test\\log");
 m_pLog->SetLevel(5);

这样就可以调用了

m_pLog->AddLog("测试。。", "Debug", CWriteLog::Debug);

最后是释放:

if(m_pLog)
 {
  //如果线程执行较复杂的程序,这儿有可能不能马上关掉线程,
  //此时删除实例可能会卡死或报错,最好的办法是使用事件来监听
  //一旦调用terminate函数则立即退出线程
  m_pLog->Terminate();
  delete m_pLog;
 }


工程在我的资源里面。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

六个沃德

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值