【编程笔记】线程池实现源码(从POCO中剥离出来)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fzuim/article/details/82023240

源码下载:https://download.csdn.net/download/fzuim/10625204

CThreadPool类

/***************************************************************************** 
    *  @COPYRIGHT NOTICE 
    *  @Copyright (c) 2018, Fzuim 
    *  @All rights reserved 

    *  @file     : ThreadPool.h 
    *  @version  : ver 1.0 

    *  @author   : Fzuim 
    *  @date     : 2018/8/20 10:36 
    *  @brief    : 线程池类 
*****************************************************************************/
#ifndef Fzuim_ThreadPool_INCLUDE
#define Fzuim_ThreadPool_INCLUDE

#include "Runnable.h"
#include "PooledThread.h"
#include "PooledMutex.h"

class CThreadPool
{
public:
    CThreadPool(int v_iMinCapacity = 2,
        int v_iMaxCapacity = 16,
        int v_iIdleTime = 60,
        int v_iStackSize = 0);

    ~CThreadPool();

    static CThreadPool& GetDefaultPool();

    void Start(CRunnable& v_Target);
    void StopAll();
    void JoinAll(); //等待所有线程完成(并非退出)
    void Collect(); //手动整理,从线程池停止并移除空闲过久的线程。整个框架也会进行自动整理

    int GetUsedThreadNum() const;
    int GetAllocatedThreadNum() const;
    int GetAvailableThreadNum() const;

    void AddMaxThreadNum(int v_i);

protected:
    void HouseKeep();
    CPooledThread* GetThread();

private:
    typedef std::vector<CPooledThread*> ThreadVec;

    int m_iMinCapacity;
    int m_iMaxCapacity;
    int m_iIdleTime;
    int m_iStackSize;
    int m_iHouseKeep;

    ThreadVec m_vecThreads;
    mutable CThreadMutex m_Mutex; //mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。
};

#endif
/***************************************************************************** 
    *  @COPYRIGHT NOTICE 
    *  @Copyright (c) 2018, Fzuim 
    *  @All rights reserved 

    *  @file     : ThreadPool.cpp 
    *  @version  : ver 1.0 

    *  @author   : Fzuim 
    *  @date     : 2018/8/20 10:35 
    *  @brief    : 线程池
*****************************************************************************/

#include "stdafx.h"
#include "ThreadPool.h"

/*
 *  描述:线程池构造函数
 *  默认创建最小2个,最多16个线程,空闲超时时间60s,线程默认栈参数为01MB)
 */
CThreadPool::CThreadPool( int v_iMinCapacity /*= 2*/, int v_iMaxCapacity /*= 16*/, int v_iIdleTime /*= 60*/, int v_iStackSize /*= 0*/ ):
    m_iMinCapacity(v_iMinCapacity),
    m_iMaxCapacity(v_iMaxCapacity),
    m_iIdleTime(v_iIdleTime),
    m_iStackSize(v_iStackSize),
    m_iHouseKeep(0)
{
    assert (m_iMinCapacity >= 1 && m_iMaxCapacity >= m_iMinCapacity && m_iIdleTime > 0);

    for (int i = 0; i < m_iMaxCapacity; ++i)
    {
        CPooledThread* pThread = new CPooledThread(m_iStackSize);
        m_vecThreads.push_back(pThread);
        pThread->Start(); //将线程启动起来
    }
}

CThreadPool::~CThreadPool()
{
    StopAll();
}

//对传入的函数指针,从线程池获取一条线程并附加执行
void CThreadPool::Start( CRunnable& v_Target )
{
    GetThread()->Start(CThread::PRIO_NORMAL_IMPL, v_Target);
}

//停止线程池所有线程
void CThreadPool::StopAll()
{
    CFastLock FastLock(m_Mutex);

    for (ThreadVec::iterator it = m_vecThreads.begin(); it != m_vecThreads.end(); ++it)
    {
        (*it)->Release();
    }
    m_vecThreads.clear();
}

//获取正在使用中的线程数量
int CThreadPool::GetUsedThreadNum() const
{
    CFastLock FastLock(m_Mutex);

    int iCount = 0;
    for (ThreadVec::const_iterator it = m_vecThreads.begin(); it != m_vecThreads.end(); ++it)
    {
        if (!(*it)->Idle()) ++iCount;
    }
    return iCount;
}

//获取线程池总的线程数
int CThreadPool::GetAllocatedThreadNum() const
{
    CFastLock FastLock(m_Mutex);

    return int(m_vecThreads.size());;
}

