您的位置:首页 > 其它

一个人的战争(2) : 成员函数与线程

2006-09-06 18:03 295 查看
本来今天打算贴BT Client的Tracker Requester的代码的,可是整理的不太完善,因为里面牵扯到很多线程和IOCP的东西,所以我先把一部分自己封装的线程代码贴上来供各位读者评论

先看下我对Win32线程的最浅封装,

注意这个是声明在thrad/win32/data_type.h下的




struct ThreadHandle //这个控制线程的句柄,ID等,提供这么各类主要是为了跨平台的考虑(并不成熟)




...{


HANDLE m_hdl;


t_u_int32 m_tid;


bool m_is_suspend;


};




struct ThreadAttr //属性类




...{


t_u_int32 stack_size;


t_u_int32 priority;


t_u_int32 create_flags;


public:




ThreadAttr() : stack_size(0), priority(0), create_flags(0) ...{ }


};






typedef unsigned int (__stdcall *ThreadFun)(void *); //win32下的被调用的函数原型

下面这部分用了点Bridge模式,有点繁杂,不过是为了一个不成熟的跨平台考虑的




/**//****************************************************threadx_impl_base.h*******************************************/


#include "thread_def.h"


#include "../misc/non_copy_able.h"






namespace ThreadSpace ...{






enum ThreadPriority ...{ HIGH, NORMAL, LOW }; //优先级控制




struct ThreadImpl : private NonCopyable //各个平台要提供的线程控制的Impl_基类




...{


virtual ThreadHandle* get_handle() = 0;


virtual void terminate() = 0;


virtual bool suspend() = 0;


virtual bool resume() = 0;


virtual ThreadPriority get_priority() const = 0;


virtual bool set_priority(ThreadPriority tp) = 0;


virtual bool is_active() const = 0;


//virtual t_u_long wait_for_end(t_u_long timeout) = 0;




virtual ~ThreadImpl()...{ };


};




}






/**//*****************************************************threadx.h*****************************************************************/






#include "thread_def.h"


#include "threadx_impl_base.h"






namespace ThreadSpace ...{










class ThreadX : private NonCopyable




...{


private:


ThreadImpl *m_pimpl;


public:


ThreadHandle* get_handle();


void terminate();


ThreadX(ThreadImpl *pimpl);


bool suspend();


bool resume();


ThreadPriority get_priority() const;


bool set_priority(ThreadPriority tp);


bool is_active() const;


//t_u_long wait_for_end(t_u_long timeout = INFINITE);


virtual ~ThreadX();




};








}








/**//**********************************************************threadx.cpp*********************************************************************/




#include "threadx.h"










namespace ThreadSpace ...{








ThreadX::ThreadX(ThreadImpl *pimpl) : m_pimpl(pimpl) ...{ }




bool ThreadX::suspend()




...{


return m_pimpl->suspend();


}




bool ThreadX::resume()




...{


return m_pimpl->resume();


}




void ThreadX::terminate()




...{


m_pimpl->terminate();


}




ThreadPriority ThreadX::get_priority() const




...{


return m_pimpl->get_priority();


}




bool ThreadX::set_priority(ThreadPriority tp)




...{


return m_pimpl->set_priority(tp);


}






ThreadX::~ThreadX() ...{ delete m_pimpl; }






bool ThreadX::is_active() const




...{


return m_pimpl->is_active();


}






ThreadHandle* ThreadX::get_handle()




...{


return m_pimpl->get_handle();


}




}






/**//*******************************************************threadx_impl.h(在win32/)********************************************************/




#pragma once




#include "../threadx_impl_base.h"


#include "../thread_expt.h"






namespace ThreadSpace ...{








class Win32ThreadImpl : public ThreadImpl




...{


private:


ThreadHandle m_handle;


public:


Win32ThreadImpl(HANDLE hdl, t_u_long tid, bool is_suspend);


virtual ~Win32ThreadImpl();


public:


virtual ThreadHandle* get_handle();


virtual void terminate();


virtual bool suspend();


virtual bool resume();


virtual ThreadPriority get_priority() const;


virtual bool set_priority(ThreadPriority tp);


virtual bool is_active()const;


//virtual t_u_long wait_for_end(t_u_long timeout);


};










}






/**//************************************************************threadx_impl.cpp(win32/)*****************************************************/






#include "threadx_impl.h"






