共享Windows下C++库之线程篇

来源:互联网 发布:对时协议软件 编辑:程序博客网 时间:2024/05/22 02:29

今天把平时积累的一些比较常用的库给共享出来,一来“展现”下自己的开源精神,二来也可以发表下自己的看法。(假设你熟悉C++ tr1的组件)

共享顺序

1.线程库(线程篇、线程池篇、线程同步与本地线程存储篇)

2.内存库(待续…)

3.网络库(待续…)

 

一、线程篇(创建和管理单线程)

在Windows下,如果要在某类中创建线程使用,则有如下几个缺点(不方便)

1. 要提供线程句柄的管理

2.要提供线程入口函数(必须为static且具有__stdcall调用方式)

3.要有机制使线程退出(bool、Event、APC…)

4.需要在CreateThread,_beginthreadex,ATL::CreateThreadT,MFC::AfxBeginThread等等做决策

5.还没想到~~

有上述如此之多的不方便和缺点,促使了我开发此组件。该组件有效地解决了上述问题。使用方式:

1.声明类(需要线程的类)成员变量—>ThreadImplEx m_thread;

2.注册线程函数(不需要为static且__stdcall的调用方式,使用类普通成员函数即可__thiscall)—>m_thread.RegisterFunc(std::tr1::bind(….));

3.开始线程—>m_thread.Start()

4.结束线程—>m_thread.Stop();

OK!上组件代码

#ifndef __THREAD_THREAD_HPP
#define __THREAD_THREAD_HPP


#include "../Thread.hpp"



#ifndef ATLTRY
#define ATLTRY(x) (x)
#endif // ATLTRY