/*
 *  获取可用线程个数=已创建线程空闲数+最大线程数-已创建线程数
 */
int CThreadPool::GetAvailableThreadNum() const
{
    CFastLock FastLock(m_Mutex);

    int iCount = 0;
    for (ThreadVec::const_iterator it = m_vecThreads.begin(); it != m_vecThreads.end(); ++it)
    {
        if ((*it)->Idle()) ++iCount;
    }

    return (int) (iCount + m_iMaxCapacity - m_vecThreads.size());
}

//从线程池获取一个线程(空闲状态)
CPooledThread* CThreadPool::GetThread()
{
    CFastLock FastLock(m_Mutex);

    //每32次获取线程,就进行一次线程池整理
    if (++m_iHouseKeep == 32)
    {
        HouseKeep();
    }

    CPooledThread* pThread = NULL;
    for (ThreadVec::iterator it = m_vecThreads.begin(); !pThread && it != m_vecThreads.end(); ++it)
    {
        if ((*it)->Idle()) pThread = *it;
    }

    if (!pThread)
    {
        if ((int)m_vecThreads.size() < m_iMaxCapacity)
        {
            pThread = new CPooledThread(m_iStackSize);
            try
            {
                pThread->Start();
                m_vecThreads.push_back(pThread);
            }
            catch(...)
            {
                delete pThread;
                pThread = NULL;
                throw;
            }
        }
        else
        {
            throw NoThreadAvailableException();
        }
    }

    //激活状态设置
    pThread->Activate();
    return pThread;
}

//等待所有线程完成任务
void CThreadPool::JoinAll()
{
    CFastLock FastLock(m_Mutex);

    for (ThreadVec::iterator it = m_vecThreads.begin(); it != m_vecThreads.end(); ++it)
    {
        (*it)->Join();
    }
}

//线程池整理:根据当前线程状态,进行调整
void CThreadPool::HouseKeep()
{
    m_iHouseKeep = 0;
    if((int)m_vecThreads.size() <= m_iMinCapacity)
    {
        return;
    }

    ThreadVec IdleThreads; //空闲线程数
    ThreadVec ExpiredThreads; //空闲过久线程
    ThreadVec ActiveThreads; //活动线程

    //手动分配vector大小,提高效率
    IdleThreads.reserve(m_vecThreads.size());
    ActiveThreads.reserve(m_vecThreads.size());

    //对线程池进行一次分类整理
    for(ThreadVec::iterator it = m_vecThreads.begin(); it != m_vecThreads.end(); ++it)
    {
        if((*it)->Idle())
        {
            if ((*it)->IdleTime() < m_iIdleTime) //和设置的超时时间对比
            {
                IdleThreads.push_back(*it); //超时不久
            }
            else
            {
                ExpiredThreads.push_back(*it); //超时太久
            }
        }
        else
        {
            ActiveThreads.push_back(*it); //活动的线程
        }
    }

    int iActiveNum = (int)ActiveThreads.size();
    int iLimit = iActiveNum + (int)IdleThreads.size();
    iLimit = iLimit < m_iMinCapacity ? m_iMinCapacity : iLimit;

    //将空闲太久和空闲不久的线程进行一次合并,合并到空闲不久的末尾
    //这边主要是为了:继续讲空闲太久的线程利用起来,防止频繁的创建销毁线程
    IdleThreads.insert(IdleThreads.end(), ExpiredThreads.begin(), ExpiredThreads.end());
    m_vecThreads.clear();

    for(ThreadVec::iterator it = IdleThreads.begin(); it != IdleThreads.end(); ++it)
    {
        if (iActiveNum < iLimit)
        {
            m_vecThreads.push_back(*it); //从超时线程内=》线程池
            ++iActiveNum;
        }
        else
        {
            (*it)->Release();
        }
    }

    //重新整合:活动+空闲
    m_vecThreads.insert(m_vecThreads.end(), ActiveThreads.begin(), ActiveThreads.end());
}

//增加线程池里的线程数
void CThreadPool::AddMaxThreadNum( int v_i )
{
    CFastLock FastLock(m_Mutex);

    assert(m_iMaxCapacity + v_i >= m_iMinCapacity);
    m_iMaxCapacity += v_i;
    HouseKeep(); //这边进行线程池整理,是为了进一步将空闲线程利用起来
}

//线程池整理
void CThreadPool::Collect()
{
    CFastLock FastLock(m_Mutex);
    HouseKeep();
}

//////////////////////////////////////////////////////////////////////////
class CThreadPoolSingleton
{
public:
    CThreadPoolSingleton()
    {
        m_pPool = NULL;
    }

