日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Iperf 源代碼分析(二)

 MikeDoc 2012-06-13
轉自: http://blog.csdn.net/willon_tom/article/details/4470197
Thread類
 
Thread類封裝了POSIX標準中的多線程機制,提供了一種簡單易用的線程模型。Thread類是Iperf的實現(xiàn)中比較重要的類,使Iperf實現(xiàn)多線程并行操作的核心。
Thread類的定義在文件lib/Thread.hpp中,其實現(xiàn)位于lib/Thread.cpp中。
/* ------------------------------------------------------------------- */
class Thread {
public:
    Thread( void );
    virtual ~Thread();
    // start or stop a thread executing
    void Start( void );
    void Stop( void );
    // run is the main loop for this thread
    // usually this is called by Start(), but may be called
    // directly for single-threaded applications.
    virtual void Run( void ) = 0;
    // wait for this or all threads to complete
    void Join( void );
    static void Joinall( void );
    void DeleteSelfAfterRun( void ) {
        mDeleteSelf = true;
    }
    // set a thread to be daemon, so joinall won't wait on it
    void SetDaemon( void );
    // returns the number of user (i.e. not daemon) threads
    static int NumUserThreads( void ) {
        return sNum;
    }
    static nthread_t GetID( void );
    static bool EqualID( nthread_t inLeft, nthread_t inRight );
    static nthread_t ZeroID( void );
protected:
    nthread_t mTID;
    bool mDeleteSelf;
    // count of threads; used in joinall
    static int sNum;
    static Condition sNum_cond;
private:
    // low level function which calls Run() for the object
    // this must be static in order to work with pthread_create
    static void*        Run_Wrapper( void* paramPtr );
}; // end class Thread
數(shù)據(jù)成員說明:
mTID紀錄本線程的線程ID;
mDeleteSelf通過方法DeleteSelfAfterRun設置,用來說明是否在線程結束后釋放屬于該現(xiàn)程的變量;
sNum是一個靜態(tài)變量,即為所有的Thread實例所共有的。該變量紀錄所生成的線程的總數(shù)。Thread對象的Joinall方法通過該變量判斷所有的Thread實例是否執(zhí)行結束;
sNum_cond是用來同步對sNum的操作的條件變量,也是一個靜態(tài)變量。
 
主要函數(shù)成員說明:

Start方法:
/* -------------------------------------------------------------------
 * Start the object's thread execution. Increments thread
 * count, spawns new thread, and stores thread ID.
 * ------------------------------------------------------------------- */
void Thread::Start( void ) {
    if ( EqualID( mTID, ZeroID() ) ) {
        // increment thread count
        sNum_cond.Lock();
        sNum++;
        sNum_cond.Unlock();
        Thread* ptr = this;
        // pthreads -- spawn new thread
        int err = pthread_create( &mTID, NULL, Run_Wrapper, ptr );
        FAIL( err != 0, "pthread_create" );
    }
} // end Start
首 先通過Num++紀錄一個新的線程的產(chǎn)生,之后通過pthread_create系統(tǒng)調用產(chǎn)生一個新的線程。新線程執(zhí)行Run_Wrapper函數(shù),以至 向該Thread實例的ptr指針作為參數(shù)。原線程在判斷pthread_create是否成功后退出Start函數(shù)。
 
Stop方法:
/* -------------------------------------------------------------------
 * Stop the thread immediately. Decrements thread count and
 * resets the thread ID.
 * ------------------------------------------------------------------- */
void Thread::Stop( void ) {
    if ( ! EqualID( mTID, ZeroID() ) ) {
        // decrement thread count
        sNum_cond.Lock();
        sNum--;
        sNum_cond.Signal();
        sNum_cond.Unlock();
        nthread_t oldTID = mTID;
        mTID = ZeroID();
        // exit thread
        // use exit()   if called from within this thread
        // use cancel() if called from a different thread
        if ( EqualID( pthread_self(), oldTID ) ) {
            pthread_exit( NULL );
        } else {
            // Cray J90 doesn't have pthread_cancel; Iperf works okay without
            pthread_cancel( oldTID );
        }
    }
} // end Stop
首先通過sNum--紀錄一個線程執(zhí)行結束,并通過sNum_cond的Signal方法激活此時wait在 sNum_cond的線程(某個主線程會調用調用Joinall方法,等待全部線程的結束,在Joinall方法中通過sNum_cond.Wait() 等待在sNum_cond條件變量上)。若結束的線程是自身,則調用pthread_exit函數(shù)結束,否則調用pthread_cancel函數(shù)。注 意:傳統(tǒng)的exit函數(shù)會結束整個進程(即該進程的全部線程)的運行,而pthread_exit函數(shù)僅結束該線程的運行。
 
