【仿muduo庫實現并發服務器】LoopThreadPool模塊

仿muduo庫實現并發服務器

  • 1.LoopThread模塊
    • 1.1成員變量
    • 1.2構造函數
    • 13線程入口函數
    • 1.4獲取eventloop對象GetLoop()
  • 2.LoopThreadPool模塊
    • 2.1成員變量
    • 2.2構造函數
    • 2.3配置線程數量
    • 2.4按照配置數量創建線程
    • 2.5依次分配Eventloop對象

1.LoopThread模塊

這個模塊是為了將EventLoop與線程整合起來。一個EventLoop對應一個線程。
要知道EventLoop對象實例化時就會將它的thread_id綁定,然后后續的RuninLoop操作里面就會判斷當前執行流的線程id與eventloop對應的線程id進行比較,如果相同就說明是同一個線程,如果不相同,就說明不是同一個線程執行。

這里要注意的是:
eventloop對象的實例化必須在線程創建之后,也就是在線程的入口函數中進行創建,然后eventloop對象一創建出來就綁定該線程。

就是構造一個新的模塊,它在里邊既有線程又有eventloop,而且它是先有線程然后在線程里邊再去實例化eventlop,這樣就能夠保證eventloop在出現的第一時刻就跟我們的一個線程是綁定到一起的。

【獲取eventloop對象】
這個模塊,它將線程跟eventloop給整合到一起了,那么問題就來了,那當我們外界說一個新連接到來了,現在要給它分配一個eventloop對象,怎么給它分配呢?我總得能夠獲取到這個evetloop對象吧,所以在這個里邊我們需要提供一個接口叫做GetLoop,獲取到eventloop對象的指針。
那么當外界可以獲取到這個eventloop對象指針之后,當新連接到來時,就可以將該線程的eventloop分配給該線程,該連接它就綁定在該eventloop對應的線程上工作。
比如在執行各種操作的時候,進行事件監控的時候,它就會綁定到我們eventloop對應的線程里邊去,要進行某些操作的時候也是把任務壓入到我們對eventloop,它的任務隊列里邊。

【獲取evnetloop同步問題】
要避免當我們的線程剛創建起來之后,還沒來得及實例化創建eventloop該對象的時候,這時候外界如果要獲取該線程的eventloop,調用Getloop操作時,獲取到的就為空。所以這里存在一個同步問題,也就是從屬線程要先實例化eventloop對象,主線程才能夠獲取eventloop對象。
所以這里面需要兩個東西:鎖與條件變量。

這2個東西,它的一個功能就是用于那么實現我們的一個loop操作的一個同步關系。因為呢?我們要避免那么線程創建之后,但是我們的eventloop,還沒有被實例化之前就去獲取loop的操作,這樣的獲取是會出問題,就是一個空了對不對所以要給它同步管理起來,也就是說你獲取loop的時候,必須是它loop已經那么實例化完了才可以之間的,你如果沒有實例化完那就不讓你獲取。

也就是在獲取eventloop對象指針時,設置一個條件:eventloop對象指針不為空。
如果這個時候不滿足,則主線程就去條件變量下阻塞等待,如果滿足條件就會被喚醒,去獲取eventloop對象指針。
而在線程的入口函數里面,在剛創建實例化eventloop對象之后,就立即發送通知,喚醒主線程。

1.1成員變量

private:std::thread _thread; // 用來創建線程,eventloop綁定的線程EventLoop *_loop;    // Eventloop的指針變量,這里不能實例化,必須在創建線程里面實例化eventloop// 下面兩個用來保證loop的同步性,必須先實例化完loop,才能獲取loopstd::mutex _mutex;             // 鎖,用來保護loop資源std::condition_variable _cond; // 條件變量

1.2構造函數

在構造中,就使用C++中的線程庫,創建線程。
所以該模塊對象一旦創建出來,就代表創建了一個線程以及對應的eventloop對象。

public:LoopThread() : _loop(NULL), _thread(std::bind(&LoopThread::ThreadEntry, this)){}

13線程入口函數

該線程一旦創建出來,就要執行的任務就是:
1.創建eventloop對象
2.喚醒主線程
3.啟動eventloop
(eventloop一旦啟動它就會循環監控在它上面的描述符的各種事件是否就緒,一旦就緒就會獲取就緒的事件以及描述符,執行對應的回調函數,并且執行任務隊列中的任務)