    ~CThreadPoolSingleton()
    {
        if (m_pPool)
        {
            delete m_pPool;
            m_pPool = NULL;
        }
    }

    CThreadPool* GetPool()
    {
        CFastLock FastLock(m_Mutex);

        if (!m_pPool)
        {
            m_pPool = new CThreadPool();
        }

        return m_pPool;
    }
private:
    CThreadPool* m_pPool;
    CThreadMutex m_Mutex;
};

static CThreadPoolSingleton g_DefaultPool;

//获取默认线程池
CThreadPool& CThreadPool::GetDefaultPool()
{
    return *g_DefaultPool.GetPool();
}

CPooledThread类

/***************************************************************************** 
    *  @COPYRIGHT NOTICE 
    *  @Copyright (c) 2018, Fzuim 
    *  @All rights reserved 

    *  @file     : PooledThread.h 
    *  @version  : ver 1.0 

    *  @author   : Fzuim 
    *  @date     : 2018/8/20 10:41 
    *  @brief    : 线程类===》线程池
*****************************************************************************/
#ifndef Fzuim_PooledThread_INCLUDE
#define Fzuim_PooledThread_INCLUDE

#include "Runnable.h"
#include "Thread.h"
#include "PooledEvent.h"
#include "PooledMutex.h"
#include <ctime>

class CPooledThread : public CRunnable
{
public:
    CPooledThread(int v_iStackSize = 0);
    ~CPooledThread();

    void Start();
    void Start(CThread::_enPriority v_enPriority, CRunnable& v_Target);
    void Run();
    void Release();
    BOOL Idle();
    int IdleTime();
    void Activate();
    void Join();

private:
    volatile bool        m_bIdle;
    volatile std::time_t m_IdleTime;

    CRunnable*           m_pTarget;
    CThread              m_Thread;

    CPooledEvent         m_hStartedEvt; //标识线程是否已经在运行
    CPooledEvent         m_hTargetReadyEvt; //标识是否设置了:线程执行的回调函数
    CPooledEvent         m_hTargetCompletedEvt; //标识线程运行任务是否完成

    CThreadMutex         m_ThreadMutex;
};

#endif
/***************************************************************************** 
    *  @COPYRIGHT NOTICE 
    *  @Copyright (c) 2018, Fzuim 
    *  @All rights reserved 

    *  @file     : PooledThread.cpp 
    *  @version  : ver 1.0 

    *  @author   : Fzuim 
    *  @date     : 2018/8/20 10:42 
    *  @brief    : 线程类===》线程池 
*****************************************************************************/
#include "stdafx.h"
#include "PooledThread.h"

CPooledThread::CPooledThread( int v_iStackSize /*= 0*/ ):
    m_bIdle(true),
    m_IdleTime(0),
    m_pTarget(NULL),
    m_hTargetCompletedEvt(false)
{
    m_Thread.SetStackSize(v_iStackSize);
    m_IdleTime = std::time(NULL);
}

CPooledThread::~CPooledThread()
{

}

//线程池初始化的时候,创建CPooledThread对象时,都将真正意义上创建一个线程
//由于CPooledThread也是继承与CRunnable,所以创建的线程将主动执行CPooledThread::Run()
//外层使用线程池线程时,将函数指针传入m_pTarget,即可实现自动运行
void CPooledThread::Start()
{
    m_Thread.Start(*this);
    m_hStartedEvt.Wait();
}

//线程启动,主要是将m_hTargetReadyEvt事件设置为触发状态
void CPooledThread::Start(CThread::_enPriority v_enPriority, CRunnable& v_Target)
{
    CFastLock FastLock(m_ThreadMutex);

    assert(m_pTarget == NULL);

    m_pTarget = &v_Target;
    m_Thread.SetPriority(v_enPriority);
    m_hTargetReadyEvt.Set();
}

//线程池里的线程运行框架,就在这个Run函数里面
void CPooledThread::Run()
{
    m_hStartedEvt.Set();
    for (;;)
    {
        m_hTargetReadyEvt.Wait();
        m_ThreadMutex.lock();
        if (m_pTarget)
        {
            m_ThreadMutex.unlock();
            try
            {
                m_pTarget->Run();
            }
            catch(...)
            {
                throw SystemException("PooledThread::Run Error.");
            }

            CFastLock FastLock(m_ThreadMutex);
            m_pTarget = NULL;
            m_IdleTime = std::time(NULL);
            m_bIdle = true;
            m_hTargetCompletedEvt.Set();
            m_Thread.SetPriority(CThread::PRIO_NORMAL_IMPL);
        }
        else
        {
            m_ThreadMutex.unlock();
            break;
        }
    }
}

