Windows下的一个C++多线程库

这个作为大多数人诟病的东西,调用Win32 API复杂,调用开源库pthread、boost::thread竟然没有暂停,还得加锁实现,比较麻烦。还有就是网上的代码,给出了是给出了,但竟然不说说如何使用,看得我蛋疼。于是我就封装了一个库,觉得网上的库麻烦可以试试我这个,通过临界区加锁。如果同学们遇到什么问题可以提出来。

hThread.h

#ifndef _H_THREAD_H_
#define _H_THREAD_H_

#pragma once

#include <Windows.h>

#define hThread_Enter(o) ::EnterCriticalSection (&(o)->cs)
#define hThread_Leave(o) ::LeaveCriticalSection (&(o)->cs)

typedef void (*pFunc)();

class hThread {
	volatile bool isPause;
	bool isNew;
protected:
	HANDLE h_hThread;
	DWORD h_dwID;
	virtual void Thread () = 0;
	void _initCritical ();
	void _releCritical ();
public:
	void updateCritical ();
	 volatile bool nearStop;
	CRITICAL_SECTION cs;
	hThread ();
	~hThread ();
	bool Start (bool bEnter);
	bool Stop (bool bEnter);
	bool Pause (bool bEnter);
	bool IsPause (bool bEnter);
	bool IsExist (bool bEnter);
	static DWORD WINAPI _thread (hThread* o);
};

#endif //_H_THREAD_H_

hThread.cpp

#include "hThread.h"

#define _hThread_Enter(cs) if (!bEnter) ::EnterCriticalSection (cs)
#define _hThread_Leave(cs) if (!bEnter) ::LeaveCriticalSection (cs)

void hThread::_initCritical () {
	RtlZeroMemory (&this->cs, sizeof (CRITICAL_SECTION));
	::InitializeCriticalSection (&this->cs);
}

void hThread::_releCritical () {
	::DeleteCriticalSection (&this->cs);
}

void hThread::updateCritical () {
	this->_releCritical ();
	this->_initCritical ();
}

hThread::hThread () {
	this->_initCritical ();
	this->nearStop = this->isPause = this->isNew = false;
	this->h_hThread = NULL;
	this->h_dwID = 0;
}

hThread::~hThread () {
	this->Stop (false);
	this->_releCritical ();
}

bool hThread::Start (bool bEnter) {
	bool bRet;
	_hThread_Enter (&this->cs);
	if (this->isPause) {
		bRet = -1 == ::ResumeThread (this->h_hThread);
	} else {
		this->nearStop = false;
		if (this->isNew) {
			this->updateCritical ();
		} else {
			this->isNew = true;
		}
		bRet = !(this->h_hThread = ::CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) hThread::_thread, this, 0, &this->h_dwID));
	}
	this->isPause = false;
	_hThread_Leave (&this->cs);
	return bRet;
}

bool hThread::Stop (bool bEnter) {
	if (this->nearStop) ::WaitForSingleObject (this->h_hThread, 100);
	_hThread_Enter (&this->cs);
	if (this->IsExist(true)) {
		::TerminateThread (this->h_hThread, 0);
		::CloseHandle (this->h_hThread);
		this->h_hThread = NULL;
	}
	_hThread_Leave (&this->cs);
	return true;
}

bool hThread::Pause (bool bEnter) {
	if (this->nearStop) ::WaitForSingleObject (this->h_hThread, 100);
	_hThread_Enter (&this->cs);
	if (this->IsExist(true)) {
		::SuspendThread (this->h_hThread);
		this->isPause = true;
	}
	_hThread_Leave (&this->cs);
	return this->isPause;
}

bool hThread::IsPause (bool bEnter) {
	return this->IsExist (bEnter) && this->isPause;
}

bool hThread::IsExist (bool bEnter) {
	_hThread_Enter (&this->cs);
	bool bRet = false;
	DWORD dwExit = 0;
	if (this->h_hThread && this->h_hThread != INVALID_HANDLE_VALUE && ::GetExitCodeThread (this->h_hThread, &dwExit)) {
		bRet = (STILL_ACTIVE == dwExit);
	}
	_hThread_Leave (&this->cs);
	return bRet;
}

DWORD WINAPI hThread::_thread (hThread* o) {
	o->nearStop = o->isPause = false;
	o->Thread ();
	hThread_Enter (o);
	::CloseHandle (o->h_hThread);
	o->h_hThread = NULL;
	hThread_Leave (o);
	return 0;
}

两个文件。使用方法:

1、引用hThread.h,不解释

2、创建一个类,继承至hThread,并实现virtual void Thread方法

class testThread : public hThread {
public:
	testThread () { }
	~testThread () { }
	virtual void Thread () {
		hThread_Enter (this);
		//...
		hThread_Leave (this);
	}
};

这里说明一下, hThread_Enter (this); 和 hThread_Leave (this); 之间的代码为临界区内部代码,如果不想在这段代码内部Pause的话。

还有就是线程内部多个临界区之间最好加一个Sleep(10),方便外部暂停线程。

3、实例化

testThread t = new testThread();

4、接下来就是创建线程。

t->Start(true);
5、然后就自由了,各种Start、Pause、Stop随便用。

可能有同学会疑问为何调用Start、Pause、Stop都要传一个参数,我在这儿简要说明下,参数的意思代表是否已经进入临界区。假如已经进入临界区了就传true,否则传false。由于线程内部为了安全,用了非常多的临界区加锁,于是设置了这个参数,用于优化代码效率吧。另外,这个参数非常重要,假如进入临界区后不能传false,否则卡死!原因自行分析。

另外,有两个问题需要同学们注意,一个是创建线程以及暂停线程后的恢复均为Start函数实现,另一个是假如一个线程结束后再次创建一个线程,传入的Start参数必须为true

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章