namespace ThreadSpace ...{






Win32ThreadImpl::Win32ThreadImpl(HANDLE hdl, t_u_long tid, bool is_suspend) //: m_hdl(hdl),


m_tid(tid),


m_is_suspend(is_suspend)




...{


m_handle.m_hdl = hdl;


m_handle.m_tid = tid;


m_handle.m_is_suspend = is_suspend;




}




Win32ThreadImpl::~Win32ThreadImpl()




...{


::CloseHandle(m_handle.m_hdl);


}




bool Win32ThreadImpl::is_active()const




...{


t_u_long code;


if(::GetExitCodeThread(m_handle.m_hdl, &code) == 0) throw ThreadExpt(::GetLastError());




return (code == STILL_ACTIVE);


}






void Win32ThreadImpl::terminate()




...{


::TerminateThread(m_handle.m_hdl, -1);


}






bool Win32ThreadImpl::suspend()




...{


if(m_handle.m_is_suspend) return true;






if(::SuspendThread(m_handle.m_hdl) == -1)...{


return false;




}else ...{


m_handle.m_is_suspend = true;


return true;


}


}




bool Win32ThreadImpl::resume()




...{


if(!m_handle.m_is_suspend) return true;






if(::ResumeThread(m_handle.m_hdl) == -1)...{


return false;




}else...{


m_handle.m_is_suspend = false;


return true;


}


}




ThreadPriority Win32ThreadImpl::get_priority() const




...{


int res = ::GetThreadPriority(m_handle.m_hdl);


if(res == THREAD_PRIORITY_ERROR_RETURN) throw ThreadExpt(::GetLastError());






switch(res)...{


case THREAD_PRIORITY_TIME_CRITICAL:


case THREAD_PRIORITY_HIGHEST:


return HIGH;


case THREAD_PRIORITY_ABOVE_NORMAL:


case THREAD_PRIORITY_NORMAL:


case THREAD_PRIORITY_BELOW_NORMAL:


return NORMAL;


default:


return LOW; //case THREAD_PRIORITY_LOWEST:


//case THREAD_PRIORITY_IDLE:


}


}




bool Win32ThreadImpl::set_priority(ThreadPriority tp)




...{




switch(tp)...{


case HIGH:


return (::SetThreadPriority(m_handle.m_hdl, THREAD_PRIORITY_HIGHEST) != 0);


case LOW:


return (::SetThreadPriority(m_handle.m_hdl, THREAD_PRIORITY_LOWEST) != 0);


default:


return (::SetThreadPriority(m_handle.m_hdl, THREAD_PRIORITY_NORMAL) != 0);


}


}








/**//*t_u_long Win32ThreadImpl::wait_for_end(t_u_long timeout)


{


return ::WaitForSingleObject(m_handle.m_hdl, timeout);


}*/






ThreadHandle* Win32ThreadImpl::get_handle()




...{


return &m_handle;


}














}







以上是大概齐的框架,下面请看如何启动一个线程




/**//***************************************************************aux_fun.h*******************************************************/


#pragma once




#include "thread_def.h"








namespace ThreadSpace ...{






class ThreadX;




ThreadX* create_thread(ThreadFun proc, void *param, const ThreadAttr &attr); //创建一个线程(在各文件夹下有不同的实现)




void free_thread(ThreadX *&pthread);//delete ThreadX*... 同上




t_u_long wait_thread(ThreadX *pthread, t_u_long timeout = INFINITE); //等待一个线程结束




t_u_long wait_multi_thread(ThreadX **ppthread, size_t count, bool wait_all = true, t_u_long timeout ); 等待所有一组结束






}








/**//**************************************************axu_fun.cpp (win32/)************************************************/




#include "../aux_fun.h"


#include "../threadx.h"


#include "threadx_impl.h"






#include <vector>


#include <cassert>




