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

📄 workthread.cpp

📁 在linux下基于UDP通讯的程序,包括客户端与服务端.
💻 CPP
字号:
//WorkThread.cpp 线程的实现文件
//author:duanjigang
//desp:实现线程的功能函数
#include "CommHead.h"
#include <string>
using namespace std;
#include "WorkThread.h"
#include "LogHelper.h"
extern CLogHelper theLogger;
//工作线程的函数体
#ifdef __LINUX__
void* 
#else
DWORD WINAPI
#endif
WorkThread(
#ifdef _WIN32
LPVOID
#else
void*
#endif
data);
//构造函数初始化相关变量
CWorkThread::CWorkThread()
{
  m_pTask = NULL; //开始时任务为空
  m_bShouldExit = false;//一开始肯定有用,所以无用标志位设置为false
  InitLock(&m_Lock);//初始化线程资源锁
  m_bFree = true; //设置空闲标志位
  m_nID = -1;

}

CWorkThread::~CWorkThread()
{

}
//供外部对象调用,传递的参数实际上是一个CWorkThread对象的地址
int CWorkThread::Start(void* data)
{
	string strError = "创建工作线程失败[CWorkThread::Start(void* data)]";
#ifdef _WIN32
	DWORD dwThreadID;
	if(CreateThread(NULL, 0, WorkThread, data, 0, &dwThreadID) == NULL)
	{
		theLogger.LogMessage(strError, true);
		return 0;
	}
#else
	pthread_t thread;
	if(pthread_create(&thread, NULL, WorkThread, data))
	{
		theLogger.LogMessage(strError, true);
		return 0;
	} 
	if(pthread_detach(thread))
	{
		return 0;
	}
#endif
	//strError = "工作线程:" + string(GetName()) + " 启动成功!";
	//theLogger.LogMessage(strError, true);
    return 1;
}
//工作线程函数体
#ifdef __LINUX__
void* 
#else
DWORD WINAPI
#endif
WorkThread(
#ifdef _WIN32
LPVOID
#else
void*
#endif
data)
{
	//因为传递进来的是一个线程对象的地址,所以我们要将它转化成
	//指向线程对象的指针,这样才能调用线程的功能函数
	CWorkThread* thread = (CWorkThread*)data;
	if(!thread)
	{
		string str = "消息处理线程中无效的参数[WorkThread]";
		theLogger.LogMessage(str, true);
	    return 0;
	}

	string str = string(thread->GetName()) + "启动[WorkThread]";
	theLogger.LogMessage(str, true);
 	//循环检测,如果线程需要退出,则退出,否则执行run函数
	while(1)
	{
		//使用这个接口,调度线程就能实现对
		//工作线程的动态管理了,如果任务比较多
		//则可以实时添加工作线程,如果空闲线程比较多,则可以动态的
		//结束一些线程,也就是通过修改线程结束标志位的方法来实现
		//每当执行完一个任务线程便会检测这个结束标志位,如果被设置了,则会
		//退出,否则就继续执行
		if(thread->ShouldExit())
		{
			string str = string(thread->GetName()) + "退出[WorkThread]";
			theLogger.LogMessage(str, true);
			return 0; 
		}
		//执行任务
		thread->Run();
		//thread->SetExitFlag();
	}
   return 0;
}
//获取线程的名字,目前的做法是根据线程的ID构造
//比如线程ID为1的话,名字为 Thread_001,线程123的
//名字为Thread_123,只是为了打印格式上的好看,也可以根据
//线程名字生成专门的日志文件,为每个线程存储日志
char* CWorkThread::GetName()
{ 
	static char szRet[128];
	memset(szRet, 0, 128);
	LockOn(&m_Lock);
	sprintf(szRet, "%s", m_szName);
	LockOff(&m_Lock);
	return szRet;
}
//设置线程的ID,这个通过外部的函数来调用,所以设计为public类型
void CWorkThread::SetID(int nID)
{
    memset(m_szName, 0, sizeof(m_szName));
	sprintf(m_szName, "线程%03d", nID);
	m_nID = nID;
}
//检测线程是否空闲,主要是调度线程来调用的
//因为它要为工作线程分配任务或者结束工作线程
//而且结束和分配任务都是在线程空闲的时候来进行的
//所以需要有一个函数能提供对线程状态的查询
bool CWorkThread::IsFree() 
{
	bool bRet = false;
	LockOn(&m_Lock);
	bRet =  m_bFree;
	LockOff(&m_Lock);
	return bRet;
}  
//线程运行函数,如果任务参数为空则直接退出
//否则执行任务对象直到结束
int CWorkThread::Run()
{
	string str;
	str = string(GetName()) + " 开始执行[CWorkThread::Run()]";
	theLogger.LogMessage(str, true);
	
	while(NULL == m_pTask)
	{
		string str  = string(GetName()) + ": 参数为空[CWorkThread::Run()]";
		SLEEP(5, 0);
		theLogger.LogMessage(str, true);
	}
	//开始执行,直到结束条件满足
	while(!m_pTask->MayEnd())
	{
		m_pTask->Execute();
	} 
	//然后要修改线程的标志位,告诉外界它已经空闲了,以方便新的任务的分配
	LockOn(&m_Lock);
	m_bFree = true;
	LockOff(&m_Lock);
	m_pTask = NULL;
	
	return 1;
}
//给线程分配任务,以继续线程的执行,这个函数是通过外界来调用的
bool CWorkThread::AssigTask(CTask *pTask)
{
	if(NULL == pTask)
	{
		return false;
	}
    //修改锁和任务对象变量
	LockOn(&m_Lock);
	m_pTask = pTask;
	m_bFree = false;
	LockOff(&m_Lock);
	return true;
}
//改变线程状态,如果为false则说明线程繁忙,如果为true则说明线程空闲
//主要是调度线程调用的,因为调度线程需要找到一个任务然后找出来一个空闲
//线程,然后把任务分配个这个空闲线程去执行
void CWorkThread::ChangeStatus(bool bNewStatus)
{
	LockOn(&m_Lock);
	m_bFree = bNewStatus;
	LockOff(&m_Lock);
}
//这个是自身调用的,用在结束线程时使用
//如果这个线程需要结束则会直接退出
bool CWorkThread::ShouldExit()
{
	bool bRet = false;
	LockOn(&m_Lock);
	bRet = m_bShouldExit;
	LockOff(&m_Lock);
	return bRet;
}
//获取线程的ID值,这几个关于线程ID的函数还有待商榷,确定是否要
//留下来
int CWorkThread::GetID()
{
	int nRet = 0;
	LockOn(&m_Lock);
    nRet =  m_nID;
	LockOff(&m_Lock);
	return nRet;
}
//设置退出标志位
void CWorkThread::SetExitFlag()
{
  	LockOn(&m_Lock);
	m_bShouldExit = true;
	LockOff(&m_Lock);
}

⌨️ 快捷键说明

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