namespace DataStructure
{


//-----------------------------------------------------
// CThread

template< bool t_bManaged >
class CThreadT
{
public:
HANDLE m_hThread; // Handle to thread
DWORD m_dwThreadID; // Thread ID
bool m_bSuspended; // Thread currently suspended?

CThreadT(HANDLE hThread = NULL) : m_hThread(hThread), m_dwThreadID(0), m_bSuspended(false)
{
}

~CThreadT()
{
if( t_bManaged ) Release();
}

// Operations

bool Create(LPTHREAD_START_ROUTINE pThreadProc, LPVOID pParam = NULL, int iPriority = THREAD_PRIORITY_NORMAL)
{
_ASSERTE(m_hThread==NULL);
_ASSERTE(pThreadProc);

#if defined(_MT) || defined(_DLL)
m_hThread = (HANDLE) _beginthreadex(NULL, 0, (UINT (WINAPI*)(void*)) pThreadProc, pParam, CREATE_SUSPENDED, (UINT*) &m_dwThreadID);
#else
m_hThread = ::CreateThread(NULL, 0, pThreadProc, pParam, CREATE_SUSPENDED, &m_dwThreadID);
#endif // _MT

if( m_hThread == NULL )
return FALSE;

if( iPriority != THREAD_PRIORITY_NORMAL )
{
if( !::SetThreadPriority(m_hThread, iPriority) )
{
_ASSERTE(!"Couldn't set thread priority");
}
}

return ::ResumeThread(m_hThread) != (DWORD) -1;
}

bool Release()
{
if( m_hThread == NULL )
return TRUE;
if( ::CloseHandle(m_hThread) == FALSE )
return FALSE;

m_hThread = NULL;
m_dwThreadID = 0;

return TRUE;
}

void Attach(HANDLE hThread)
{
_ASSERTE(m_hThread==NULL);
m_hThread = hThread;
}

HANDLE Detach()
{
HANDLE hThread = m_hThread;
m_hThread = NULL;

return hThread;
}

bool SetPriority(int iPriority) const
{
_ASSERTE(m_hThread);

return ::SetThreadPriority(m_hThread, iPriority);
}

int GetPriority() const
{
_ASSERTE(m_hThread);

return ::GetThreadPriority(m_hThread);
}

bool Suspend()
{
_ASSERTE(m_hThread);

if( m_bSuspended )
return TRUE;

if( ::SuspendThread(m_hThread) == (DWORD) -1 )
return FALSE;

m_bSuspended = true;

return TRUE;
}

bool Resume()
{
_ASSERTE(m_hThread);

if( !m_bSuspended )
return TRUE;

if( ::ResumeThread(m_hThread) == (DWORD) -1 )
return FALSE;

m_bSuspended = false;

return TRUE;
}

bool IsSuspended() const
{
_ASSERTE(m_hThread);

return m_bSuspended == true;
}

bool IsRunning() const
{
if( m_hThread == NULL )
return FALSE;
DWORD dwCode = 0;

::GetExitCodeThread(m_hThread, &dwCode);

return dwCode == STILL_ACTIVE;
}

bool WaitForThread(DWORD dwTimeout = INFINITE) const
{
_ASSERTE(m_hThread);

return ::WaitForSingleObject(m_hThread, dwTimeout) == WAIT_OBJECT_0;
}

bool Terminate(DWORD dwExitCode = 0) const
{
// See Q254956 why calling this could be a bad idea!
_ASSERTE(m_hThread);

return TRUE == ::TerminateThread(m_hThread, dwExitCode);
}

DWORD GetThreadID() const
{
return m_dwThreadID;
}

bool GetExitCode(DWORD* pExitCode) const
{
_ASSERTE(m_hThread);
_ASSERTE(pExitCode);

return ::GetExitCodeThread(m_hThread, pExitCode);
}

#if(WINVER >= 0x0500)

bool GetThreadTimes(LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime) const
{
_ASSERTE(m_hThread);
_ASSERTE(lpExitTime!=NULL && lpKernelTime!=NULL && lpUserTime!=NULL);

return ::GetThreadTimes(m_hThread, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime);
}

#endif // WINVER

#if(WINVER >= 0x0501)

bool SetThreadAffinityMask(DWORD dwThreadMask)
{
_ASSERTE(m_hThread);

return ::SetThreadAffinityMask(m_hThread, dwThreadMask) != 0;
}

bool SetThreadIdealProcessor(DWORD dwIdealProcessor)
{
_ASSERTE(m_hThread);

return ::SetThreadIdealProcessor(m_hThread, dwIdealProcessor) != (DWORD) -1;
}

DWORD GetThreadIdealProcessor() const
{
_ASSERTE(m_hThread);

return ::SetThreadIdealProcessor(m_hThread, MAXIMUM_PROCESSORS);
}

#endif // WINVER

operator HANDLE() const
{
return m_hThread;
}
};

typedef CThreadT CThreadHandle;
typedef CThreadT CThread;


//----------------------------------------------------------------------
// Thread Stop policy

class CThreadStopAtBool
{
public:
volatile bool m_bStopped;
CThreadStopAtBool() : m_bStopped(false) { };
bool _ClearAbort() { m_bStopped = false; return TRUE; };
bool _Abort() { m_bStopped = true; return TRUE; };
bool _IsAborted() const { return m_bStopped == true; };
};

class CThreadStopAtEvent
{
public:
HANDLE m_hStopEvent;
CThreadStopAtEvent() { m_hStopEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); };
~CThreadStopAtEvent() { ::CloseHandle(m_hStopEvent); };
BOOL _ClearAbort() { return ::ResetEvent(m_hStopEvent); };
BOOL _Abort() { return ::SetEvent(m_hStopEvent); };
bool _IsAborted() const { return ::WaitForSingleObject(m_hStopEvent, 0) != WAIT_TIMEOUT; };
};


/////////////////////////////////////////////////////////////////////////////
// CThreadImpl

