#Boost io_service# 網(wǎng)絡(luò)編程與IO操作的boost框架
“ ?文章所涉及內(nèi)容更多來自網(wǎng)絡(luò),在此聲明,并感謝知識的貢獻(xiàn)者!”
io_service 是什么—
io_service 簡介
io_service對象是asio框架中的調(diào)度器,所有異步io事件都是通過它來分發(fā)處理的
io_service的作用:?io_servie實現(xiàn)了一個任務(wù)隊列,這里的任務(wù)就是void(void)的函數(shù)。Io_servie最常用的兩個接口是post和run,post向任務(wù)隊列中投遞任務(wù),run是執(zhí)行隊列中的任務(wù),直到全部執(zhí)行完畢,并且run可以被N個線程調(diào)用。Io_service是完全線程安全的隊列。
1 post用于發(fā)布io事件,如timer,socket讀寫等,一般由asio框架相應(yīng)對象調(diào)用,無需我們顯式調(diào)用。
2 run用于監(jiān)聽io事件響應(yīng),并執(zhí)行響應(yīng)回調(diào),對于異步io操作需要在代碼中顯式調(diào)用,對于同步io操作則由io
對象隱式調(diào)用(并不是run函數(shù),不過也是等待io事件)
Io_service 是什么
asio是boost提供的一個c++異步編程模型庫,其核心類io_service,在多線程編程里面提供了任務(wù)隊列和任務(wù)分發(fā)功能
—
Io_service 用在哪
在socket、io編程里主要作為一個事件驅(qū)動器(完成端口、select、poll、epoll等)
—
Io_service 怎么用
每個io_service都一個公有任務(wù)隊列,和多個私有任務(wù)隊列,公有隊列由各個線程共享,私有隊列則是每個線程獨享一個。
—
io_service的任務(wù)執(zhí)行流程大致如下:
1調(diào)用run方法,進(jìn)入主loop;
2判斷公有隊列是否為空,不為空則取出任務(wù)并執(zhí)行,當(dāng)任務(wù)數(shù)大于1時同時喚醒其他空閑線程;
3任務(wù)執(zhí)行結(jié)束,把各個線程的私有隊里面的任務(wù)移動到公有任務(wù)隊列里面;
4觸發(fā)reactor,linux下面一般是epoll,當(dāng)有事件時,把相應(yīng)的事件的任務(wù)放到私有隊列里。
5當(dāng)隊列為空時,把當(dāng)前線程加到空閑線程隊列里面,同時進(jìn)入wait狀態(tài),等待其他線程的喚醒(task_operation)。
6當(dāng)用戶調(diào)用post時,任務(wù)是直接投遞到公有隊列op_queue里面。
—
io_service與線程的模式
1 一個io_service實例和一個處理線程的單線程
當(dāng)幾個處理程序需要被同時調(diào)用時,你通常會遇到瓶頸。如果一個處理程序需要花費很長的時間來執(zhí)行,所有隨后的處理程序都不得不等待。
2 一個io_service實例和多個處理線程的多線程
如果幾個處理程序被同時調(diào)用了,它們會在各自的線程里面被調(diào)用。唯一的瓶頸就是所有的處理線程都很忙的同時又有新的處理程序被調(diào)用。然而,這是有快速的解決方式的,增加處理線程的數(shù)目即可。
3 多個io_service實例和多個處理線程的多線程
當(dāng)你有成千上萬實時(socket)連接時。你可以認(rèn)為每一個處理線程(運行io_service::run()的線程)有它自己的select/epoll循環(huán);它等待任意一個socket連接,然后等待一個讀寫操作,當(dāng)它發(fā)現(xiàn)這種操作時,就執(zhí)行。
—

