博客 / 詳情

返回

Webrtc線程模型

webrtc的base的 thread,是我見過的封裝最帥的c++線程庫,根據比qt的還好用,發個例子給你

  using namespace webrtc;
    using namespace rtc;
    //std::cout<<"Thread::Current():" << Thread::Current()->GetId();
    //Thread::Current()->Start(); 不能調用start,因為不是我創建的,他已經開始了
    //Thread::Current()->Run(); //阻塞當前線程進入線程循環

    Thread * thread = new Thread();
    //MyRunnable run;
    //thread->Start(&run);//可以帶一個Runnable參數運行,運行完就結束,否則運行Thread::Run進入消息循環
    thread->Start();
    //std::cout << "Thread::Invoke():"<< thread->Invoke<bool>(RTC_FROM_HERE, &task)<< " at " << Thread::Current()->GetId() << std::endl;
    thread->Post(RTC_FROM_HERE, Bind(task2));//將最常用的
    auto  handler= new MessageClient;
    //thread->PostAt(RTC_FROM_HERE, (int64_t)3000,handler);
    //thread->PostDelayed(RTC_FROM_HERE, (int64_t)5000, handler);
    //thread->Stop();


    Thread * thread2 = new Thread();
    thread2->Start();
    thread2->Post(RTC_FROM_HERE, Bind(task2));//將最常用的
    //thread2->Invoke() 非常有用,在任何地方可以指定我的代碼運行在某個線程

    //api下的proxy機制,實際上就是設置要執行的線程,然後加鎖等待線程執行結果。這是我設計對外接口可以在任何線程調用而不出錯的常用方法

    //base的asyncinvoker與proxy類似的機制。

有ios的gdc,android的handler異曲同工

因為編寫複雜穩定的多線程C++項目實在太難,所以一個好的跨平台C++基礎庫是我最求的目標,目前比較欣賞的項目有:

Boost:大而全,缺少一些可以直接上手的東西如線程消息隊列,智能指針並非線程安全。
QT core:非常好
C++11:也需要線程消息隊列,線程安全智能指針。
chromium的base庫:太大了
當我看到webrtc的base時,非常驚訝的發現它正是我想要的,特點:

小:只有幾M
純:基於c++標準庫和各操作系統sdk
跨平台
對智能指針、線程、socket封裝非常好。
不斷更新(需要一直跟蹤官方代碼)
移植出來單獨使用,方案有三:

把源碼拷貝出來用通用的編譯工具(makefile,cmake,qmake)管理。(makefile較複雜,cmake簡單,qmake最簡單)
把源碼拷貝出來用基於自帶的gn管理
在webrtc項目裏面編譯和合並需要的靜態庫和pdb

因為google官方説了:引用計數+引用計數的智能化(scoped_ref_ptr)+弱引用就可以解決問題。
shared_ptr不是線程安全的,因為shared_ptr有兩個成員:引用計數,和源對象指針。沒辦法對兩個成員同時實現原子操作。
但unique_ptr是個好東西

智能指針的使用:

  1. 不用再使用delete。
  2. 儘量使用unique_ptr。
  3. 多個線程讀寫同一個 shared_ptr 對象,那麼需要加鎖。
  4. shared_ptr 和weak_ptr配合解決循環引用的問題。

weak_ptr必須,oc,swift的ViewControler和控件都是weak關係

內存管理模型的三種級別:
1 手動內存管理(c/c++的malloc與free,new與delete):容易出錯。
2 自動內存管理(oc的arc,c++的智能指針,scoped_ptr):存在循環引用問題,通過程序員自己管理強弱引用關係解決。
3 垃圾回收機制(如java,python):後台GC降低了程序效率,好的程序員仍然好考慮java的強引用[表情]引用/軟引用/

3 線程模型
1 生產者消費模型(mutex,condition):最最常用的模型。
2 線程池模型:解決大量請求分配太多線程的問題。比如一個android和ios的app,http請求會很多很多。
3 (着重強調)串行模型:ios有GCD(Grand Central Dispatch,global queue是線程池),android有looper, win32有PostMessage,boost有strand
讀寫鎖:特別只有寫才會不安全的情況。
再結合其他的手段會讓程序簡潔優美易讀:java的handler,oc的delegate和block、swift的閉包,mvc模式 ,c++的function/bind/lambda,python和javascript的function

而串行模型就成了解決這類多線程問題的首選,就是線程消息模型。
在android 系統裏面,無數這樣的例子。

模塊處理線程

Call構造方法中創建module_process_thread與pacer_thread兩個ProcessThread.接着為module_process_thread註冊CallStats, ReceiveSideCongestionController, SendSideCongestionController模塊,為pacer_thread註冊PacedSender, RemoteBitrateEstimator模塊.

Call::CreateVideoSendStream創建VideoSendStream時,將module_process_thread做構造參數傳入,調用RegisterProcessThread方法,註冊所有的rtc_rtcp模塊到module_process_thread線程.同樣的為VideoReceiveStream中設置.

user avatar philadelphia 頭像 11pmsleep 頭像 yunwei37 頭像
3 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.