private:// 線程的入口函數void ThreadEntry(){// 首先創建對應的Eventloop對象EventLoop loop;_loop = &loop;// 創建完就喚醒可能阻塞的主線程_cond.notify_all();// 該線程就開始啟動工作:_loop->Start();// 1.進行事件監控,并獲取就緒的事件和fd 2.進行就緒事件處理3.執行任務隊列里的任務}

1.4獲取eventloop對象GetLoop()

 // 獲取該線程對應的loop是由主線執行的,所以存在線程安全問題,并且還要保證loop的同步問題EventLoop *GetLoop(){EventLoop *loop = NULL; // 為了保證臨界資源_loop的安全性,在訪問時最后將臨界資源拷貝過去,最后返回的時候就不涉及臨界資源的訪問{std::unique_lock<std::mutex> _lock(_mutex); // 加鎖// 確保獲取_loop之前已經被實例化_cond.wait(_lock, [&](){ return _loop != NULL; }); // 如果這時_loop為空,則主線程就一直阻塞在條件變量的隊列中loop = _loop;}return loop;}

實現了我們的一個主從react模型,主線程只負責對監聽套件字的處理,獲取新連接
保證我們連接的一個獲取效率不會因為我們的一個業務的處理而導致無法去獲取連接
而我們的從屬react呢?當它獲取到新連接之后,將我們的新連接分配給我們的從屬react線程中,讓從屬線程對它進行一個事件監控,進行事件監控然后事件的處理以及業務的處理。

2.LoopThreadPool模塊

LoopThreadPool線程池是對所有的LoopThread線程進行管理及分配。
主要提供的功能是:
1.能夠讓用戶設置創建幾個線程。

不過要注意當用戶設置的從線程數據為0時,這時候新連接的事件監控就必須要有主線程中的baseloop進行監控管理。所以該線程池中必須要傳入主線程的baseloop對象,以防止從屬線程的數量為0。

在主從Reactor模型中,主線程只負責獲取新連接,而從屬線程負責對連接進行監控和處理,當線程池中線程的個數為0時,就變成了單Reactor服務器,主線程既負責或者新連接,也負責新連接的監控與處理。
2.能夠將線程池中對應線程的eventloop對象分配出去。

如果線程池中線程的個數為0 ,則將主線程的Eventloop分配給新連接,進行監控與處理。
如果線程池中線程的個數有多個,則采用RR輪轉思想,進行線程的分配。(就是將對應線程的Eventloop對象獲取到然后分配給Connection)
將所有線程的Eventloop對象都存儲起來,然后依次分配出去即可。

2.1成員變量

private:int _thread_count;                  // 要創建的線程的數量int _loop_idx;                      // 要分配的loop下標EventLoop *_baseloop;               // 主線程的loop,外界傳入進來,如果要創建的從線程數據為0,那么就分配出去的就是主線程的loopstd::vector<LoopThread *> _threads; // 保存所有的LoopThread線程對象std::vector<EventLoop *> _loops;    // 保存所有線程對應的eventloop,然后依次分配出去。

2.2構造函數

線程的數量在初始化時不設置,由用戶調用接口設置。
外界需要將主線程的baseloop對象傳入進來,以防止線程池中沒有線程。

LoopThreadPool(EventLoop *baseloop) : _thread_count(0), _loop_idx(0), _baseloop(baseloop) {}

2.3配置線程數量

void SetThreadCount(int count){_thread_count = count;}

2.4按照配置數量創建線程

