Thread类

2013年6月15日 由 Creater 留言 »

Thread 类是一个基类,自定义线程都需要派生自该基类,并且重写Run这个纯虚函数。该类其中有4个数据成员

	bool m_running;
	bool m_release;
	bool m_b_delete_on_exit;
	bool m_b_destructor;

m_running标记线程是否在运行(构造函数初始化为true),如果创建线程失败则更改状态为false,析构函数也会更改为false。
m_release标记是否释放了线程的控制,如果已经释放则线程函数可以运行,否则线程函数需要等待控制被释放。
m_b_delete_on_exit标记在线程函数执行完毕退出时是否释放该线程资源,如果不释放则该线程还可以重新运行。
m_b_destructor标记该线程对象是否已经被析构。

由于pthread_create参数中的线程函数,必须在编译阶段就已经能够确定地址,所以不能是类的非static成员函数。故使用了静态函数StartThread。该函数中会检测是否已经释放了控制权(如果已经释放控制权则线程可以进入真正的线程运行函数),在线程函数执行完毕后会进行状态更新与是否进行资源释放检测。另外StartThread中还有一个比较重要的地方就是参数:

将对象的指针做为参数传入则可以对虚函数Run实现多态调用.

#ifndef _SOCKETS_Thread_H
#define _SOCKETS_Thread_H

#include "sockets-config.h"
#ifdef _WIN32
#else
#include <pthread.h>
#endif
#include "Semaphore.h"

#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif

#ifdef _WIN32
// to be
//typedef DWORD  threadfunc_t;
//typedef LPVOID threadparam_t;
//#define STDPREFIX WINAPI
typedef unsigned threadfunc_t;
typedef void * threadparam_t;
#define STDPREFIX __stdcall
#else

typedef void * threadfunc_t;
typedef void * threadparam_t;
#define STDPREFIX
#endif


class Thread
{
public:
	Thread(bool release = true);
	virtual ~Thread();

	static threadfunc_t STDPREFIX StartThread(threadparam_t);

	virtual void Run() = 0;

#ifdef _WIN32
	HANDLE GetThread() { return m_thread; }
	unsigned GetThreadId() { return m_dwThreadId; }
#else
	pthread_t GetThread() { return m_thread; }
#endif

	bool IsRunning();
	void SetRunning(bool x);
	bool IsReleased();
	void SetRelease(bool x);
	bool DeleteOnExit();
	void SetDeleteOnExit(bool x = true);
	bool IsDestructor();

	void Start() {
		SetRelease(true);
	}

	void Stop() {
		Start();
		SetRunning(false);
	}

	void Wait();

protected:
#ifdef _WIN32
	HANDLE m_thread;
	unsigned m_dwThreadId;
#else
	pthread_t m_thread;
	pthread_attr_t m_attr;
#endif

private:
	Thread(const Thread& ) {}
	Thread& operator=(const Thread& ) { return *this; }
	Semaphore m_sem;
	bool m_running;
	bool m_release;
	bool m_b_delete_on_exit;
	bool m_b_destructor;
};


#ifdef SOCKETS_NAMESPACE
}
#endif

#endif // _SOCKETS_Thread_H

#include <stdio.h>
#ifdef _WIN32
#include <process.h>
#include "socket_include.h"
#else
#include <unistd.h>
#endif

#include "Thread.h"
#include "Utility.h"


#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif


Thread::Thread(bool release)
:m_thread(0)
,m_running(true)
,m_release(false)
,m_b_delete_on_exit(false)
,m_b_destructor(false)
{
#ifdef _WIN32
//	m_thread = ::CreateThread(NULL, 0, StartThread, this, 0, &m_dwThreadId);
	m_thread = (HANDLE)_beginthreadex(NULL, 0, &StartThread, this, 0, &m_dwThreadId);
#else
	pthread_attr_init(&m_attr);
	//设置为detache属性,则该线程退出时自己释放资源而不是创建线程来释放。
	pthread_attr_setdetachstate(&m_attr,PTHREAD_CREATE_DETACHED);
	//由于pthread_create的线程函数参数不能为内的非静态成员函数,所以定义了StartThread。
	if (pthread_create(&m_thread,&m_attr, StartThread,this) == -1)
	{
		perror("Thread: create failed");
		//设置线程未运行
		SetRunning(false);
	}
#endif
	//设置线程是否释放控制权
	m_release = release;
	//释放控制权
	if (release)
		m_sem.Post();
}


Thread::~Thread()
{
	m_b_destructor = true;
	if (m_running)
	{
		SetRelease(true);
		SetRunning(false);
		/*
			Sleep one second to give thread class Run method enough time to
			release from run loop
		*/
		Utility::Sleep(1000);
	}
#ifdef _WIN32
	if (m_thread)
		::CloseHandle(m_thread);
#else
	pthread_attr_destroy(&m_attr);
#endif
}


threadfunc_t STDPREFIX Thread::StartThread(threadparam_t zz)
{
	/*
		Sleep here to wait for derived thread class constructor to setup
		vtable... hurts just looking at it
	*/
	Utility::Sleep(5);

	Thread *p = (Thread *)zz;

	p -> Wait();
	if (p -> m_running)
	{
		p -> Run();
	}
	//已经停止运行
	p -> SetRunning(false); // if return
	if (p -> DeleteOnExit() && !p -> IsDestructor())
	{
		delete p;
	}
#ifdef _WIN32
	_endthreadex(0);
#endif
	return (threadfunc_t)NULL;
}


bool Thread::IsRunning()
{
 	return m_running;
}


void Thread::SetRunning(bool x)
{
 	m_running = x;
}


bool Thread::IsReleased()
{
 	return m_release;
}


void Thread::SetRelease(bool x)
{
 	m_release = x;
 	if (x)
 		m_sem.Post();
}


bool Thread::DeleteOnExit()
{
	return m_b_delete_on_exit;
}


void Thread::SetDeleteOnExit(bool x)
{
	m_b_delete_on_exit = x;
}


bool Thread::IsDestructor()
{
	return m_b_destructor;
}


void Thread::Wait()
{
	m_sem.Wait();
}


#ifdef SOCKETS_NAMESPACE
}
#endif
广告位

发表评论

你必须 登陆 方可发表评论.