程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 不到300行的簡單線程池C++實現

不到300行的簡單線程池C++實現

編輯:C++入門知識

///////////////// 頭文件 Thread.h//////////////////////////////


/**************
    Multi-threading-related Classes
    
    2011-11-03 Add By AYA
        Support Windows platform only
 
 **************/ 
#ifndef THREAD_H_2011_11_03 
#define THREAD_H_2011_11_03 
#include <list> 
#include <string> 
#ifdef WIN32 
#include <windows.h> 
#endif 
 
 
class ThreadException { 
public: 
    ThreadException (const char* msg)  
        : mMsg (msg) { 
    } 
 
    const char* what () const { 
        return mMsg.c_str (); 
    } 
private: 
    std::string mMsg; 
}; 
 
 
 
///////////////// Lock & LockGuide ////////////////////////////// 
class Lock { 
public: 
    Lock (); 
    ~Lock (); 
 
public: 
    void Enter (); 
    void Leave (); 
 
 
private: 
    CRITICAL_SECTION mSection; 
}; 
 
 
class LockGuide { 
public: 
    LockGuide (Lock& _Lock) 
        :mLock (_Lock) { 
            mLock.Enter(); 
    } 
 
    ~LockGuide () { 
        mLock.Leave (); 
    } 
 
private: 
    Lock& mLock; 
}; 
 
 
/////////////// Signal /////////////////////////////// 
class Signal { 
public: 
    Signal (); 
    ~Signal (); 
 
public: 
    bool Wait (unsigned int Timeout = INFINITE); 
    void WakeUp (); 
 
private: 
    HANDLE mHandle; 
}; 
 
 
////////////// Job ///////////////////////////////// 
 
class Job { 
public: 
    virtual void Do () = 0; 
}; 
 
 
 
///////////////// Thread /////////////////////////// 
class Thread { 
    friend class ThreadPool; 
public: 
    Thread (ThreadPool& Pool); 
    virtual ~Thread (); 
 
public: 
    void Attach (Job* _Job); 
 
private: 
    /// Only called by ThreadPool 
    void Die (); 
 
private: 
    static DWORD WINAPI Routine (LPVOID Parameter); 
 
private: 
    DWORD           mThreadID; 
    HANDLE          mHandle; 
    Lock            mLock; 
    Signal          mSignal; 
    Signal          mDieSignal; 
    Job*            mCurrJob; 
    ThreadPool&     mPool; 
    bool            mIsDie; 
}; 
 
 
 
///////////////// ThreadPool ///////////////////////// 
class ThreadPool { 
    friend class Thread; 
public: 
    ThreadPool (); 
    ~ThreadPool (); 
 
public: 
    bool Alloc (unsigned int ThreadNum); 
    bool IsBusy (); 
    void Release (); /// WARNING: ALL THREADS MUST BE IDLE BEFORE RELEASE THE POOL! 
    Thread* Get (); 
     
 
private: 
    /// Only called by Thread 
    void Put (Thread* _Thread); 
 
 
private: 
    Lock mKeeper; 
    std::list<Thread*> mIdleThreads; 
    std::list<Thread*> mBusyThreads; 
}; 
 
 
#endif 

/////////////////////實現 Thread.cpp///////////////////////////////////////

#include "Thread.h" 
 
Lock::Lock() 

    InitializeCriticalSection (&mSection); 

 
Lock::~Lock() 

    DeleteCriticalSection (&mSection); 

 
void 
Lock::Enter() 

    EnterCriticalSection (&mSection); 

 
void  
Lock::Leave() 

    LeaveCriticalSection (&mSection); 

 
 
 
#undef  _CLASS_ 
#define _CLASS_ "Signal" 
 
Signal::Signal() 

    mHandle = CreateSemaphore (NULL, 0, 1, NULL); 
    if (!mHandle) { 
        throw ThreadException ("CreateSemaphore Failed"); 
    } 

 
 
Signal::~Signal() 

    CloseHandle (mHandle); 

 
 