//线程释放
void CPooledThread::Release()
{
    m_ThreadMutex.lock();
    m_pTarget = NULL;
    m_ThreadMutex.unlock();

    m_hTargetReadyEvt.Set(); //让Run直接运行,自动退出线程
    //等待线程退出
    if (m_Thread.TryJoin(10000))
    {
        delete this;
    }
}

//返回线程繁忙状态
BOOL CPooledThread::Idle()
{
    return m_bIdle;
}

//返回线程空闲时间
int CPooledThread::IdleTime()
{
    CFastLock FastLock(m_ThreadMutex);
    return (int) (std::time(NULL) - m_IdleTime);
}

//线程激活相关状态设置
void CPooledThread::Activate()
{
    CFastLock FastLock(m_ThreadMutex);

    assert(m_bIdle);
    m_bIdle = false;
    m_hTargetCompletedEvt.Reset();
}

//等待线程完成,同步操作
void CPooledThread::Join()
{
    if (m_pTarget)
    {
        m_hTargetCompletedEvt.Wait();
    }
}


CThread类

/***************************************************************************** 
    *  @COPYRIGHT NOTICE 
    *  @Copyright (c) 2018, Fzuim 
    *  @All rights reserved 

    *  @file     : Thread.h 
    *  @version  : ver 1.0 

    *  @author   : Fzuim 
    *  @date     : 2018/8/20 10:17 
    *  @brief    : 线程类
*****************************************************************************/

#ifndef Fzuim_Thread_INCLUDE
#define Fzuim_Thread_INCLUDE

#include "GlobalHead.h"
#include "Runnable.h"

class CThread
{
public:

#if defined(_DLL)
    typedef DWORD (WINAPI *Entry)(LPVOID);
#else
    typedef unsigned (__stdcall *Entry)(void*);
#endif

    enum _enPriority
    {
        PRIO_LOWEST_IMPL  = THREAD_PRIORITY_LOWEST,
        PRIO_LOW_IMPL     = THREAD_PRIORITY_BELOW_NORMAL,
        PRIO_NORMAL_IMPL  = THREAD_PRIORITY_NORMAL,
        PRIO_HIGH_IMPL    = THREAD_PRIORITY_ABOVE_NORMAL,
        PRIO_HIGHEST_IMPL = THREAD_PRIORITY_HIGHEST
    };

    CThread();
    ~CThread();

    void Start(CRunnable& v_Target);
    void SetPriority(_enPriority v_enPrio);
    _enPriority GetPriority() const;
    void SetStackSize(int v_iSize);
    int GetStackSize() const;

    bool TryJoin(long v_lngMilliseconds);
    bool IsRunning() const;

protected:
#if defined(_DLL)
    static DWORD WINAPI runnableEntry(LPVOID pThread);
#else
    static unsigned __stdcall runnableEntry(void* pThread);
#endif

    void Create(Entry v_Ent, void* v_pData);
    void ThreadCleanup();

private:
    CRunnable* m_pRunnableTarget;

    HANDLE m_hThread;
    DWORD m_dwThreadId;
    int m_iPriority;
    int m_iStackSize;
};

#endif
/***************************************************************************** 
    *  @COPYRIGHT NOTICE 
    *  @Copyright (c) 2018, Fzuim 
    *  @All rights reserved 

    *  @file     : Thread.cpp 
    *  @version  : ver 1.0 

    *  @author   : Fzuim 
    *  @date     : 2018/8/20 10:37 
    *  @brief    : 线程类 
*****************************************************************************/

#include "stdafx.h"
#include "Thread.h"

CThread::CThread():
    m_pRunnableTarget(NULL),
    m_hThread(NULL),
    m_dwThreadId(0),
    m_iPriority(PRIO_NORMAL_IMPL),
    m_iStackSize(0)
{

}

CThread::~CThread()
{
    if (m_hThread)
    {
        CloseHandle(m_hThread);
        m_hThread = NULL;
    }
}

#if defined(_DLL)
DWORD WINAPI CThread::runnableEntry(LPVOID pThread)
#else
unsigned __stdcall CThread::runnableEntry(void* pThread)
#endif
{
    reinterpret_cast<CThread*>(pThread)->m_pRunnableTarget->Run();
    return 0;
}

//启动线程
void CThread::Start( CRunnable& v_Target )
{
    if (!IsRunning())
    {
        m_pRunnableTarget = &v_Target;
        Create(runnableEntry, this);
    }
    else
    {
        throw SystemException("thread already running");
    }
}