Io_service 線程池
1多個線程共享一個任務(wù)隊列
用戶把任務(wù)投遞到該任務(wù)隊列中,其他線程競爭從該隊列中獲取任務(wù)執(zhí)行。結(jié)合boost::thread,在多個線程里面調(diào)用run方法,即可實現(xiàn)該線程池:
using namespace boost;
using namespace boost::asio;
io_service ios;
int thread_num = 10;
thread *t[thread_num] = {0};
// 創(chuàng)建線程池
for(int i = 0; i < thread_num; ++i)
{
t[i] = new thread(bind(&io_service::run, &ios));
}
// 向任務(wù)隊列中投遞任務(wù),該任務(wù)將隨機由一個調(diào)用run方法的線程執(zhí)行
ios.post(func);
// 等待線程退出
for(int i = 0; i < thread_num; ++i)
{
t[i]->join();
}
問題:
多個線程競爭取任務(wù),在大并發(fā)的程序里面容易導(dǎo)致性能下降
2 每個線程各自維護(hù)一個任務(wù)隊列
用戶可以選擇隨機或者輪訓(xùn)地投遞任務(wù)到其中一個任務(wù)隊列里面,該任務(wù)隊列中的任務(wù)只由其所在的線程才能消費。這種線程池在boost的example里面也有相應(yīng)的實現(xiàn)(io_service_pool),基本方法是創(chuàng)建多個io_service對象,每個對應(yīng)一個thread
using namespace boost;
using namespace boost::asio;
int thread_num = 10;
io_service ios[thread_num];
thread *t[thread_num] = {0};
// 創(chuàng)建線程池
for(int i = 0; i < thread_num; ++i)
{
t[i] = new thread(bind(&io_service::run, &ios[i]));
}
// 輪訓(xùn)投遞任務(wù)
for(int i = 0; i < thread_num; ++i)
{
ios[i].post(func);
}
// 等待線程退出
for(int i = 0; i < thread_num; ++i)
{
t[i]->join();
}
—
Io_service的機制
io_service定義了主要的接口,在linux下的實現(xiàn)是task_io_service。
task_io_service主要定義了三個東西:
一個reactor,reactor就是完成端口、select、poll、epoll之類的事件驅(qū)動器;
一個公共的任務(wù)隊列op_queue,用來存放用戶post的任務(wù),和reactor返回的任務(wù);
線程相關(guān)變量。io_service本身不會創(chuàng)建任何線程,但它會保存一些線程調(diào)用信息,如線程私有隊列等。
此外,task_io_service還維護(hù)了一個空閑線程列表,在有多余任務(wù)到來時,喚醒其中一個空閑線程。在常見的linux單任務(wù)隊列的線程池里面,用一個condition變量來喚醒線程,在多核系統(tǒng)里面,一次pthread_cond_signal調(diào)用,會喚起處于wait狀態(tài)的一個或多個線程(參考 https://linux.die.net/man/3/pthread_cond_signal ),盡管只有一個任務(wù),如果采用空閑線程的方法,有任務(wù)時只喚醒一個空閑線程,可以減少很多不必要喚醒。
thread_info_base類維護(hù)了一個簡單的內(nèi)存池,只有一塊內(nèi)存,僅在連續(xù)的申請釋放內(nèi)存情況下,可以減少內(nèi)存開辟的開銷。
—
同步模式
在asio框架中,同步的io主要流程如下:

1 應(yīng)用程序調(diào)用IO對象成員函數(shù)執(zhí)行IO操作
2 IO對象向io_service 提出請求.
3 io_service 調(diào)用操作系統(tǒng)的功能執(zhí)行連接操作.
4 操作系統(tǒng)向io_service 返回執(zhí)行結(jié)果.
5 io_service將錯誤的操作結(jié)果翻譯為boost::system::error_code類型,再傳遞給IO對象.
6 如果操作失敗,IO對象拋出boost::system::system_error類型的異常.
異步模式
異步IO的處理流程則有些不同:

1 應(yīng)用程序調(diào)用IO對象成員函數(shù)執(zhí)行IO操作
2 IO對象請求io_service的服務(wù)
3 io_service 通知操作系統(tǒng)其需要開始一個異步連接.
4 操作系統(tǒng)指示連接操作完成, io_service從隊列中獲取操作結(jié)果
5 應(yīng)用程序必須調(diào)用io_service::run()以便于接收結(jié)果
6 調(diào)用io_service::run()后,io_service返回一個操作結(jié)果,并將其翻譯為error_code,傳遞到事件回調(diào)函數(shù)中
—
Io_service 常用方法
io_servie::Post方法
Post向隊列中投遞任務(wù),然后激活空閑線程執(zhí)行任務(wù)。
io_servie::run方法
Run方法執(zhí)行隊列中的所有任務(wù),直到任務(wù)執(zhí)行完畢。
Run方法的原則是:
- 有任務(wù)立即執(zhí)行任務(wù),盡量使所有的線程一起執(zhí)行任務(wù)
- 若沒有任務(wù),阻塞在epoll_wait上等待io事件
- 若有新任務(wù)到來,并且沒有空閑線程,那么先中斷epoll_wait,先執(zhí)行任務(wù)
- 若隊列中有任務(wù),并且也需要epoll_wait監(jiān)聽事件,那么非阻塞調(diào)用epoll_wait(timeout字段設(shè)置為0),待任務(wù)執(zhí)行完畢在阻塞在epoll_wait上。
- 幾乎對線程的使用上達(dá)到了極致。
- 從這個函數(shù)中可以知道,在使用ASIO時,io_servie應(yīng)該盡量多,這樣可以使其epoll_wait占用的時間片最多,這樣可以最大限度的響應(yīng)IO事件,降低響應(yīng)時延。但是每個io_servie::run占用一個線程,所以io_servie最佳應(yīng)該和CPU的核數(shù)相同。
io_servie::stop方法
停止所有線程的任務(wù)
—
io_service的注意問題
1 run函數(shù)在io事件完成后會退出,導(dǎo)致后續(xù)基于該對象的異步io任務(wù)無法執(zhí)行
給其【io_service】分配一個線程,然后執(zhí)行run函數(shù)。但run函數(shù)在io事件完成后會退出,線程會終止,后續(xù)基于該對象【io_service】的異步io任務(wù)無法得到調(diào)度。
通過一個asio::io_service::work對象來守護(hù)io_service。這樣,即使所有io任務(wù)都執(zhí)行完成,也不會退出,繼續(xù)等待新的io任務(wù)。
boost::asio::io_service?io;
boost::asio::io_service::work?work(io);
io.run();
2. 回調(diào)在run函數(shù)的線程中同步執(zhí)行,當(dāng)回調(diào)處理時間較長時阻塞后續(xù)io響應(yīng)
解決這個問題的方法有兩種:
1. 啟動多線程執(zhí)行run函數(shù)(run函數(shù)是線程安全的)
2. 新啟動一個線程(或通過線程池)來執(zhí)行回調(diào)函數(shù)。一般來講,如果回調(diào)處理事件不是特別短,應(yīng)該使用在線程池中處理回調(diào)的方式。
3. 回調(diào)在run函數(shù)的線程中同步執(zhí)行,io事件較多的時候得不到及時響應(yīng)
這個其實是性能問題了,在多核cpu上可以通過在多個線程中執(zhí)行run函數(shù)來解決這一問題。這種方式也只能充分利用cpu性能,本身性能問題就不是光靠軟件就能解決的。
—
學(xué)習(xí)范例:
io_service 的使用框架
#include <boost/asio.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/thread.hpp>
#include <boost/atomic.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/date_time/posix_time/ptime.hpp>
#include <boost/date_time.hpp>
#include <iostream>
int main()
{
//io_service asio框架的調(diào)度器,在多線程機制中提供任務(wù)隊列和任務(wù)分發(fā)功能
boost::asio::io_service io_service;
//work對象來守護(hù)io_service,即使所有io任務(wù)都執(zhí)行完成,也不會退出,繼續(xù)等待新的io任務(wù)。
boost::asio::io_service::work work(io_service);
//run用于監(jiān)聽io事件響應(yīng),并執(zhí)行響應(yīng)回調(diào),1在io事件完成后退出 2io_service調(diào)用stop()后退出
io_service.run();
return 0;
}
鎖的機制
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>
long num = 0;
//mutex 互斥量
std::mutex num_mutex;
void numplus() {
std::cout << "++ :" << num << std::endl;
//創(chuàng)建互斥量管理對象時,它試圖給給定mutex加鎖。當(dāng)程序離開互斥量管理對象的作用域時,互斥量管理對象會析構(gòu)并且并釋放mutex。所以我們則不需要擔(dān)心程序跳出或產(chǎn)生異常引發(fā)的死鎖了。
std::lock_guard<std::mutex> lock_guard(num_mutex);
std::cout <<"++ before:" << num << std::endl;
for (long i = 0; i < 1000000; ++i) {
num++;
}
std::cout << num << std::endl;
std::cout << "++ after:" << num << std::endl;
};
void numsub() {
std::cout << "-- :" << num << std::endl;
std::lock_guard<std::mutex> lock_guard(num_mutex);
std::cout << "-- before:" << num << std::endl;
for (long i = 0; i < 1000000; ++i) {
num--;
}
std::cout << "-- after:" << num << std::endl;
}
int main() {
std::thread t1(numplus);
std::thread t2(numsub);
t1.join();
t2.join();
std::cout << num << std::endl;
system("PAUSE");
}
線程池管理
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>
void Run(int nVal)
{
//
int nTemp = nVal * nVal;
//下面輸出需要加鎖,不能多個線程共享輸出。
static boost::mutex mutexCout;
boost::lock_guard<boost::mutex> autoLock(mutexCout);
std::cout << "thread Run: [" << nVal << "] " << nTemp << std::endl;
}
int main(int argc, char * argv[])
{
//定義一個線程組對象。提供了多個線程創(chuàng)建、保存、退出等管理。
boost::thread_group threadGroup;
//設(shè)置最大的線程個數(shù)。一般來說是CPU的個數(shù)的兩倍是最高效率的線程模型。
const int nMaxCount = 5;
//循環(huán)地創(chuàng)建N個線程。
for (int i = 0; i < nMaxCount; ++i)
{
//使用create_thread函數(shù)可以創(chuàng)建多個線程,每個線程都調(diào)用函數(shù)Run運行。
threadGroup.create_thread(boost::bind(Run, i));
}
//等所有線程退出。使用join_all函數(shù)來確保所有線程運行,都從線程運行函數(shù)里退出來,如果其中一個線程沒有辦法退出,那么就會一直等待的。
threadGroup.join_all();
system("PAUSE");
return 0;
}
多線程中使用io_service 使得線程一直運行
#include <boost/asio/io_service.hpp>
#include <boost/thread/thread.hpp>
#include <iostream>
//asio 任務(wù)調(diào)度器
boost::asio::io_service io_service;
void WorkerThread()
{
std::cout << "Thread Start\n";
//在多個線程中調(diào)用run()即可開啟線程池,io_service負(fù)責(zé)執(zhí)行任務(wù)處理。阻塞在線程里
io_service.run();
std::cout << "Thread Finish\n";
}
int main(int argc, char * argv[])
{
//work類型的指針
boost::shared_ptr< boost::asio::io_service::work > work(new boost::asio::io_service::work(io_service));
//輸出信息
std::cout << "Press [return] to exit." << std::endl;
//創(chuàng)建線程池/線程組
boost::thread_group worker_threads;
for (int x = 0; x < 4; ++x)
{
//創(chuàng)建線程
worker_threads.create_thread(WorkerThread);
}
//主線程獲取監(jiān)聽輸入
std::cin.get();
//stop()會告知io_service,所有的任務(wù)需要終止。它的調(diào)用可能會使已經(jīng)進(jìn)入隊列的任務(wù)得不到執(zhí)行。
io_service.stop();
//等所有線程退出。使用join_all函數(shù)來確保所有線程運行,都從線程運行函數(shù)里退出來,如果其中一個線程沒有辦法退出,那么就會一直等待的。
worker_threads.join_all();
//屏幕暫停關(guān)閉
system("PAUSE");
return 0;
}
Bind的使用
#include <boost/asio/io_service.hpp>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <iostream>
//互斥量
boost::mutex global_stream_lock;
void WorkerThread(boost::shared_ptr< boost::asio::io_service > io_service)
{
//線程id
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id() << "] Thread Start" << std::endl;
global_stream_lock.unlock();
//io_service阻塞
io_service->run();
//
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id() << "] Thread Finish" << std::endl;
global_stream_lock.unlock();
}
int main(int argc, char * argv[])
{
//智能指針,維護(hù)對象,進(jìn)行自動管理
boost::shared_ptr< boost::asio::io_service > io_service(new boost::asio::io_service);
boost::shared_ptr< boost::asio::io_service::work > work(new boost::asio::io_service::work(*io_service));
//主線程 id
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id() << "] Press [return] to exit." << std::endl;
global_stream_lock.unlock();
//多線程
boost::thread_group worker_threads;
for (int x = 0; x < 4; ++x)
{
//使用boost::bind可以把函數(shù)調(diào)用包裝成為對象。便于傳遞參數(shù)
worker_threads.create_thread(boost::bind(&WorkerThread, io_service));
}
//主線程獲取鍵盤數(shù)據(jù)
std::cin.get();
//io_service關(guān)閉任務(wù)
io_service->stop();
//等所有線程退出。使用join_all函數(shù)來確保所有線程運行,都從線程運行函數(shù)里退出來,如果其中一個線程沒有辦法退出,那么就會一直等待的。
worker_threads.join_all();
//屏幕暫停關(guān)閉
system("PAUSE");
return 0;
}
Post dispatch
#include <boost/asio/io_service.hpp>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <iostream>
boost::mutex global_stream_lock;
void WorkerThread(boost::shared_ptr< boost::asio::io_service > io_service,int i)
{
std::cout << i << std::endl;
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id() << "] Thread Start" << std::endl;
global_stream_lock.unlock();
io_service->run();
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id() << "] Thread Finish" << std::endl;
global_stream_lock.unlock();
}
//dispatch會立即執(zhí)行任務(wù),否則把任務(wù)加入到queue
void Dispatch(int x)
{
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id() << "] " << __FUNCTION__ << " x = " << x << std::endl;
global_stream_lock.unlock();
}
//post只會把任務(wù)加入到隊列
void Post(int x)
{
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id() << "] " << __FUNCTION__ << " x = " << x << std::endl;
global_stream_lock.unlock();
}
void Run3(boost::shared_ptr< boost::asio::io_service > io_service)
{
for (int x = 0; x < 3; ++x)
{
io_service->dispatch(boost::bind(&Dispatch, x * 2));
io_service->post(boost::bind(&Post, x * 2 + 1));
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
}
}
int main(int argc, char * argv[])
{
boost::shared_ptr< boost::asio::io_service > io_service(new boost::asio::io_service);
boost::shared_ptr< boost::asio::io_service::work > work(new boost::asio::io_service::work(*io_service));
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id() << "] The program will exit when all? work has finished." << std::endl;
global_stream_lock.unlock();
boost::thread_group worker_threads;
for (int x = 0; x < 1; ++x)
{
worker_threads.create_thread(boost::bind(&WorkerThread, io_service, x));
}
io_service->post(boost::bind(&Run3, io_service));
//立即結(jié)束任務(wù)
work.reset();
worker_threads.join_all();
//屏幕暫停關(guān)閉
system("PAUSE");
return 0;
}
Strand 順序處理
#include <boost/asio/io_service.hpp>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <boost/asio/strand.hpp>
#include <iostream>
boost::mutex global_stream_lock;
void WorkerThread(boost::shared_ptr< boost::asio::io_service > io_service)
{
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id() << "] Thread Start" << std::endl;
global_stream_lock.unlock();
io_service->run();
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id() << "] Thread Finish" << std::endl;
global_stream_lock.unlock();
}
void PrintNum(int x)
{
std::cout << "[" << boost::this_thread::get_id() << "] x: " << x << std::endl;
}
int main(int argc, char * argv[])
{
boost::shared_ptr< boost::asio::io_service > io_service(new boost::asio::io_service);
boost::shared_ptr< boost::asio::io_service::work > work(new boost::asio::io_service::work(*io_service));
//strand提供順序化的事件執(zhí)行器。意思是,如果以“work1->work2->work3”的順序post,不管有多少個工作線程,它們依然會以這樣的順序執(zhí)行任務(wù)。
boost::asio::io_service::strand strand(*io_service);
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id() << "] The program will exit when all? work has finished." << std::endl;
global_stream_lock.unlock();
boost::thread_group worker_threads;
for (int x = 0; x < 2; ++x)
{
worker_threads.create_thread(boost::bind(&WorkerThread, io_service));
}
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
//strand.post( boost::bind( &PrintNum, 1 ) );
//strand.post( boost::bind( &PrintNum, 2 ) );
//strand.post( boost::bind( &PrintNum, 3 ) );
//strand.post( boost::bind( &PrintNum, 4 ) );
//strand.post( boost::bind( &PrintNum, 5 ) );
io_service->post(boost::bind(&PrintNum, 1));
io_service->post(boost::bind(&PrintNum, 2));
io_service->post(boost::bind(&PrintNum, 3));
io_service->post(boost::bind(&PrintNum, 4));
io_service->post(boost::bind(&PrintNum, 5));
work.reset();
worker_threads.join_all();
return 0;
}
boost::noncopyable
#include <iostream>
#include <boost/noncopyable.hpp>
class Test1 {
public:
Test1(int i) { std::cout << "This is Test1 that is copyable" << std::endl; }
};
//將私有化類的拷貝構(gòu)造函數(shù)和拷貝賦值操作符,這樣子類可以調(diào)用,但是外部調(diào)用者不能通過復(fù)制/賦值等語句來產(chǎn)生一個新的對象。不支持使用復(fù)制的方式來實例化類。
class Test2 : boost::noncopyable {
public:
Test2(int i) { std::cout << "This is Test2 that is noncopyable" << std::endl; }
};
int main()
{
Test1 t1(1);
Test2 t2(2);
Test1 t3 = t1;??? // It's OK
Test1 t4(t1);???? // It's OK
Test2 t5 = t2;??? // Cannot be referenced
Test2 t6(t2);???? // Cannot be referenced
Test2 &t7 = t2;?? // It's OK
return 0;
}
boost::asio::deadline_timer 計時器 同步模式
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
int main()
{
//創(chuàng)建任務(wù)調(diào)度器 io_service
boost::asio::io_service io;
//定時器
boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
//阻塞等待,boost::asio::deadline_timer::wait()的在創(chuàng)建后5秒內(nèi)(注意:不是等待開始后),timer到時之前不會返回任何值.
t.wait();
//boost::asio::deadline_timer::wait()在到時的timer對象上調(diào)用,會立即return,輸出信息
std::cout << "Hello, world! ";
return 0;
}
boost::asio::deadline_timer 計時器 異步模式
#include <iostream>
#include <boost/asio.hpp>
void handler(const boost::system::error_code &ec)
{
std::cout << "5 s." << std::endl;
}
int main()
{
boost::asio::io_service io_service;
boost::asio::io_service::work work(io_service);
boost::asio::deadline_timer timer(io_service, boost::posix_time::seconds(5));
timer.async_wait(handler);
std::cout << "soon." << std::endl;
io_service.run();
}
多線程執(zhí)行任務(wù):一個io_service多個thread
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <iostream>
void handler1(const boost::system::error_code &ec)
{
for (int i = 0; i < 10000; i++)
{
std::cout << "1." << std::endl;
}
}
void handler2(const boost::system::error_code &ec)
{
for (int i = 0; i < 10000; i++)
{
std::cout << "2." << std::endl;
}
}
boost::asio::io_service io_service;
void run()
{
io_service.run();
}
int main()
{
boost::asio::deadline_timer timer1(io_service, boost::posix_time::seconds(5));
timer1.async_wait(handler1);
boost::asio::deadline_timer timer2(io_service, boost::posix_time::seconds(5));
timer2.async_wait(handler2);
boost::thread thread1(run);
boost::thread thread2(run);
thread1.join();
thread2.join();
}
在 main() 中創(chuàng)建了兩個線程。這兩個線程均針對同一個 I/O 服務(wù)調(diào)用了 run() 方法。這樣當(dāng)異步操作完成時,這個 I/O 服務(wù)就可以使用兩個線程去執(zhí)行句柄函數(shù)。
兩個計時數(shù)均被設(shè)為在五秒后觸發(fā)。由于有兩個線程,所以 handler1() 和 handler2() 可以同時執(zhí)行。如果第二個計時器觸發(fā)時第一個仍在執(zhí)行,則第二個句柄就會在第二個線程中執(zhí)行。如果第一個計時器的句柄已經(jīng)終止,則 I/O 服務(wù)可以自由選擇任一線程。
線程可以提高應(yīng)用程序的性能。因為線程是在處理器內(nèi)核上執(zhí)行的,所以創(chuàng)建比內(nèi)核數(shù)更多的線程是沒有意義的。這樣可以確保每個線程在其自己的內(nèi)核上執(zhí)行,而沒有同一內(nèi)核上的其它線程與之競爭。
多個io_service多個thread
多次調(diào)用同一個 I/O 服務(wù)的 run()方法,是為基于 Boost.Asio 的應(yīng)用程序增加可擴展性的推薦方法。另外還有一個不同的方法:不要綁定多個線程到單個 I/O 服務(wù),而是創(chuàng)建多個 I/O 服務(wù)。然后每一個 I/O 服務(wù)使用一個線程。如果 I/O 服務(wù)的數(shù)量與系統(tǒng)的處理器內(nèi)核數(shù)量相匹配,則異步操作都可以在各自的內(nèi)核上執(zhí)行。
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <iostream>
void handler1(const boost::system::error_code &ec)
{
for (int i = 0; i < 10000; i++)
{
std::cout << "1." << std::endl;
}
}
void handler2(const boost::system::error_code &ec)
{
for (int i = 0; i < 10000; i++)
{
std::cout << "2." << std::endl;
}
}
boost::asio::io_service io_service1;
boost::asio::io_service io_service2;
void run1()
{
io_service1.run();
}
void run2()
{
io_service2.run();
}
int main()
{
boost::asio::deadline_timer timer1(io_service1, boost::posix_time::seconds(5));
timer1.async_wait(handler1);
boost::asio::deadline_timer timer2(io_service2, boost::posix_time::seconds(5));
timer2.async_wait(handler2);
boost::thread thread1(run1);
boost::thread thread2(run2);
thread1.join();
thread2.join();
}
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <iostream>
using namespace boost::asio;
io_service service;
void func(int i) {
std::cout << "func called, i= " << i << std::endl;
}
void worker_thread() {
service.run();
}
int main(int argc, char* argv[]) {
for (int i = 0; i < 10; ++i)
service.post(boost::bind(func, i));
boost::thread_group threads;
for (int i = 0; i < 3; ++i)
threads.create_thread(worker_thread);
// wait for all threads to be created
boost::this_thread::sleep(boost::posix_time::millisec(500));
threads.join_all();
getchar();
}
循環(huán)計時器
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
void print(const boost::system::error_code& /*e*/,
boost::asio::deadline_timer* t, int* count)
{
if (*count < 5)
{
std::cout << *count << std::endl;
}
++(*count);
std::cout << *count << std::endl;
//在計時器處理程序中調(diào)用deadline_timer :: expires_from_now和deadline_timer :: async_wait來執(zhí)行此操作,這將在最后一個計時器到期時添加計時器
t->expires_at(t->expires_at() + boost::posix_time::seconds(5));
t->async_wait(boost::bind(print,
boost::asio::placeholders::error, t, count));
}
int main()
{
boost::asio::io_service io;
int count = 0;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
t.async_wait(boost::bind(print,
boost::asio::placeholders::error, &t, &count));
io.run();
std::cout << "Final count is " << count << std::endl;
return 0;
}
—
參考資料
https://www.cnblogs.com/fnlingnzb-learner/p/10402232.html
https://blog.csdn.net/qq_38365116/article/details/85102103
https://blog.csdn.net/guotianqing/article/details/100730340
boost::thread_group join_all
https://blog.csdn.net/caimouse/article/details/8741295
互斥量、鎖
https://www.cnblogs.com/flyinggod/p/13570390.html
io_service 多線程,一個線程綁定一個函數(shù)
https://blog.csdn.net/guotianqing/article/details/100730340
boost::noncopyable
https://blog.csdn.net/rangfei/article/details/122464346
boost::asio::io_service post run stop reset work
https://www.cnblogs.com/fnlingnzb-learner/p/10402232.html
io_service 與多線程的模式
https://blog.csdn.net/qq_38365116/article/details/85102103
boost::asio::io_service創(chuàng)建線程池簡單實例
https://blog.csdn.net/guotianqing/article/details/100730340
boost::asio 網(wǎng)絡(luò)編程
https://blog.csdn.net/smilejiasmile/article/details/114330843
boost asio 重復(fù)計時器
https://www.icode9.com/content-4-494864.html
boost 多線程使用
https://blog.csdn.net/alppkk4545/article/details/101575899
https://www.cnblogs.com/ttmoon/p/7658224.html
https://www.codenong.com/22826143/
https://www.codenong.com/61276549/
https://blog.csdn.net/zzhongcy/article/details/85162856
std thread join 等待線程執(zhí)行返回
https://blog.csdn.net/duan19920101/article/details/121357347
智能指針reset()方法分析
https://blog.csdn.net/qq43645149/article/details/130037999
reset()函數(shù)接受一個可選參數(shù),這個參數(shù)可以是一個指向新對象的指針,也可以是一個空指針。
當(dāng)參數(shù)為空指針時,reset()會釋放原來指針?biāo)芾淼馁Y源,同時將指針置為空。當(dāng)參數(shù)為非空指針時,
reset()會先釋放原來指針?biāo)芾淼馁Y源,然后將指針重新指向新對象,
此時此刻,如果有其它智能指針也指向它,只是計數(shù)減一。
當(dāng)使用reset函數(shù)時,智能指針的引用計數(shù)會相應(yīng)地減少1。如果減少后引用計數(shù)變?yōu)?,則表示該資源不再被使用,可以安全地刪除資源。
Io_service 線程池
https://blog.csdn.net/hlday6/article/details/82696916