template< typename T, typename TStopPolicy = CThreadStopAtBool >
class CThreadImpl
: public CThread
, public TStopPolicy
{
public:
bool m_bAutoDelete; // Thread class will delete itself upon thread exit?
bool m_bAutoCleanup; // Thread class will wait for thread completion upon scope exit?

CThreadImpl()
: m_bAutoDelete(false)
, m_bAutoCleanup(true)
{
}

~CThreadImpl()
{
if( m_bAutoCleanup )
Stop();
}

// Operations

bool Start()
{
if( !_ClearAbort() )
return FALSE;
if( !Create(ThreadProc, (LPVOID) static_cast(this)) )
return FALSE;

return TRUE;
}

void Stop()
{
if( !Abort() )
return;

WaitForThread();
Release();
}

bool Abort()
{
if( m_hThread == NULL )
return FALSE;
if( !_Abort() )
return FALSE;
if( m_bSuspended )
Resume();

return TRUE;
}

bool IsAborted() const
{
_ASSERTE(m_hThread);

return _IsAborted();
}

void SetAutoClean(bool bAutoClean = true)
{
m_bAutoCleanup = bAutoClean;
}

void SetDeleteOnExit(bool bAutoDelete = true)
{
m_bAutoDelete = bAutoDelete;
m_bAutoCleanup = !bAutoDelete;
}

// Static members

static DWORD WINAPI ThreadProc(LPVOID pData)
{
T* pThis = static_cast(pData);

#if defined(_MT) || defined(_DLL)
ATLTRY( ::_endthreadex(pThis->Run()) );
if( pThis->m_bAutoDelete )
delete pThis;
return 0;
#else
DWORD dwRet = 0;
ATLTRY( dwRet = pThis->Run() );
if( pThis->m_bAutoDelete )
delete pThis;
return dwRet;
#endif // _MT
}

// Overridables

DWORD Run()
{
_ASSERTE(false); // must override this
//
// Sample thread loop...
//
// while( !IsAborted() ) {
// ...
// }
//
return 0;
}
};


//---------------------------------------------------------------
// CThreadImplEx

template<typename TStopPolicy>
class CThreadImplExT
: public CThread
, public TStopPolicy
{
typedef std::tr1::functionvoid)> ThreadFunc;

public:
bool m_bAutoDelete; // Thread class will delete itself upon thread exit?
bool m_bAutoCleanup; // Thread class will wait for thread completion upon scope exit?

ThreadFunc m_fThread; // Thread work function

public:
CThreadImplExT()
: m_bAutoDelete(false)
, m_bAutoCleanup(true)
{
}

~CThreadImplExT()
{
if( m_bAutoCleanup )
Stop();
}

// Register Thread work function
void RegisterFunc(ThreadFunc func)
{
m_fThread = func;
}

// Operations

bool Start()
{
if( !_ClearAbort() )
return FALSE;
if( !Create(ThreadProc, reinterpret_cast(this)) )
return FALSE;

return TRUE;
}

void Stop(DWORD dwTime = INFINITE)
{
if( !Abort() )
return;

if( WaitForThread(dwTime) )
Terminate(-1);

Release();
}

bool Abort()
{
if( m_hThread == NULL )
return FALSE;
if( !_Abort() )
return FALSE;
if( m_bSuspended )
Resume();

return TRUE;
}

bool IsAborted() const
{
_ASSERTE(m_hThread);

return _IsAborted();
}

void SetAutoClean(bool bAutoClean = true)
{
m_bAutoCleanup = bAutoClean;
}

void SetDeleteOnExit(bool bAutoDelete = true)
{
m_bAutoDelete = bAutoDelete;
m_bAutoCleanup = !bAutoDelete;
}

// Static members

static DWORD WINAPI ThreadProc(LPVOID pData)
{
CThreadImplExT* pThis = reinterpret_cast(pData);

// Not Register?
if( pThis->m_fThread == NULL )
return -1L;

#if defined(_MT) || defined(_DLL)
ATLTRY( _endthreadex(pThis->m_fThread()) );
if( pThis->m_bAutoDelete )
delete pThis;
return 0;
#else
DWORD dwRet = 0;
ATLTRY( dwRet = pThis->pThis->m_fThread() );
if( pThis->m_bAutoDelete )
delete pThis;
return dwRet;
#endif // _MT
}
};

typedef CThreadImplExT ThreadImplEx;
typedef CThreadImplExT ThreadImplExEvent;



//-----------------------------------------------------------
// CMessageThreadImpl