//设置线程优先级
void CThread::SetPriority( _enPriority v_enPrio )
{
    m_iPriority = v_enPrio;
}

//获取线程优先级
CThread::_enPriority CThread::GetPriority() const
{
    return _enPriority(m_iPriority);
}

//设置线程堆栈空间大小
void CThread::SetStackSize( int v_iSize )
{
    m_iStackSize = v_iSize;
}

//获取线程堆栈空间大小
int CThread::GetStackSize() const
{
    return m_iStackSize;
}

//判断线程是否在运行
bool CThread::IsRunning() const
{
    if (m_hThread)
    {
        DWORD dwEc = 0;
        return GetExitCodeThread(m_hThread, &dwEc) && dwEc == STILL_ACTIVE;
    }
    return false;
}

//创建线程,最底层实现:CreateThread或_beginthreadex
void CThread::Create( Entry v_Ent, void* v_pData )
{
#if defined(_DLL)
    m_hThread = CreateThread(NULL, m_iStackSize, v_Ent, v_pData, 0, &m_dwThreadId);
#else
    unsigned threadId;
    m_hThread = (HANDLE) _beginthreadex(NULL, m_iStackSize, v_Ent, this, 0, &threadId);
    m_dwThreadId = static_cast<DWORD>(threadId);
#endif

    if (!m_hThread){
        throw SystemException("cannot create thread");
    }
    if (m_iPriority != PRIO_NORMAL_IMPL && !SetThreadPriority(m_hThread, m_iPriority)){
        throw SystemException("cannot set thread priority");
    }
}

//等待线程退出
bool CThread::TryJoin( long v_lngMilliseconds )
{
    if (!m_hThread)
    {
        return true;
    }

    switch(WaitForSingleObject(m_hThread, v_lngMilliseconds + 1))
    {
    case WAIT_TIMEOUT:
        return false;
    case WAIT_OBJECT_0:
        ThreadCleanup();
        return true;
    default:
        throw SystemException("cannot join thread");
    }
}

//线程句柄释放
void CThread::ThreadCleanup()
{
    if (!m_hThread) return;
    if (CloseHandle(m_hThread)) m_hThread = NULL;
}

CRunnable类

/***************************************************************************** 
    *  @COPYRIGHT NOTICE 
    *  @Copyright (c) 2018, Fzuim 
    *  @All rights reserved 

    *  @file     : Runnable.h 
    *  @version  : ver 1.0 

    *  @author   : Fzuim 
    *  @date     : 2018/8/20 10:19 
    *  @brief    : 纯虚函数,接口类
*****************************************************************************/

#ifndef Fzuim_Runnable_INCLUDE
#define Fzuim_Runnable_INCLUDE

class CRunnable
{
public:
    CRunnable(){};
    virtual ~CRunnable(){};

    virtual void Run() = 0;
};

#endif

CRunnableAdapter类

/***************************************************************************** 
    *  @COPYRIGHT NOTICE 
    *  @Copyright (c) 2018, Fzuim 
    *  @All rights reserved 

    *  @file     : RunnableAdapter.h 
    *  @version  : ver 1.0 

    *  @author   : Fzuim 
    *  @date     : 2018/8/20 11:09 
    *  @brief    : 进程回调适配器类 
*****************************************************************************/
#ifndef Fzuim_RunnableAdapter_INCLUDE
#define Fzuim_RunnableAdapter_INCLUDE

#include "Runnable.h"

template <class C>
class CRunnableAdapter : public CRunnable
{
public:
    typedef void (C::*Callback)();

    CRunnableAdapter(C& object, Callback method): _pObject(&object), _method(method)
    {
    }

    CRunnableAdapter(const CRunnableAdapter& ra): _pObject(ra._pObject), _method(ra._method)
    {
    }

    ~CRunnableAdapter()
    {
    }

    CRunnableAdapter& operator = (const CRunnableAdapter& ra)
    {
        _pObject = ra._pObject;
        _method  = ra._method;
        return *this;
    }

    void Run()
    {
        (_pObject->*_method)();
    }

private:
    CRunnableAdapter();

    C*       _pObject;
    Callback _method;
};

#endif

CThreadMutex类

/***************************************************************************** 
    *  @COPYRIGHT NOTICE 
    *  @Copyright (c) 2018, Fzuim 
    *  @All rights reserved 

    *  @file     : PooledMutex.h 
    *  @version  : ver 1.0 

    *  @author   : Fzuim 
    *  @date     : 2018/8/20 10:40 
    *  @brief    : 线程锁 
*****************************************************************************/
#ifndef Fzuim_PooledMutex_INCLUDE
#define Fzuim_PooledMutex_INCLUDE