創建線程時,將所有線程以及線程對應的eventloop對象都存儲在數組中。
然后根據下標就可以依次分配線程對應的eventloop對象了。

 void CreateLoopThread(){if (_thread_count > 0) // 如果大于0就將所有的線程都創建出來,如果小于0,那么就必須要用主線程的baseloop。{_threads.resize(_thread_count);_loops.resize(_thread_count);for (int i = 0; i < _thread_count; i++){// 創建線程,并將所有的線程管理起來_threads[i] = new LoopThread();// 并保存管理所有線程對應的loop_loops[i] = _threads[i]->GetLoop();}}}

2.5依次分配Eventloop對象

如果線程池中線程的個數為0,這時候分配出去的eventloop對象就是主線程的baseloop對象。主線程eventloop既獲取連接,也進行連接監控與處理。
否則就按照輪轉形式依次分配出去。

 EventLoop *AssignLoop(){// 如果從線程的數量為0,那么分配出去的loop就是主線程對應的loopif (_thread_count == 0){return _baseloop;}_loop_idx = (_loop_idx + 1) % _thread_count;return _loops[_loop_idx];}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/87005.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/87005.shtml
英文地址,請注明出處:http://en.pswp.cn/web/87005.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

華為云Flexus+DeepSeek征文|基于Dify構建文本/圖像/視頻生成工作流

華為云FlexusDeepSeek征文&#xff5c;基于Dify構建文本/圖像/視頻生成工作流 一、構建文本/圖像/視頻生成工作流前言二、構建文本/圖像/視頻生成工作流環境2.1 基于FlexusX實例的Dify平臺2.2 基于MaaS的模型API商用服務 三、構建文本/圖像/視頻生成工作流實戰3.1 配置Dify環境…

相機-IMU聯合標定:IMU更新頻率

文章目錄 ??簡介?? IMU頻率參數錯誤設置的影響? 相機-IMU聯合標定失敗:Optimization failed!?? 確定IMU更新頻率直接通過 rostopic hz 檢查實際頻率檢查 IMU 驅動或數據手冊從 bag 文件統計頻率在這里插入圖片描述修改 `update_rate` 的注意事項**最終建議****常見問題…

動手實踐:如何提取Python代碼中的字符串變量的值

要提取Python代碼中所有變量類型為字符串的變量的值&#xff0c;但不執行代碼&#xff08;避免安全風險&#xff09;&#xff0c;可以通過靜態分析代碼的抽象語法樹&#xff08;AST&#xff09;來實現。以下是完整的解決方案&#xff1a; 本文由「大千AI助手」原創發布&#xf…

Python中字符串isalpha()函數詳解

在 Python 中&#xff0c;isalpha() 是字符串&#xff08;string&#xff09;類型的內置方法&#xff0c;用于檢查字符串中的所有字符是否都是字母字符&#xff08;alphabetic character&#xff09;。以下是詳細說明&#xff1a; 一、基本功能 返回值&#xff1a;布爾值&…

Gradio全解13——MCP詳解(4)——TypeScript包命令:npm與npx

Gradio全解13——MCP詳解&#xff08;4&#xff09;——TypeScript包命令&#xff1a;npm與npx 第13章 MCP詳解13.4 TypeScript包命令&#xff1a;npm與npx13.4.1 概念區分1. npm概念與運行邏輯2. npx概念及特點 13.4.2 操作示例1. 使用npm執行包2. 使用npx執行包3. 常用npm命令…

《推客小程序全鏈路開發指南:從架構設計到裂變運營》

在移動互聯網流量紅利逐漸消退的今天&#xff0c;如何低成本獲客成為企業營銷的核心痛點。推客小程序作為一種基于社交關系的裂變營銷工具&#xff0c;正成為企業突破增長瓶頸的利器。本文將為您全面解析推客小程序的開發定制全流程&#xff0c;幫助您打造專屬的社交裂變營銷平…

中鈞科技參加中亞數字經濟對話會,引領新疆企業數字化新征程!

6月27 日&#xff0c;烏魯木齊成為數字經濟領域的焦點&#xff0c;中國新疆 - 中亞國家數字經濟和數字貿易企業對話會在此盛大舉行。 來自中亞國家及新疆數字經濟領域的100 余位核心代表齊聚一堂&#xff0c;圍繞數字經濟時代的機遇、挑戰與策略展開深度探討。 本次對話會由新…

k8s一鍵部署tongweb企業版7049m6(by why+lqw)

聲明 1.此貼僅供參考&#xff0c;請根據自身需求在測試環境測試和修改。 安裝準備 1.獲取對應的安裝包和授權,并將授權和安裝包放在同一個目錄下 2.docekr已配置遠程倉庫 3.提前拉取jdk的鏡像&#xff08;這里配置了使用openjdk:8&#xff09; 安裝 將以下內容復制到k8s_…

Qt 與 Halcon 聯合開發六:基于海康SDK設計完整的相機類【附源碼】

在現代工業自動化、機器人視覺、等領域&#xff0c;相機模塊的作用至關重要。通過相機模塊采集到的圖像數據&#xff0c;我們能夠進行一系列的圖像處理和分析。為了高效地控制相機和處理圖像&#xff0c;本篇文章將介紹如何使用Qt和Halcon聯合開發一個相機模塊&#xff0c;幫助…

第7篇:Gin模板引擎——服務端頁面渲染

作者:GO兔 博客:https://luckxgo.cn 分享大家都看得懂的博客 引言 在Web開發中&#xff0c;服務端頁面渲染(SSR)依然是構建動態網頁的重要方式。Gin框架雖然以API開發見長&#xff0c;但也內置了強大的模板引擎支持&#xff0c;基于Go標準庫的html/template包實現。本文將深入…

RagFlow 源碼部署啟動指南

一、環境準備 1. 安裝 uv 和 pre-commit 如果已安裝&#xff0c;可跳過。推薦使用官方方式安裝&#xff0c;避免報錯&#xff1a; pipx install uv pre-commit export UV_INDEXhttps://mirrors.aliyun.com/pypi/simple安裝報錯 使用清華源安裝&#xff1a; pipx install uv…

【Python基礎】12 閑談分享:Python用于無人駕駛的未來

引言&#xff1a;一個程序員的自動駕駛夢想 還記得2016年的那個秋天&#xff0c;我第一次坐進特斯拉Model S的駕駛座&#xff0c;體驗Autopilot功能。當方向盤開始自己轉動&#xff0c;車輛在高速公路上自動跟隨前車時&#xff0c;我的內心涌起了一種奇妙的感覺——這不就是我…

為什么js是單線程?

js單線程&#xff0c;同一時間只能做一件事 。js的單線程 主要與它的用途有關。作為瀏覽器腳本語言&#xff0c;js的主要用途是與用戶互動&#xff0c;以及操作DOM。這決定了它只能是單線程&#xff0c;否則會帶來很復雜的同步問題。如果js同時有兩個線程&#xff0c;一個線程在…

DVWA靶場通關筆記-文件包含(Medium級別 9種滲透方法)

目錄 一、文件包含 1、原因 2、危害 3、防范措施 二、代碼審計&#xff08;Medium級別&#xff09; 1、滲透準備 &#xff08;1&#xff09;配置php.ini &#xff08;2&#xff09;file1.php &#xff08;3&#xff09;file2.php &#xff08;4&#xff09;file3.php…

飛云翻倍布林(翻倍密碼系統四線布林版)雙安全系統+均價趨勢指標+日線周線MACD,組合操盤技術圖文分享

如上圖組合操盤套裝指標&#xff0c;主圖指標-翻倍密碼系統四線布林版-飛云翻倍布林。副圖指標1-均價趨勢指標&#xff0c;跟蹤市場均價走勢和趨勢&#xff1b;副圖指標2-日線周線MACD指標&#xff0c;跟蹤日線和周線兩個級別的MACD多空走勢以及共振與否。 主圖指標-飛云翻倍布…

《匯編語言:基于X86處理器》第6章 條件處理(1)

本章向程序員的匯編語言工具箱中引入一個重要的內容&#xff0c;使得編寫出來的程序具備作決策的功能。幾乎所有的程序都需要這種能力。首先&#xff0c;介紹布爾操作&#xff0c;由于能影響CPU狀態標志&#xff0c;它們是所有條件指令的核心。然后&#xff0c;說明怎樣使用演繹…

【分治思想】歸并排序 與 逆序對

歸并排序 歸并排序是一種分治算法&#xff0c;怎么分&#xff0c;怎么治&#xff1f; 分&#xff1a;通過遞歸不斷把數組分成兩半&#xff0c;直到每個子數組只剩 1 個元素&#xff08;天然有序&#xff09;治&#xff1a;把兩個已經排好序的子數組合并成一個有序數組。 把問…

SQL參數化查詢:防注入與計劃緩存的雙重優勢

在數據庫操作中&#xff0c;SQL參數化查詢&#xff08;Parameterized Queries&#xff09;是一種非常有效的技術&#xff0c;它不僅可以防止SQL注入攻擊&#xff0c;還可以提高數據庫查詢的效率&#xff0c;尤其是在與計劃緩存&#xff08;Query Plan Caching&#xff09;結合使…

【你怕一E1】- 孰輕孰重如何斷-組合問題的多種情形

摘要 本視頻講解了組合問題的多種情形,包括多選一、多選二、多選三以及分隊問題的解題方法。首先介紹了從不同人數中選人的不同選擇方式,如一百人中選一人有一百種選擇。隨后,詳細講解了有序思考方法在多選二問題中的應用,通過選隊長的方式列舉不同組合情況,并歸納出選擇規…

nginx反向代理的bug

nginx反向代理的bug 問題呈現 當我們配置反向代理的時候查詢error.log的時候我們發現以下的問題 2025/06/29 08:38:47 [error] 7#7: *2 open() “/usr/share/nginx/html/payed/notify” failed (2: No such file or directory), client: 192.168.98.1, server: localhost, r…