template< typename T >
class CMessageThreadImpl
: public CThreadImpl
{
public:
// Operations

bool PostQuitMessage()
{
_ASSERTE(m_hThread);
if( m_hThread == NULL )
return FALSE;

return ::PostThreadMessage(m_dwThreadID, WM_QUIT, 0, 0L);
}

bool PostMessage(UINT uMsg, WPARAM wParam = 0, LPARAM lParam = 0L)
{
_ASSERTE(m_hThread);
if( m_hThread == NULL )
return FALSE;

return ::PostThreadMessage(m_dwThreadID, uMsg, wParam, lParam);
}

// Overridables

void InitQueue()
{
}

void CloseQueue()
{
}

void ProcessWindowMessage(LPVOID /*pReserved*/, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& /*lResult*/, DWORD /*dwReserved*/)
{
_ASSERTE(false); // must override this
}

// Implementation

DWORD Run()
{
T* pT = static_cast(this);
MSG msg;
::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
pT->InitQueue();
while( !IsAborted() )
{
int iRet = (int)
::GetMessage(&msg, NULL, 0, 0);
if( iRet <= 0 )
break;

LRESULT lResult = 0;
pT->ProcessWindowMessage(NULL, msg.message, msg.wParam, msg.lParam, lResult, 0L);
}

pT->CloseQueue();
return 0;
}
};


//--------------------------------------------------------------
// CMessageThreadImplEx

template<typename StopPolicyT>
class CMessageThreadImplExT
: public CThreadImplExT
{
typedef std::tr1::function<void(MSG &, LRESULT &)> ThreadMessageFunc;

public:
ThreadMessageFunc m_fMessageFunc;

protected:
void RegisterFunc(ThreadFunc);

public:
// Operations

void RegisterMessageFunc(ThreadMessageFunc func)
{
m_fMessageFunc = func;
m_fThread = std::tr1::bind(&CMessageThreadImplExT::Run, this);
}

bool PostQuitMessage()
{
_ASSERTE(m_hThread);
if( m_hThread == NULL )
return FALSE;

return 0 != ::PostThreadMessage(m_dwThreadID, WM_QUIT, 0, 0L);
}

bool PostMessage(UINT uMsg, WPARAM wParam = 0, LPARAM lParam = 0L)
{
_ASSERTE(m_hThread);
if( m_hThread == NULL )
return FALSE;

return 0 != ::PostThreadMessage(m_dwThreadID, uMsg, wParam, lParam);
}

// Implementation

DWORD Run()
{
assert(m_fMessageFunc != NULL);
// Not Register?
if( m_fMessageFunc == NULL )
return -1L;

MSG msg;
::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);

while( !IsAborted() )
{
LRESULT lResult = 0;
m_fMessageFunc(msg, lResult);
if( lResult != S_OK )
break;
}


return 0;
}
};

typedef CMessageThreadImplExT MessageThreadImplEx;
typedef CMessageThreadImplExT MessageThreadImplExEvent;



}

#endif // __THREAD_THREAD_HPP


简单介绍下各个类:

  • CThreadT很简单,就是对thread的句柄包装而已,一个简单的wrapper。对他有个模板参数bool,是否需要在析构的时候释放自己(熟悉WTL的朋友笑了~)。

  • CThreadStopAtBool和CThreadStopAtEvent是线程退出的策略,知道C++ Policy机制的朋友笑了~

  • CThreadImpl是线程的再次包装,如果客户端要使用此类来进行线程工作,需要继承此类,并且提供DWORD Run()签名函数,因为使用了静多态的手法(熟悉ATL的朋友笑了~),但是并不推荐使用此类,因为它让客户端代码和线程耦合起来了,悲剧~

  • CThreadImplExT是针对CThreadImpl会和客户端类耦合的一个扩展类,它使客户端使用线程非常方便,在上面的使用方式中展现了~

  • CMessageThreadImpl和CMessageThreadImplExT是对线程接受消息的一个扩展,原理类似CThreadImpl和CThreadImplExT~

 

当然,上述的线程组件代码并不是人见人爱,希望能听到各种意见~

再次,我提供了使用此组件的配套示例代码,欢迎下载(右键下载)测试~(当然要把后缀gif替换为rar,熟悉的人笑了~)

猛击这里 这里~~

原创粉丝点击