#include "GlobalHead.h"

class CThreadMutex
{
public:
    CThreadMutex();
    ~CThreadMutex();

    void lock();
    void lock(long v_lngMilliseconds);
    bool tryLock();
    void unlock();
private:
    bool m_bInitialized;
    CRITICAL_SECTION m_criticalSection;
};

//自动加解锁,利用C++ 构造和析构函数的特性
class CFastLock
{
public:
    CFastLock(CThreadMutex& v_Mutex);
    ~CFastLock();
private:
    CThreadMutex* m_pMutex;
};

#endif
/***************************************************************************** 
    *  @COPYRIGHT NOTICE 
    *  @Copyright (c) 2018, Fzuim 
    *  @All rights reserved 

    *  @file     : PooledMutex.cpp 
    *  @version  : ver 1.0 

    *  @author   : Fzuim 
    *  @date     : 2018/8/20 10:40 
    *  @brief    : 线程锁 
*****************************************************************************/
#include "stdafx.h"
#include "PooledMutex.h"

CThreadMutex::CThreadMutex()
{
    m_bInitialized = TRUE;
    InitializeCriticalSection(&m_criticalSection);
}

CThreadMutex::~CThreadMutex()
{
    if (m_bInitialized)
        DeleteCriticalSection(&m_criticalSection);
    m_bInitialized = FALSE;
}

void CThreadMutex::lock()
{
    if (!m_bInitialized)
        return;

    EnterCriticalSection(&m_criticalSection);
}

bool CThreadMutex::tryLock()
{
    try
    {
        return TryEnterCriticalSection(&m_criticalSection) != 0;
    }
    catch (...)
    {
    }
    throw SystemException("cannot lock mutex");
}

void CThreadMutex::unlock()
{
    if (!m_bInitialized)
        return;

    LeaveCriticalSection(&m_criticalSection);
}

CFastLock::CFastLock( CThreadMutex& v_Mutex )
{
    m_pMutex = &v_Mutex;
    if (m_pMutex)
    {
        m_pMutex->lock();
    }
}

CFastLock::~CFastLock()
{
    if (m_pMutex)
    {
        m_pMutex->unlock();
    }
}

CPooledEvent类

/***************************************************************************** 
    *  @COPYRIGHT NOTICE 
    *  @Copyright (c) 2018, Fzuim 
    *  @All rights reserved 

    *  @file     : PooledEvent.h 
    *  @version  : ver 1.0 

    *  @author   : Fzuim 
    *  @date     : 2018/8/20 10:38 
    *  @brief    : 线程池事件类 
*****************************************************************************/
#ifndef Fzuim_PooledEvent_INCLUDE
#define Fzuim_PooledEvent_INCLUDE

#include "GlobalHead.h"

class CPooledEvent
{
public:
    CPooledEvent(bool v_bAutoReset = true);
    ~CPooledEvent();

    void Set();
    void Wait();
    bool Wait(const long v_lngmilliseconds);
    void Reset();
private:
    HANDLE m_hEvent;
};

#endif
/***************************************************************************** 
    *  @COPYRIGHT NOTICE 
    *  @Copyright (c) 2018, Fzuim 
    *  @All rights reserved 

    *  @file     : PooledEvent.cpp 
    *  @version  : ver 1.0 

    *  @author   : Fzuim 
    *  @date     : 2018/8/20 10:39 
    *  @brief    : 线程池事件类  
*****************************************************************************/
#include "stdafx.h"
#include "PooledEvent.h"

CPooledEvent::CPooledEvent( bool v_bAutoReset /*= true*/ )
{
    m_hEvent = CreateEvent(NULL, v_bAutoReset ? FALSE : TRUE, FALSE, NULL);
    if (!m_hEvent)
    {
        throw SystemException("cannot create event");
    }
}

CPooledEvent::~CPooledEvent()
{
    if (m_hEvent)
    {
        CloseHandle(m_hEvent);
        m_hEvent = NULL;
    }
}

void CPooledEvent::Set()
{
    if (!SetEvent(m_hEvent))
    {
        throw SystemException("cannot signal event");
    }
}

void CPooledEvent::Wait()
{
    switch (WaitForSingleObject(m_hEvent, INFINITE))
    {
    case WAIT_OBJECT_0:
        return;
    default:
        throw SystemException("wait for event failed");
    }
}

