UTI.THREAD
我写的线程类, 用GP技术和OOP思想对OS的线程创建进行了封装, 使用起来灵活方便(后附example),力求简单实用。
这个线程类需要boost库的头文件支持, 但无需对boost库进行编译, 要知道编译boost库是一个漫长的过程... 而且boost库里面有很多我们平常用不上的一些“高级”玩意:-).
此外, 我还写了一系列使用灵活、方便,且在编程中经常需要使用的类(如同步锁, 线程池, 同步队列, 常用I/O对象, 常用算法等), 我其中的大部分放入了uti namespace之中, 所以称之为uti库。我尽量保持这些类的相对独立,一般只需要注释掉某行就可以单独使用。总之, 我写此类库所奉行的原则是 --- 稳定,灵活,简单(在example中应该可以看得到:-)).其他类库将出现在后续文章中, 希望大家喜欢, 也希望能和大家交流:-) stlflingfeitang@gmail.com
/*******************************************************************
created: 2008/06/05
created: 5:6:2008
Vision 0.8
file base: uti::thread
file ext: h
author: lingfei.tang
copyright(c) 2008.9
stlflingfeitang@gmail.com
欢迎使用本轻量级的线程类库---uti::thread
目前版本只支持Win32操作系统,且需要boost库的支持,
但只需引入头文件, 可免去编译boost的漫长等待过程
请注意boost::thread是需要编译才能使用的, 而且已经比较庞大复杂。
本线程库支持两种形式的函数签名:
1. 若是自由函数(全局函数):
RT func_name(PT param);
RT, PT 均已泛化. 即带一个参数的自由函数都满足条件
2. 若是成员函数:
RT memb_func_name(void);
父类, 和返回型别已经被泛化.
以上两种形式的函数其实已经可以满足大多数需求, 且形式简洁.
***你可以自由使用本库, 但请保留本说明和作者名及联系方式***
0.8版本已经过单元测试.
若有问题或建议请与我联系:-)stlflingfeitang@gmail.com
This code may be used in compiled form in any way you desire. This
file may be redistributed unmodified by any means PROVIDING it is
not sold for profit without the authors written consent, and
providing that this notice and the authors name and all copyright
notices remains intact.
An email letting me know how you are using it would be nice as well.
This file is provided "as is" with no expressed or implied
warranty.
The author accepts no liability for any damage/loss of business that
this product may cause.
*******************************************************************/
/*--------------------------使用说明-------------------------------
本线程类的使用时简单且灵活的:
1. 在线程对象的构造函数中传入你的线程函数指针, 以及相关参数
eg:
void freefunc(void*p){}//自由函数
uti::thread
thread_1(&freefunc, NULL);
class aclass{public:
threadfunc(){}};
aclass ainstan;//对象
uit::thread thread_2(&aclass::threadfunc,
&ainstan);
2. 调用start方法即可以启动线程
eg:
thread_1->start();
thread_2->start();
3. 调用join方法可以等待线程的退出,在线程对象析构时可以保证该线程的退出
eg:
thread_1->join();
thread_2->join();
另外,在后面还提供了两个用于继承复用的包装类, 继承复用可能时最简单的,但是耦合也是较高的:-)
eg:
class mythreadclass :public
ThreadObjBase
{
void Run
{
//...重写该线程函数
}
}
***需要特别说明的是:请确保你的线程函数是可以解栈的,否则利用该函数创建的线程将无法退出:(
------------------------------------------------------------------*/
/*modification record
08-08-29 by tlf :为了支持友元方式的访问, 将Thread_MemFun中的原对象的动态创建
移到父类thread 中创建.
*/
#if !defined(_UTI_THREAD__)
#define _UTI_THREAD__
//#include "utidef.h"//如果你想只使用本线程类, 请注释该行
#include <Windows.h>
#include <process.h>
#include <boost\function.hpp>
#include <boost\shared_ptr.hpp>
#include <vector>
#if !defined(_UTI_DEF__)
#define BEGIN_UTI
#define END_UTI
#else
#include <iostream>
#endif
BEGIN_UTI
class ThreadFunbase
{public: virtual
void run() =
0;};
template<typename
RT, typename CT>
class Thread_MemFun:
public ThreadFunbase
{
public:
typedef RT(CT::*FT)();
explicit Thread_MemFun( RT(CT::*f)(), CT *pcobj):m_fp(f), m_p(pcobj)
{}
virtual void run()
{
if (m_p)
(m_p->*m_fp)();
else
throw
std::logic_error("the thread function have no owner!");
}
private:
CT *m_p;
FT m_fp;
};
template<typename
RT, typename PT>
class Thread_Fun:
public ThreadFunbase
{
public:
explicit Thread_Fun(RT(*f)(PT), PT param){
m_funptor
= f;
m_param
= param;
}
virtual void run()
{
m_funptor(m_param);
}
private:
boost::function1<RT, PT> m_funptor;
PT m_param;
};
class thread
{
public:
template<typename RT, typename CT>
explicit thread(RT(CT::*f)(), CT *pcobj = NULL, std::string thread_name=
""):
m_thread_name(thread_name),m_id(0),
m_threadhandle(0), m_bisrunning(false), m_bisout(true)
{
CT *po = pcobj;
if (NULL == po)
{
get_static_obj_ptr(&po);
}
m_pfunptor.swap(boost::shared_ptr<ThreadFunbase>(new Thread_MemFun<RT, CT>(f, po)));
}
template<typename RT, typename PT>
explicit thread( RT(*f)(PT), PT param, std::string thread_name= ""):
m_thread_name(thread_name),m_id(0),
m_threadhandle(0), m_bisrunning(false)
{
m_pfunptor.swap(boost::shared_ptr<ThreadFunbase>(new Thread_Fun<RT,PT>(f, param)));
}
virtual ~thread()
{
join();
}
inline unsigned int getid() const
{
return m_id;
}
inline void start()
{
if (!m_bisrunning){
m_threadhandle
= reinterpret_cast<HANDLE>
(_beginthreadex(0,
0, threadfun, this,
0, &m_id));
m_bisout
= false;//we must
used it in two thread for sync
while(!m_bisrunning && !m_bisout){
//blocking to waiting thread running
#ifdef ___UTI_DEBUG
std::cout<<"###the
thread is waiting for start! "<< std::endl;
#endif
Sleep(2);
}
//Sleep(8);
}
}
inline bool IsRunning() const
{
return m_bisrunning;
}
inline void join()
{
if (m_threadhandle)
::WaitForSingleObject(m_threadhandle, INFINITE);
::CloseHandle(m_threadhandle);
m_threadhandle
= 0;
}
private:
std::string m_thread_name;
boost::shared_ptr<ThreadFunbase>
m_pfunptor;
HANDLE m_threadhandle;
unsigned int m_id;
bool m_bisrunning;
bool m_bisout;
virtual void run()
{
try{
m_bisrunning
= true;
m_pfunptor->run();
m_bisout
= true;
m_bisrunning
= false;
}
catch(...)
{
throw
std::logic_error("\r\n exception found in thread func! \r\n");
}
}
//now we are in
another thread :-)
static unsigned __stdcall threadfun(void *threadenti)
{
thread *
th = reinterpret_cast<thread*>(threadenti);
th->run();
return 0;
}
template<typename CT> CT *get_static_obj_ptr(CT **po = NULL)
{
static std::vector<boost::shared_ptr<CT> > v_ct;
boost::shared_ptr<CT>
sp_ct(new CT);
v_ct.push_back(sp_ct);
return sp_ct.get();
}
};
class ThreadObjBase
{
public:
enum ATACH_DETACH{ATTCH
= 0, DETACH};
ThreadObjBase(ATACH_DETACH a_or_d
= ATTCH): m_bNeedStop(false), m_a_or_d(a_or_d)
{}
virtual ~ThreadObjBase()
{
m_pth->join();
}
void Start()
{
if (ATTCH == m_a_or_d)
{
m_pth
= boost::shared_ptr<thread>(new thread(&ThreadObjBase::Thread_Start,this));
m_pth->start();
}
if (DETACH == m_a_or_d)
{
m_pth
= boost::shared_ptr<thread>(new thread(&ThreadObjBase::Thread_Start));
m_pth->start();
}
}
inline void NotifyStop()
{
m_bNeedStop
= true;
}
void Join()
{
m_pth->join();
}
public:
virtual void Run(){}
private:
void Thread_Start()
{
Run();
}
boost::shared_ptr<thread>
m_pth;
bool m_bNeedStop;
ATACH_DETACH
m_a_or_d;
};
template <typename
DT>
class ThreadObjBase_T
{
public:
enum ATACH_DETACH{ATTCH
= 0, DETACH};
ThreadObjBase_T(ATACH_DETACH a_or_d
= ATTCH):m_bNeedStop(FALSE), m_a_or_d(a_or_d)
{}
virtual ~ThreadObjBase_T()
{
m_pth->join();
}
void start()
{
if (ATTCH == m_a_or_d){
m_pth
= boost::shared_ptr<thread>(new thread(&DT::Run, static_cast<DT*>(this)));
m_pth->start();
}
if (DETACH == m_a_or_d){
m_pth
= boost::shared_ptr<thread>(new thread(&DT::Run));
m_pth->start();
}
}
inline void notify_stop()
{
m_bNeedStop
= TRUE;
}
void join()
{
m_pth->join();
}
private:
boost::shared_ptr<thread>
m_pth;
bool m_bNeedStop;
ATACH_DETACH
m_a_or_d;
};
END_UTI
#endif
//===================================================================
//example
#include "thread.h"
#include <iostream>
#include <stdlib.h>
bool g_needstop
= false;
int g_count
= 0;
void globle_func(int np)
{
std::cout << "-------
globle_func start--------" <<std::endl;
while(1)
{
if (g_needstop)
break;
std::cout << ">>in
globle_func countint:" <<g_count++
<<" param:" << np << std::endl;
Sleep(200);
}
std::cout << "-------
globle_func exit--------" <<std::endl;
}
class uti_thread_test_cls
{
public:
void mem_func()
{
std::cout << "-------
uti_thread_test_cls::mem_func start--------" <<std::endl;
while(1)
{
if (g_needstop)
break;
std::cout <<">>in
uti_thread_test_cls::mem_func count:"<< g_count++ << std::endl;
Sleep(200);
}
std::cout << "-------
uti_thread_test_cls::mem_func exit--------" <<std::endl;
}
};
//线程类的简单使用。
int main(int argc, char* argv[])
{
{
thread thread_1(globle_func, 100);
thread_1.start();
uti_thread_test_cls
cls_mem;
thread thread_2(&uti_thread_test_cls::mem_func, &cls_mem);
thread_2.start();
::system("pause\r\n");
g_needstop
= true;
}
::system("pause\r\n");
return 0;
}
昨天我通过zoundry将此文发表在本BLOG之中, 后来我通过网页才看到排版很糟糕(至今我还没有发现完美的BLOG桌面软件:-(, 如果大家有什么好的blog桌面软件也希望可以介绍一下, 在这里先谢谢了 ^_^),
故今天稍作调整重新发表。