您的位置:首页 > 编程语言 > C语言/C++

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

2015-04-13 01:28 162 查看
这个作为大多数人诟病的东西,调用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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息