bool CPooledEvent::Wait( const long v_lngmilliseconds )
{
    switch (WaitForSingleObject(m_hEvent, v_lngmilliseconds + 1))
    {
    case WAIT_TIMEOUT:
        return false;
    case WAIT_OBJECT_0:
        return true;
    default:
        throw SystemException("wait for event failed");     
    }
}

void CPooledEvent::Reset()
{
    if (!ResetEvent(m_hEvent))
    {
        throw SystemException("cannot reset event");
    }
}

CPooledException类

/***************************************************************************** 
    *  @COPYRIGHT NOTICE 
    *  @Copyright (c) 2018, Fzuim 
    *  @All rights reserved 

    *  @file     : Exception.h 
    *  @version  : ver 1.0 

    *  @author   : Fzuim 
    *  @date     : 2018/8/20 10:39 
    *  @brief    : 异常类 
*****************************************************************************/
#ifndef Fzuim_Exception_INCLUDE
#define Fzuim_Exception_INCLUDE

#include <stdexcept>

class CPooledException: public std::exception
{
public:
    CPooledException(const std::string& msg, int code = 0);

    CPooledException(const std::string& msg, const std::string& arg, int code = 0);

    CPooledException(const std::string& msg, const CPooledException& nested, int code = 0);

    CPooledException(const CPooledException& exc);

    ~CPooledException() throw();

    CPooledException& operator = (const CPooledException& exc);

    virtual const char* name() const throw();

    virtual const char* className() const throw();

    virtual const char* what() const throw();

    const CPooledException* nested() const;

    const std::string& message() const;

    int code() const;

    std::string displayText() const;

    virtual CPooledException* clone() const;

    virtual void rethrow() const;

protected:
    CPooledException(int code = 0);

    void message(const std::string& msg);

    void extendedMessage(const std::string& arg);

private:
    std::string  _msg;
    CPooledException*  _pNested;
    int          _code;
};

//宏实现类定义
#define FZUIM_DECLARE_EXCEPTION_CODE(CLS, BASE, CODE) \
    class CLS: public BASE                                                          \
        {                                                                           \
        public:                                                                     \
        CLS(int code = CODE);                                                       \
        CLS(const std::string& msg, int code = CODE);                               \
        CLS(const std::string& msg, const std::string& arg, int code = CODE);       \
        CLS(const std::string& msg, const CPooledException& exc, int code = CODE);  \
        CLS(const CLS& exc);                                                        \
        ~CLS() throw();                                                                \
        CLS& operator = (const CLS& exc);                                           \
        const char* name() const throw();                                           \
        const char* className() const throw();                                      \
        CPooledException* clone() const;                                            \
        void rethrow() const;                                                       \
        };

#define FZUIM_DECLARE_EXCEPTION(CLS, BASE) \
    FZUIM_DECLARE_EXCEPTION_CODE(CLS, BASE, 0)

//宏实现类接口
#define FZUIM_IMPLEMENT_EXCEPTION(CLS, BASE, NAME)                                                  \
    CLS::CLS(int code): BASE(code)                                                                  \
    {                                                                                               \
    }                                                                                               \
    CLS::CLS(const std::string& msg, int code): BASE(msg, code)                                     \
    {                                                                                               \
    }                                                                                               \
    CLS::CLS(const std::string& msg, const std::string& arg, int code): BASE(msg, arg, code)        \
    {                                                                                               \
    }                                                                                               \
    CLS::CLS(const std::string& msg, const CPooledException& exc, int code): BASE(msg, exc, code)   \
    {                                                                                               \
    }                                                                                               \
    CLS::CLS(const CLS& exc): BASE(exc)                                                             \
    {                                                                                               \
    }                                                                                               \
    CLS::~CLS() throw()                                                                                \
    {                                                                                               \
    }                                                                                               \
    CLS& CLS::operator = (const CLS& exc)                                                           \
    {                                                                                               \
        BASE::operator = (exc);                                                                     \
        return *this;                                                                               \
    }                                                                                               \
    const char* CLS::name() const throw()                                                           \
    {                                                                                               \
        return NAME;                                                                                \
    }                                                                                               \
    const char* CLS::className() const throw()                                                      \
    {                                                                                               \
        return typeid(*this).name();                                                                \
    }                                                                                               \
    CPooledException* CLS::clone() const                                                            \
    {                                                                                               \
        return new CLS(*this);                                                                      \
    }                                                                                               \
    void CLS::rethrow() const                                                                       \
    {                                                                                               \
        throw *this;                                                                                \
    }


