五月天青色头像情侣网名,国产亚洲av片在线观看18女人,黑人巨茎大战俄罗斯美女,扒下她的小内裤打屁股

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

uvw 源碼閱讀

2022-09-11 12:51 作者:Meriex  | 我要投稿

這一部分開始我們再接觸一個新庫叫做 uvw ,那這個庫的話只看介紹就比較令人激動了

uvw started as a header-only, event based, tiny and easy to use wrapper for libuv written in modern C++.

Now it's finally available also as a compilable static library.

uvw 最初是一個 header only 的庫,通過現(xiàn)代 C++ 封裝了 libuv 的功能,基于事件驅(qū)動(event based),精巧且易于使用 現(xiàn)在同時支持編譯為 static 靜態(tài)庫使用

libuv 的話是屬于名氣比較高的一個基于事件驅(qū)動的異步 I/O 庫,和 libeventlibev 互為替代品,功能的話主要就是負責維護一個隊列,那在這個隊列上你可以注冊自己感興趣的事件同時添加一個回調(diào)函數(shù)(比如添加一個定時任務(wù),回調(diào)設(shè)置為一個需要定期執(zhí)行的函數(shù)),那么當事件發(fā)生時(定時任務(wù)到期觸發(fā))就會調(diào)用之前注冊的回調(diào)函數(shù)。這個概念應(yīng)該比較好理解,尤其是之前對 epoll 有了解的話。

首先還是看一下基本的用例:

這段代碼就有很大的信息量了,一起來讀一下。首先看 main 函數(shù),通過 uvw::Loop::getDefault 創(chuàng)建了一個事件循環(huán),接著調(diào)用 listenconn 并傳入 loop ,最后執(zhí)行 loop->run() 。

暫時跳過創(chuàng)建事件循環(huán)的方法,接著看下 listenconn 中做了什么,先來看 listen

首先創(chuàng)建了一個 uvw::TCPHandle ,那從類型名字不難猜出是用來處理 tcp 事件的,同時說明 libuv 所處理的事件類型應(yīng)該是有限制的,那不知道可不可以通過繼承某個類去做自定義的 Handle , 接著是 tcp->once<uvw::ListenEvent>(); 應(yīng)該是注冊了一個只執(zhí)行一次的事件并設(shè)置回調(diào)函數(shù)為一個 lambda 函數(shù),也就是在接收到客戶端的連接請求后注冊兩個事件 CloseEventEndEvent ,接著 accept 客戶端請求,并嘗試讀取客戶端 socket。

事件注冊完成后通過 bind 設(shè)置 IP 和端口并正式開始 listen ,當然這里不太確定機制,也有可能是等到 loop->run 再開始做?

不管怎樣我們接著看 conn 的實現(xiàn):

這里同樣是拿了 uvw::TCPHandle ,這樣看的話可能 tcp 是單例模式所以拿到的都是同一個?接著也是注冊了兩個事件,一個是用于錯誤處理,而另外一個是在連接建立成功后直接寫一個 "bc" 然后關(guān)閉 socket 的一次性事件。

接著調(diào)用 tcp->connect 去嘗試連接 4242 端口,這個端口就是我們剛剛監(jiān)聽的端口,那上面理解有一些偏差,兩個函數(shù)中的 tcp 并不是同一個,這里 listen 實際上扮演了 server 的角色去監(jiān)聽端口并嘗試讀取內(nèi)容, conn 則扮演了 client 的角色,主動連接并發(fā)送內(nèi)容。

現(xiàn)在還剩余一個疑問就是 listen 、 connectloop->run() 的執(zhí)行順序,這里先行保留。

接著來看看 uvw::Loop::getDefault() 的實現(xiàn):

這里返回了 std::shared_ptr<Loop> ,那也就不難解釋之前傳參時候為什么都使用 *loop 了,接著這里使用 static std::weak_ptr<Loop> 做了一個單例的實現(xiàn),如果 ref 沒有指向的對象或者對象已經(jīng)銷毀那么通過 uv_default_loop 生成一個默認事件循環(huán),否則通過 ref.lock() 獲取一個 std::shared_ptr<Loop> 返回。

這里的代碼存在一點問題,一般我們做一個單例的實現(xiàn)的時候都需要用一些手段確保它是線程安全的,那這里的話就可能出現(xiàn)兩個線程同時調(diào)用時因為還沒有實例化因此兩個線程一起進入 if(ref.expired()) 分支的情況。如果要確保線程安全的話代碼類似這樣:

這里我們使用一個鎖保證了任務(wù)執(zhí)行的先后順序,當?shù)谝粋€執(zhí)行函數(shù)的線程實例化 Loop 完成并返回后第二個線程才能嘗試獲取。

接著這里 uv_default_loop 應(yīng)該是 libuv 的函數(shù),返回一個 uv_loop_t* 類型的 def , 接著把這個指針放到 unique_ptr 中去管理卻給了一個空的自定義 Deleter,這里應(yīng)該是要交給其他地方去釋放。接著把指針移交給 shared_ptr<Loop> 管理,我們來簡單看一下 Loop 的構(gòu)造函數(shù):

這里就是接受一個 std::unique_ptr<uv_loop_t, Deleter> 類型的指針也就是我們剛剛生成并包裝的 def ,直接給到Loop::loop 沒有做額外動作。

順便看一下析構(gòu)函數(shù):

那這里可以看到也確實是交還給 libuv 去關(guān)閉了。

那么本節(jié)內(nèi)容就到這里,下一節(jié)我們一起看一下 loop->run() 的實現(xiàn)。

下次再會!


uvw 源碼閱讀的評論 (共 條)

分享到微博請遵守國家法律
江都市| 昌吉市| 肥西县| 栾川县| 马山县| 阳东县| 东台市| 都兰县| 江口县| 绥德县| 西乌珠穆沁旗| 藁城市| 佛冈县| 抚顺县| 个旧市| 文水县| 上饶县| 舞钢市| 海安县| 龙口市| 衡阳县| 谢通门县| 丰宁| 普洱| 阳城县| 陈巴尔虎旗| 潞西市| 西乡县| 阿拉尔市| 新源县| 织金县| 荥经县| 马鞍山市| 福鼎市| 光泽县| 阿拉善左旗| 普宁市| 肥东县| 九江市| 宽甸| 西平县|