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是個好東西
智能指針的使用:
- 不用再使用delete。
- 儘量使用unique_ptr。
- 多個線程讀寫同一個 shared_ptr 對象,那麼需要加鎖。
- 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中設置.