namespace ThreadSpace ...{










ThreadX* create_thread(ThreadFun proc, void *param, const ThreadAttr &attr)




...{


t_u_int32 tid;


HANDLE hdl = (HANDLE)_beginthreadex(0, attr.stack_size, proc, param, attr.create_flags, &tid);


if(hdl == 0) throw(ThreadExpt(errno));




return new ThreadX(new Win32ThreadImpl(hdl, tid, (attr.create_flags == CREATE_SUSPENDED)));




}






void free_thread(ThreadX *&pthread)




...{


assert(pthread != 0);




try...{


delete pthread;


pthread = 0;




}catch(...)




...{




}


}








t_u_long wait_thread(ThreadX *pthread, t_u_long timeout)




...{


assert(pthread != 0);


t_u_long res = ::WaitForSingleObject(pthread->get_handle()->m_hdl, timeout);


if(res == WAIT_FAILED) throw (ThreadExpt(::GetLastError()));


return res;


}




t_u_long wait_multi_thread(ThreadX **ppthread, size_t count, bool wait_all, t_u_long timeout)




...{


assert(ppthread != 0);


std::vector<HANDLE> vhdl;


for(size_t i = 0; i < count; ++i)


vhdl.push_back(ppthread[i]->get_handle()->m_hdl);




t_u_long res = ::WaitForMultipleObjects(count, &vhdl[0], wait_all, timeout);




if(res == WAIT_FAILED) throw(ThreadExpt(::GetLastError()));




return res;








}





恩,下面是关键了,就是我们如何直接把一成员函数当做线程来执行平是我们的习惯是




class Test




...{


public:




void test() ...{ printf("xxxxxxxxx"); } //成员函数


static unsigned int WINAPI ThreadFun(void *pvoid)




...{


Test *ptest = static_cast<Test*>(pvoid);


ptest->test();


return 0;


}


};




int main()




...{


Test test;


HANDLE hdl = (HANDLE)_beginthreadex(0, 0, Test::ThreadFun, (void*)&test, 0, 0);




cin.get();


return 0;


}

如果我们希望直接启动这个成员函数呢?OK,下面有些复杂的模板定义,请注意,这些东西也许无意义,但很有意思


#pragma once




#include <memory>






namespace ThreadSpace ...{






template<class T, class MF, class P>


struct ThreadInfo




...{


T *ptype; //传递进来的那个类的指针;


MF mem_fun; //类成员函数指针


P *param; //参数指针;






ThreadInfo(T *pt, MF mf, P *pa) : ptype(pt), mem_fun(mf), param(pa) ...{ }


};








template<class ExecImpl>


class MemFunExector




...{


private:


typedef typename ExecImpl::HandleType HandleType; //见下面的ExecImpBase注释


typedef typename ExecImpl::Result Result;


typedef typename ExecImpl::Param Param;


private:


template<class C>//这个是那个被执行的线程函数,根据被实例化的不同的ThreadInfo模板来作实例化


static Result ThreadFunc(Param param)




...{


std::auto_ptr<C> p_info((C*)param);


//这样,根据调用一个函数指针来调用相应的成员函数


return ((p_info->ptype)->*(p_info->mem_fun))(*p_info->param);


}






public://首先这个模板函数接受一个类的指针,这个类的成员函数指针和成员函数参数


template<class Type, class MFun, class MParam>


HandleType operator()(Type *pt, MFun fun, MParam ¶m)




...{


//ThreadInfo<Type, MFun, MParam>相应的ThreadInfo实例化,这个类同样作为记录参数信息来用的


//ThreadFunc再根据上面的ThradInfo类作实例化


return ExecImpl()(ThreadFunc<ThreadInfo<Type, MFun, MParam> >, (Param)(new ThreadInfo<Type, MFun, MParam>(pt, fun, ¶m)));


}




template<class Type, class MFun, class MParam, class ATTR>


HandleType operator()(Type *pt, MFun fun, MParam ¶m, ATTR &attr)




...{


return ExecImpl(attr)(ThreadFunc<ThreadInfo<Type, MFun, MParam> >, (Param)(new ThreadInfo<Type, MFun, MParam>(pt, fun, ¶m)));


}


};






//这个类是为了提供不同平台的线程启动函数兼容的,每个平台都应该有一个不同的派生类


template<class H, class R, class P>


struct ExecImpBase




...{


typedef H HandleType; //注意,这个是启动那个成员函数返回的句柄,例如ThreadX*


typedef R Result; //这个是那个成员函数的返回值,类似unsigned int


typedef P Param; //那个成员函数的参数,类似void*p等,以后定义


typedef Result (*PF)(Param);




virtual HandleType operator()(PF pf, Param param) = 0;


};






}











根据平台定义相应的Traits类


#pragma once






#include "../mem_fun_exector.h"








namespace ThreadSpace ...{




class ThreadX;


struct ThreadAttr;




struct ExecutorWin32 : public ExecImpBase<ThreadX*, unsigned int, void*>




...{


const ThreadAttr &m_attr;




ExecutorWin32(const ThreadAttr &attr);




virtual HandleType operator()(PF pf, Param param);




};






#define MFExecutor(type, mfun, param, attr)


MemFunExector<ExecutorWin32>()((type), (mfun), (param), (attr))






}




class Test




...{


public:




void test(void *p) ...{ printf("xxxxxxxxx"); } //成员函数 注意,这个和上个不同,加了个void*p作为参数,是为了兼容那个模板




};




int main()




...{


Test test;


ThreadAttr attr;


void *p = 0;


MFExecutor(&test, Test::test, p, attr);


cin.get();


return 0;


}

OK,这部分就到此为止了,有什么错误请各位读者指教,有喜欢模板的朋友请加我QQ 2070341,明天我会贴IOCP的相关类或者Tracker requester类的代码,请各位看官支持,谢谢
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: