日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

sigslot库源码分析

發(fā)布時間:2024/8/23 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 sigslot库源码分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

言歸正傳,sigslot是一個用標(biāo)準(zhǔn)C++語法實現(xiàn)的信號與槽機制的函數(shù)庫,類型和線程安全。提到信號與槽機制,恐怕最容易想到的就是大名鼎鼎的Qt所支持的對象之間通信的模式吧。不過這里的信號與槽雖然在概念上等價與Qt所實現(xiàn)的信號與槽,但是采用的僅僅是標(biāo)準(zhǔn)C++語法,不像Qt采用了擴展C++語言的方式(Qt需要使用moc工具對代碼預(yù)處理之后,才能由標(biāo)準(zhǔn)的C++編譯器進行編譯)。

眾所周知,C++是一門特性眾多的語言,其支持多種編程范式。雖然C++在一定程度上支持OOP編程,但是C++這種“靜態(tài)消息機制”的語言一直沒有實現(xiàn)對象級別的delegate機制,而C++之父Bjarne主張的“庫擴展勝于語言擴展”的做法使得各種解決方案層出不窮。除了信號與槽機制,C++11正式加入的std:bind/std::function組合也提供了優(yōu)秀的解決方案。這里所說的信號與槽機制也是一種對象間通信的機制,具體的討論也可以看看sigslot相關(guān)介紹中的內(nèi)容。

sigslot主頁:?http://sigslot.sourceforge.net

sigslot文檔:?http://sigslot.sourceforge.net/sigslot.pdf

sigslot?庫的用法文檔中已然很明了了,所以在這里就不贅述了。接下來我們看看這個庫的實現(xiàn)。源碼分析的方法有很多種,具體到庫代碼的分析的方法,我喜歡的是先研究庫的功能,直到能寫出一個demo程序為止。研究一個庫的前提是你得會用它,熟悉它的接口。讀完文檔,很容易就寫出了下面的測試代碼:

#include #include "sigslot.h"using namespace sigslot;class Switch { public:signal0<> clicked; };class Light : public has_slots<> { public:void turn_on(){std::cout << "Turn on ~" << std::endl;}};int main(int argc, char *argv[]) {Light lit1;Switch swh;swh.clicked.connect(&lit1, &Light::turn_on);swh.clicked.emit();return 0; }

使用方法很簡單。從這里我們就能看出來,這個庫無非就是在信號那一端保存了這個信號所綁定的函數(shù)指針,在槽函數(shù)這一端保存了其綁定的信號而已。接下來的問題實際上就是采用合理的數(shù)據(jù)結(jié)構(gòu)來處理問題了。

sigslot庫簡單到只有一個頭文件?sigslot.h?,打開后洋洋灑灑幾千行代碼,其實仔細看看絕大多數(shù)代碼都是為了適應(yīng)參數(shù)數(shù)量不同的成員函數(shù)指針的定義,為其擴展的模版代碼。從定義上看,這個庫支持?0~8?個參數(shù)的成員函數(shù)綁定。在紙上畫一下類的繼承關(guān)系,很容易就得到了如下的函數(shù)繼承圖(?IDE?有相關(guān)的工具也可以拿來用?~?)?:

從這個圖上看,其實代碼關(guān)系已經(jīng)很清晰了。?實現(xiàn)了槽函數(shù)的類需要繼承?has_slots?類。而?has_slots類?擁有一個?std::set<_signal_base<mt_policy>*>?類型的容器(所有的?mt_policy?其實是庫定義的三種鎖策略而已[單線程無鎖、多線程共享全局鎖、多線程局部鎖])。所有的?_signal_base[0-8]?的類持有各自的?std::list<_connection_base[0-8]<mt_policy?>?>?的list容器,而?_connection_base[0-8]?則分別封裝了0~8個參數(shù)的成員函數(shù)的指針。

這里的重復(fù)代碼是很多的,作為分析的話完全可以每中類代碼只留下一個,這樣所有的代碼就精簡到只有6個類了(反正別的也只是為了適應(yīng)參數(shù)個數(shù)寫的模版罷了,代碼除了參數(shù)個數(shù)外都是一樣的)。

至于前面說到的鎖,其實也只是因為C++ STL庫中的容器本身不是線程安全的,需要在外部加鎖。鎖的實現(xiàn)很平常,另外用C++ RAII手法封裝的lock_block類也是常見的用法。唯一需要注意的是,這個庫在使用了信號與槽的用戶類發(fā)生了拷貝構(gòu)造時,其信號與槽的綁定關(guān)系也會被拷貝,所以代碼中的類都自行編寫了相關(guān)的拷貝構(gòu)造函數(shù)。這里稍微解釋下,如果A類的a對象的x信號和B類的b1對象的y函數(shù)綁定,然后用b1初始化構(gòu)造b2(即 B b2(b1))。這時候,A類的a對象的x信號也會綁定到b2對象的y函數(shù)。這個特性我感覺有點莫名其妙,而且使得代碼復(fù)雜了不少(我覺得沒必要這么設(shè)計,用戶需要這個特性的話,自己再調(diào)用一次綁定函數(shù)就是了)。

知曉了基本的原理之后,看代碼就很容易了。比如在擁有信號和擁有槽函數(shù)的對象析構(gòu)時,會自動的取消掉之前的綁定,代碼很清晰易讀的。下面是我自己根據(jù)sigslot的原理,簡化出來的代碼,大家可以先看看然后去讀sigslot的源碼會簡單很多。

總結(jié)

以上是生活随笔為你收集整理的sigslot库源码分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。