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

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