• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牽著老婆滿街逛

            嚴以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            libjingle翻譯之《Important Concepts(重要概念)之Threads(線程)》

            轉載自:http://blog.csdn.net/night_cat/article/details/3496797

            Threads(線程)

             

            libjingle 考慮到使用到此庫的應用程序的性能,libjingle內部支持多線程。其內組件使用12個全局線程:

             signaling thread  被用作創建底層(基礎)組件,

                例如:Session Management,Control,XMPP Messaging組件。

             worker thread  ( 有時稱作channel thread)用來集中處理p2p組件中的對象提交過來的大量資源,例如:數據流。之所以這樣用另外的線程單獨處理,是為了避免數據流阻塞或被XMPP/用戶界面組件阻塞。使用 worker thread的類包括ChannelManage,SocketMonitor,P2PTransportChannel 和 屬于Port類的對象。

            若起用worker thread,使之工作,在應用中必須創建一個Thread類對象,并把此對象當作SessionManager的構造函數的參數。(如果SessionManager類對象在創建時,沒有傳遞給它Thread對象,則SessionManager類將在內部創建一個線程,當作worker thread)CallClient::InitPhone示范了如何為底層組件(low-level components)創建一個worker thread方法。

             

            另外、libjingle提供了一個基類SignalThread。擴展此類可以讓一個擴展類對象存在于它自身代表的線程,此擴展類對象可以被實例化,啟動,單獨離開,結束時自釋放。更多信息請查看signalthread.h/cc

             

            注意:盡管libjingle支持多線程,但是只有幾個函數通過呼叫方線程的驗證來支持線程安全,并且極少函數做了線程鎖定。下面的片斷示范了在函數中如何安全地呼叫線程(或線程安全地被呼叫):

            // Check that being called from the channel (e.g., worker) thread.

            ASSERT(talk_base::Thread::Current() == channel_thread_);

            channel_thread_->Clear(this);

             

            libjingle中用到的所有線程,signaling threadworker thread,其它的一些線程,都是talk_base::Thread的對象(或子類的對象)。所有的Thread對象都被ThreadManager管理,當被請求時,ThreadManager會返回這些Thread對象。SessionManager被創建時通過調用ThreadManager::CurrentThread得到一個signal thread(當無worker thread 傳遞給SessionManager構造函數時,同時得到一個work thread)XmppPump類把當前線程當作它的signal thread來用(XmppPump uses the current thread for its signaling thread)。所以,應用程序必須為signal thread創建一個Thread對象(或其子類對象),并在SessionManager對象創建之前或在XmppPump工作之前,把此對象放進ThreadManager的線程池里。(Signing In to a Server(登錄服務器) 有示例)有兩種方法創建一個Thread對象:

            AutoThread    這種方式就是libjingleThread對象包裝一個操作系統中的線程,并把它當作ThreadManager線程池里的當前線程(當然,Thread::CurrentThread()被調用時,此線程會被提取出來)。

            Thread   這種方式將創建一個新線程并用Thread類包裝,比較典型就是的創建worker thread。使此線程發生作用,應用程序必須新創建一個Thread對象,調用ThreadManager::Add()ThreadManager::SetCurrent()把它丟進線程池里,并且調用Run()使之在阻塞狀態下運行或調用Start()使之處于監聽狀態。

             

            線程為對象間或對象內部的消息溝通提供了“管道”()。例如:SocketManager可以通過其它線程向自己發送銷毀一個套接字的消息,或當鏈接候選被產生時向SessionManager發送消息。Thread繼承自MessageQueue,所以Thread的對象具有了SendPost,和一些同步或異步發送消息的函數。如果要使一個對象能夠接收到MessageQueue送出的消息,那么此對象必須繼承和實現MessageHandlerMessageHandler定義了一個OnMessage函數,此函數在MessageQueue送出消息時被調用,用來接收MessageQueue送出的消息。

             

            你可以通過任何線程向繼承自talk_base::MessageHandler的任何對象發送消息。盡管能夠做到,如果你發出的消息是為了集中處理大量的數據,應用程序應該通過worker thread。調用SessionManager::worker_thread()可以得到worker thread的句柄。

            調用Session::Manager::signaling_thread()可以得到 signaling thrread的句柄。

             

            對象使用一個指定的線程有如下幾種方式:

                   對象要求一個線程指針作輸入參數,并儲存這個指針。

                   對象在創建時取得當前線程(構造函數中調用ThreadManager::CurrentThread()取得),把取得的線程存進對象內部成員變量引用它,一般應用于獲取特定的線程。(it can assume that the current thread when it is created (accessed byThreadManager::CurrentThread in its constructor) is a particular thread and cache a member pointer to it

                   對象調用SessionManger::signal_thread()  SessionManager::worker_thread()獲取線程。

                   以上三種方法,libjingle均有用到。

             

            因為一個對象可以被任意線程使用,對象可能需要驗證當前調用是來自哪個線程的方法。應用可以調用Thread::Current()得到當前線程的句柄,然后與對象內部保存線程的數據成員進行比較,此數據成員的值可以是從SessionManager中暴露在外面的線程,或是對象在創建時通過構造函數傳進去的初始化值。

            這是一個對象通過其它線程調用自身函數時而廣范使用的范例:

            // Note that worker_thread_ is not initialized until someone 
            // calls PseudoTcpChannel::Connect
            // Also note that this method *is* thread-safe. 
            bool PseudoTcpChannel::Connect(const std::string& channel_name) {
              ASSERT(signal_thread_->IsCurrent());
              CritScope lock(&cs_);
                if (channel_)
                  return false;
                ASSERT(session_ != NULL);
                worker_thread_ = session_->session_manager()->worker_thread();
            ...
            }
             
            void PseudoTcpChannel::SomeFunction(){
              ...
              // Post a message to yourself over the worker thread.
              worker_thread_->Post(this, MSG_PING); // <- Goes in here....
              ...
            }
             
            // Handle queued requests.
            void PseudoTcpChannel::OnMessage(Message *pmsg) {
              if (pmsg->message_id == MSG_SORT)
                OnSort();
              else if (pmsg->message_id == MSG_PING) // -> And comes out here!
                // Check that we're in the worker thread before proceding.
                ASSERT(worker_thread_->IsCurrent());
                OnPing();
              else if (pmsg->message_id == MSG_ALLOCATE)
                OnAllocate();
              else
                assert(false);
            }



            posted on 2013-09-01 16:29 楊粼波 閱讀(483) 評論(0)  編輯 收藏 引用

            久久精品国产精品青草app| 99久久久久| 久久国产精品免费一区二区三区| 伊人久久大香线蕉av不变影院| 欧美精品丝袜久久久中文字幕| 久久久久久噜噜精品免费直播| 久久综合丁香激情久久| 日本久久久精品中文字幕| 91久久精一区二区三区大全| 99久久久精品免费观看国产| 精品久久久无码人妻中文字幕豆芽| 亚洲国产精品无码久久SM| 日韩久久久久久中文人妻| 亚洲综合伊人久久综合| 亚洲va久久久噜噜噜久久男同| 久久午夜羞羞影院免费观看| av午夜福利一片免费看久久| 国产一区二区三区久久| 精品久久久久久国产牛牛app| 久久久久亚洲精品男人的天堂| 久久无码一区二区三区少妇| 久久久SS麻豆欧美国产日韩| 国产麻豆精品久久一二三| 久久精品国产亚洲沈樵| 久久久久国产精品三级网| 99久久综合国产精品免费| 99久久99久久精品免费看蜜桃| 99久久精品免费国产大片| 中文国产成人精品久久亚洲精品AⅤ无码精品 | 久久久久国产精品嫩草影院| 久久久久久亚洲精品成人 | 国内精品久久久久久99| 国产亚洲婷婷香蕉久久精品| 色婷婷久久久SWAG精品| 97久久香蕉国产线看观看| 久久午夜综合久久| 人妻精品久久无码区| 久久天天躁狠狠躁夜夜2020老熟妇 | 欧美牲交A欧牲交aⅴ久久| 久久精品无码一区二区三区免费| 精产国品久久一二三产区区别|