FZUIM_DECLARE_EXCEPTION(RuntimeException, CPooledException)
FZUIM_DECLARE_EXCEPTION(NoThreadAvailableException, RuntimeException)
FZUIM_DECLARE_EXCEPTION(SystemException, RuntimeException)

#endif
/***************************************************************************** 
    *  @COPYRIGHT NOTICE 
    *  @Copyright (c) 2018, Fzuim 
    *  @All rights reserved 

    *  @file     : Exception.cpp 
    *  @version  : ver 1.0 

    *  @author   : Fzuim 
    *  @date     : 2018/8/20 10:39 
    *  @brief    : 异常类 
*****************************************************************************/
#include "stdafx.h"
#include "Exception.h"
#include <typeinfo>

CPooledException::CPooledException(int code): _pNested(0), _code(code)
{
}


CPooledException::CPooledException(const std::string& msg, int code): _msg(msg), _pNested(0), _code(code)
{
}


CPooledException::CPooledException(const std::string& msg, const std::string& arg, int code): _msg(msg), _pNested(0), _code(code)
{
    if (!arg.empty())
    {
        _msg.append(": ");
        _msg.append(arg);
    }
}


CPooledException::CPooledException(const std::string& msg, const CPooledException& nested, int code): _msg(msg), _pNested(nested.clone()), _code(code)
{
}


CPooledException::CPooledException(const CPooledException& exc):
    std::exception(exc),
    _msg(exc._msg),
    _code(exc._code)
{
    _pNested = exc._pNested ? exc._pNested->clone() : 0;
}


CPooledException::~CPooledException() throw()
{
    delete _pNested;
}


CPooledException& CPooledException::operator = (const CPooledException& exc)
{
    if (&exc != this)
    {
        delete _pNested;
        _msg     = exc._msg;
        _pNested = exc._pNested ? exc._pNested->clone() : 0;
        _code    = exc._code;
    }
    return *this;
}


const char* CPooledException::name() const throw()
{
    return "Exception";
}


const char* CPooledException::className() const throw()
{
    return typeid(*this).name();
}


const char* CPooledException::what() const throw()
{
    return name();
}


std::string CPooledException::displayText() const
{
    std::string txt = name();
    if (!_msg.empty())
    {
        txt.append(": ");
        txt.append(_msg);
    }
    return txt;
}


void CPooledException::extendedMessage(const std::string& arg)
{
    if (!arg.empty())
    {
        if (!_msg.empty()) _msg.append(": ");
        _msg.append(arg);
    }
}


CPooledException* CPooledException::clone() const
{
    return new CPooledException(*this);
}

void CPooledException::rethrow() const
{
    throw *this;
}

inline const CPooledException* CPooledException::nested() const
{
    return _pNested;
}


inline const std::string& CPooledException::message() const
{
    return _msg;
}


inline void CPooledException::message(const std::string& msg)
{
    _msg = msg;
}


inline int CPooledException::code() const
{
    return _code;
}

FZUIM_IMPLEMENT_EXCEPTION(RuntimeException, CPooledException, "Runtime exception")
FZUIM_IMPLEMENT_EXCEPTION(NoThreadAvailableException, RuntimeException, "No thread available")
FZUIM_IMPLEMENT_EXCEPTION(SystemException, RuntimeException, "System exception")

全局头文件包含 GlobalHead.h

#ifndef Fzuim_GlobalHead_INCLUDE
#define Fzuim_GlobalHead_INCLUDE

#include <iostream>
#include <Windows.h>
#include <assert.h>
#include <vector>
#include "Exception.h"

#endif

使用栗子

// Fzuim_ThreadPool.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "./ThreadPool/ThreadPool.h"
#include "./ThreadPool/RunnableAdapter.h"

class CTest
{
public:
    CTest(){};
    ~CTest(){};

    void Test()
    {
        try
        {
            CThreadPool pool;
            printf("allocate:%d\n", pool.GetAllocatedThreadNum());
            printf("available:%d\n", pool.GetAvailableThreadNum());

            CRunnableAdapter<CTest> ra(*this, &CTest::Proc);
            pool.Start(ra);
            pool.JoinAll();

            pool.AddMaxThreadNum(2);
            printf("allocate:%d\n", pool.GetAllocatedThreadNum());
            printf("available:%d\n", pool.GetAvailableThreadNum());
        }
        catch(...)
        {

        }
    }

    void Proc()
    {
        for (int i = 0; i < 10; ++i)
        {
            printf("%d===>%d\n", i, 10 - i);
        }
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    CTest test;
    test.Test();

    system("pause");

    return 0;
}

猜你喜欢

转载自blog.csdn.net/fzuim/article/details/82023240