Run_Wrapper方法:
/* -------------------------------------------------------------------
 * Low level function which starts a new thread, called by
 * Start(). The argument should be a pointer to a Thread object.
 * Calls the virtual Run() function for that object.
 * Upon completing, decrements thread count and resets thread ID.
 * If the object is deallocated immediately after calling Start(),
 * such as an object created on the stack that has since gone
 * out-of-scope, this will obviously fail.
 * [static]
 * ------------------------------------------------------------------- */
void*
Thread::Run_Wrapper( void* paramPtr ) {
    assert( paramPtr != NULL );
    Thread* objectPtr = (Thread*) paramPtr;
    // run (pure virtual function)
    objectPtr->Run();
#ifdef HAVE_POSIX_THREAD
    // detach Thread. If someone already joined it will not do anything
    // If noone has then it will free resources upon return from this
    // function (Run_Wrapper)
    pthread_detach(objectPtr->mTID);
#endif
    // set TID to zero, then delete it
    // the zero TID causes Stop() in the destructor not to do anything
    objectPtr->mTID = ZeroID();
    if ( objectPtr->mDeleteSelf ) {
        DELETE_PTR( objectPtr );
    }
    // decrement thread count and send condition signal
    // do this after the object is destroyed, otherwise NT complains
    sNum_cond.Lock();
    sNum--;
    sNum_cond.Signal();
    sNum_cond.Unlock();
    return NULL;
} // end run_wrapper
該方法是一個外包函數(shù)(wrapper),其主要功能是調用本實例的Run方法。實際上, Run_Wrapper是一個靜態(tài)成員函數(shù),是為所有的Thread實例所共有的,因此無法使用this指針。調用Run_Wrapper的Thread 是通過參數(shù)paramPtr指明具體的Thread實例的。在Run返回之后,通過pthread_detach使該線程在運行結束以后可以釋放資源。 Joinall函數(shù)是通過監(jiān)視sNum的數(shù)值等待所有線程運行結束的,而并非通過pthread_join函數(shù)。在完成清理工作后, Run_Wrapper減少sNum的值,并通過sNum_cond.Signal函數(shù)通知在Joinall中等待的線程。
Run方法:
從Run方法的聲明中知道,該方法是一個純虛函數(shù),因此Thread是一個抽象基類,主要 作用是為其派生類提供統(tǒng)一的對外接口。在Thread的派生類中,像Iperf中的Server,Client,Speader,Audience, Listener等類,都會為Run提供特定的實現(xiàn),完成不同的功能,這是對面向對象設計多態(tài)特性的運用。Thread函數(shù)通過Run方法提供了一個通用 的線程接口。
 
討論: 為什么要通過Run_Wrapper函數(shù)間接的調用Run函數(shù)?
首先,Thread的各派生類的完成的功能不同,但它們都是Thread的實例,都有一些相同的工作要做,如初始化和清理等。在Run_Wrapper中實現(xiàn)這些作為Thread實例所應有的相同功能,在Run函數(shù)中實現(xiàn)派生類各自不同的功能,是比較合理的設計。
更重要的是,由于要通過Pthread_create函數(shù)調用Run_Wrapper函數(shù),因此 Run_Wrapper函數(shù)必須是一個靜態(tài)成員,無法使用this指針區(qū)分運行Run_Wrapper函數(shù)的具體實例,也就無法利用多態(tài)的特性。而這個問 題可以通過把this指針作為Run_Wrapper函數(shù)的參數(shù),并在Run_Wrapper中顯示調用具有多態(tài)特性的Run函數(shù)來解決。
這種使用一個wrapper函數(shù)的技術為我們提供了一種將C++面向對象編程和傳統(tǒng)的Unix系統(tǒng)調用相結合的思路。
 
Joinall方法和SetDaemon方法:
/* -------------------------------------------------------------------
 * Wait for all thread object's execution to complete. Depends on the
 * thread count being accurate and the threads sending a condition
 * signal when they terminate.
 * [static]
 * ------------------------------------------------------------------- */
void Thread::Joinall( void ) {
    sNum_cond.Lock();
    while ( sNum > 0 ) {
        sNum_cond.Wait();
    }
    sNum_cond.Unlock();
} // end Joinall
/* -------------------------------------------------------------------
 * set a thread to be daemon, so joinall won't wait on it
 * this simply decrements the thread count that joinall uses,
 * which is not a thorough solution, but works for the moment
 * ------------------------------------------------------------------- */
void Thread::SetDaemon( void ) {
    sNum_cond.Lock();
    sNum--;
    sNum_cond.Signal();
    sNum_cond.Unlock();
}
由這兩個方法的實現(xiàn)可見,Thread類是通過計數(shù)器sNum監(jiān)視運行的線程數(shù)的。線程開始前(Start方法 中的pthread_create)sNum加一,線程結束后(Stop方法和Run_Wrapper方法末尾)sNum減一。Joinall通過條件變 量類的實例sNum_cond的Wait方法等待sNum的值改變。而SetDaemon的目的是使調用線程不再受主線程Joinall的約束,只是簡單 的把sNum減一就可以了。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多