c语言 线程封装,C语言封装线程与日志类

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

6b8d8ec9729449ca88528bfce19d6c2a.png

WriLog.h

#pragma once

#include

#include

#ifdef WRILOGDLL

#define WRILOGAPI __declspec(dllexport)

#else

#define WRILOGAPI __declspec(dllimport)

#endif

//日志工具包

#define MAX_MSG_TEXT1024*10

#define MAX_MSG_TITLE1024

//日志消息结构体

struct LogMessage

{

char msgText[MAX_MSG_TEXT];//日志消息信息

char msgType[256];//消息类型

int level;//消息级别

};

//消息队列,使用到了stl的队列

class CLogQueue

{

private:

std::queue 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:

BOOLm_terminated;//是否终止

BOOLm_finished;//是否结束

BOOLm_running;//是否运行

public:

CMyThread(void);

~CMyThread(void);

enum ThreadState

{

Runing=0x00, //运行状态

Finished=0x01, //完成

};

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

//获取线程状态

ThreadStateGetThreadState();

//线程操作

BOOLStart();

BOOLSuspend();

BOOLResume();

voidStop();

voidTerminate();//结束线程

};

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;

}

工程在我的资源里面。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值