bool  
Signal::Wait (eolas_uint Timeout) 

    if (WAIT_OBJECT_0 != WaitForSingleObject(mHandle, Timeout)) { 
        return false; 
    } 
    return true; 

 
 
void 
Signal::WakeUp () 

    if (!ReleaseSemaphore(mHandle, 1, NULL)) { 
        throw ThreadException ("ReleaseSemaphore Failed"); 
    } 

 
 
 
 
#undef  _CLASS_ 
#define _CLASS_ "Thread" 
 
 
Thread::Thread(ThreadPool& Pool) 
:mPool (Pool), 
 mThreadID (0), 
 mCurrJob (NULL), 
 mIsDie (false) 

    mHandle = CreateThread ( 
        NULL, 
        0, 
        Routine, 
        this, 
        0, 
        &mThreadID 
        ); 
    if (NULL == mHandle) { 
        throw ThreadException ("CreateThread Failed"); 
    } 

 
Thread::~Thread() 


 
 
void  
Thread::Attach (Job* _Job) 

    LockGuide Guide (mLock); 
 
    mCurrJob = _Job; 
    mSignal.WakeUp(); 

 
 
void  
Thread::Die() 

    mLock.Enter(); 
 
    mIsDie = true; 
    mSignal.WakeUp(); 
    mLock.Leave(); 
    mDieSignal.Wait(); 
 

 
 
DWORD  
Thread::Routine (LPVOID Parameter) 

    Thread* _Thread = static_cast <Thread*> (Parameter); 
    while (true) { 
        _Thread->mSignal.Wait(); 
 
        /// 檢查線程是否需要退出 
        _Thread->mLock.Enter(); 
        if (_Thread->mIsDie) { 
            _Thread->mLock.Leave(); 
            break; 
        } 
        _Thread->mLock.Leave(); 
 
        /// 干活 
        _Thread->mCurrJob->Do(); 
 
 
        /// 干完活,回到IDLE狀態 
        _Thread->mLock.Enter(); 
        _Thread->mCurrJob = NULL; 
        _Thread->mPool.Put (_Thread); 
        _Thread->mLock.Leave(); 
 
    } 
 
    _Thread->mDieSignal.WakeUp(); 
    return 0; 

 
 
 
 
#undef  _CLASS_ 
#define _CLASS_ "ThreadPool" 
 
 
ThreadPool::ThreadPool() 


 
ThreadPool::~ThreadPool() 

    Release(); 

 
 
bool  
ThreadPool::Alloc (unsigned int ThreadNum) 

    LockGuide Guide(mKeeper); 
    try { 
        for (unsigned int N = 0; N < ThreadNum; ++N) { 
            mIdleThreads.push_back(new Thread (*this)); 
        } 
    } catch (const ThreadException& e) { 
        return false; 
    } 
    return true; 

 
 
void  
ThreadPool::Release() 

    LockGuide Guide(mKeeper); 
 
    /// 編程上的要求: 
    /// 釋放線程池之前必須先讓所有Thread進入Idle狀態 
    /// 這樣才不用強制Kill掉線程 
    assert(mBusyThreads.empty()); 
 
    while (!mIdleThreads.empty()) { 
        Thread* _Thread = mIdleThreads.front(); 
        _Thread->Die(); 
        delete _Thread; 
        mIdleThreads.pop_front(); 
    } 

 
 
Thread*  
ThreadPool::Get() 

    LockGuide Guide (mKeeper); 
    if (!mIdleThreads.empty()) { 
        Thread* _Thread = mIdleThreads.front(); 
        mIdleThreads.pop_front(); 
        mBusyThreads.push_back(_Thread); 
        return _Thread; 
    } 
    return NULL; 

 
 
void  
ThreadPool::Put (Thread* _Thread) 

    LockGuide Guide (mKeeper); 
    mBusyThreads.remove(_Thread); 
    mIdleThreads.push_back(_Thread); 

 
bool  
ThreadPool::IsBusy() 

    LockGuide Guide (mKeeper); 
    return !mBusyThreads.empty(); 


摘自 最大的敵人是自己

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved