当前位置:网站首页>Boost. Asio Library
Boost. Asio Library
2022-07-03 18:33:00 【It's haohaozi】
1. io_service
io_service
yes Boost::Asio The core object in the namespace ,I/O service Is a channel for accessing operating system resources , And submit I/O Requested procedure and execution I/O Establish communication between the requested operating systems .io_service The most frequently used method for objects is run()
, It is used for continuous response io_service Object needs to handle events . So it will block , Until all the events are handled .
If you want to let io_service
Object when there is no event to handle ,run()
Still blocked , have access to work()
Method . for example :
#include <boost/asio.hpp>
#include <iostream>
int main(void) {
boost::asio::io_service io_svc;
boost::asio::io_service::work worker(io_svc); // Equivalent to changing io_svc The nature of
io_svc.run(); // This waiting does not occupy CPU resources
std::cout << "We will not see this line in console window :(" << std::endl;
return 0;
}
In the code above ,work
Class notification io_service
Object it has work to do , But we don't define what work is . therefore , The program will be infinitely blocked , So the last line of code will not output . The reason for the blockage is run() Function called .
And run()
The opposite is poll()
Method .poll()
Method is used to handle ready programs , Until there are no remaining ready programs or until io_service Object stop . however , And run() Compared to the function ,poll() Functions do not block programs , Even if work()
Method .
2. Delete work object
You can do this by io_service
Object to unblock the program , But in order to remove the working object itself , We must use a pointer to the working object .
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include<boost/chrono.hpp>
#include <iostream>
int main(void) {
boost::asio::io_service io_svc;
boost::shared_ptr<boost::asio::io_service::work> worker(
new boost::asio::io_service::work(io_svc));
worker.reset(); // Destroy the pointer , All pending work will be over
io_svc.run();
std::cout << "We will not see this line in console window :(" << std::endl;
return 0;
}
3. Dealing with multithreading
One io_service
Process in multiple threads .
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <iostream>
boost::asio::io_service io_svc;
int a = 0;
void WorkerThread() {
std::cout << ++a << ".\n";
io_svc.run();
std::cout << "End.\n";
}
int main(void) {
boost::shared_ptr<boost::asio::io_service::work> worker(
new boost::asio::io_service::work(io_svc));
std::cout << "Press ENTER key to exit!" << std::endl;
boost::thread_group threads;
for(int i=0; i<5; i++)
threads.create_thread(WorkerThread);
std::cin.get();
io_svc.stop(); // worker.reset();
threads.join_all();
return 0;
}
4. Copy io_service The pointer
Other things to note are io_service
Is an object that cannot be copied . But it can be done by shared_ptr Instantiate in pointer io_service object , Make it replicable , So we can bind it to worker thread()
In the method , Use as a thread handler .
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <iostream>
using namespace boost::asio;
void workThread(std::shared_ptr<io_service> iosvc, int counter) {
std::cout << counter << std::endl;
iosvc->run();
std::cout << "End." << std::endl;
}
int main() {
//io_service ios;
auto io_svc = std::make_shared<io_service>();
std::shared_ptr<io_service::work> worker(new io_service::work(*io_svc));
std::cout << "Press ENTER key to exit!" << std::endl;
boost::thread_group threads;
for(int i=1; i<=5; i++) {
threads.create_thread(boost::bind(&workThread, io_svc, i));
}
std::cin.get();
worker.reset(); // io_svc->stop(); Is to stop all work , Even if you haven't finished .worker.reset(); Like Cancel io_service Object's work attribute
threads.join_all();
return 0;
}
5. The mutex
In the above examples of multithreading , The operation is random . because std::cout Object is a global object , Write from different threads at once , It may cause output formatting problems . Mutexes can be used to synchronize access to any global or shared data .
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <iostream>
boost::mutex global_stream_lock;
void WorkerThread(boost::shared_ptr<boost::asio::io_service> iosvc,
int counter) {
global_stream_lock.lock();
std::cout << counter << ".\n";
global_stream_lock.unlock();
iosvc->run();
global_stream_lock.lock();
std::cout << "End.\n";
global_stream_lock.unlock();
}
int main(void) {
boost::shared_ptr<boost::asio::io_service> io_svc(
new boost::asio::io_service
);
boost::shared_ptr<boost::asio::io_service::work> worker(
new boost::asio::io_service::work(*io_svc)
);
std::cout << "Press ENTER key to exit!" << std::endl;
boost::thread_group threads;
for(int i=1; i<=5; i++)
threads.create_thread(boost::bind(&WorkerThread, io_svc, i));
std::cin.get();
io_svc->stop();
threads.join_all();
return 0;
}
6. towards I/O service Distribution work
stay io_service
There are two ways to io_service
Assigned tasks :post()
Method for request io_service
Object runs after we queue all the work io_service
The object corresponds to work, So it doesn't allow us to run work immediately . and dispatch()
The method is also used to io_service
Object makes a request to run io_service
Object's work , But it will execute the work immediately , Instead of queuing up .
post()
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <iostream>
boost::mutex global_stream_lock;
void WorkerThread(boost::shared_ptr<boost::asio::io_service> iosvc,
int counter) {
global_stream_lock.lock();
std::cout << counter << ".\n";
global_stream_lock.unlock();
iosvc->run();
global_stream_lock.lock();
std::cout << "End.\n";
global_stream_lock.unlock();
}
size_t fac(size_t n) {
if ( n <= 1 ) {
return n;
}
boost::this_thread::sleep(
boost::posix_time::milliseconds(1000)
);
return n * fac(n - 1);
}
void CalculateFactorial(size_t n) {
global_stream_lock.lock();
std::cout << "Calculating " << n << "! factorial" << std::endl;
global_stream_lock.unlock();
size_t f = fac(n);
global_stream_lock.lock();
std::cout << n << "! = " << f << std::endl;
global_stream_lock.unlock();
}
int main(void) {
boost::shared_ptr<boost::asio::io_service> io_svc(
new boost::asio::io_service
);
boost::shared_ptr<boost::asio::io_service::work> worker(
new boost::asio::io_service::work(*io_svc)
);
global_stream_lock.lock();
std::cout << "The program will exit once all work has finished." << std::endl;
global_stream_lock.unlock();
boost::thread_group threads;
for(int i=1; i<=5; i++)
threads.create_thread(boost::bind(&WorkerThread, io_svc, i));
io_svc->post(boost::bind(CalculateFactorial, 5));
io_svc->post(boost::bind(CalculateFactorial, 6));
io_svc->post(boost::bind(CalculateFactorial, 7));
worker.reset();
threads.join_all();
return 0;
}
stay main Function , Use post() Function publishes three function objects to io_service On the object . We're initializing 5 A worker thread will io_service The object pointer is assigned to 5 In threads . such , Because we call in every thread io_service Object's run() function , therefore io_service Object's work Will run post() Method release work .
dispatch()
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <iostream>
using namespace boost::asio;
//boost::mutex global_lock;
void Dispatch(int i) {
std::cout << "dispatch() function for i=" << i << std::endl;
}
void Post(int i) {
std::cout << "post() function for i=" << i << std::endl;
}
void workerThread(std::shared_ptr<io_service> iosv) {
std::cout << "Thread Start." <<std::endl;
iosv->run();
std::cout << "Thread Finish." << std::endl;
}
void running(std::shared_ptr<io_service> iosv) {
for(int i=0; i<5; i++) {
iosv->dispatch(boost::bind(&Dispatch, i));
iosv->post(boost::bind(&Post, i));
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
}
}
int main() {
auto iosv =std::make_shared<io_service>();
//io_service::work worker(*iosv);
auto worker = std::make_shared<io_service::work>(*iosv); // make_shared<io_service::work> Would call work Constructor for
boost::thread_group threads;
threads.create_thread(boost::bind(&workerThread, iosv));
iosv->post(boost::bind(&running, iosv));
worker.reset();
threads.join_all();
return 0;
}
Output results :
Thread Start.
dispatch() function for i=0
dispatch() function for i=1
dispatch() function for i=2
dispatch() function for i=3
dispatch() function for i=4
post() function for i=0
post() function for i=1
post() function for i=2
post() function for i=3
post() function for i=4
Thread Finish.
According to the conventional understanding, the output result should be dispatch() and post() Alternate execution , But the result is to execute first dispatch() Re execution post(). This is because dispatch() The distributed work requires immediate invocation from the current worker thread , and post() You must wait until the worker thread's handler completes before it can be called . let me put it another way ,post() Queue up when the worker thread has other pending events , It can't be allowed to execute until the handler finishes executing .
That is to say, we first post One. running Work , And in this job , also dispatch and post Work , that workerThread Process first in the same thread running Work , When running to dispatch when , although running The work is not finished , however dispatch It also requires immediate operation , and post Just put your tasks in a queue , When the thread is not busy, it can run , Wait in line when busy .
边栏推荐
- AcWing 271. Teacher Yang's photographic arrangement [multidimensional DP]
- [combinatorics] generating function (positive integer splitting | repeated ordered splitting | non repeated ordered splitting | proof of the number of repeated ordered splitting schemes)
- Self executing function
- [combinatorics] exponential generating function (example of exponential generating function solving multiple set arrangement)
- 论文阅读 GloDyNE Global Topology Preserving Dynamic Network Embedding
- Three gradient descent methods and code implementation
- Unsafe类的使用
- English语法_名词 - 分类
- 2022-2028 global plasmid DNA cdmo industry research and trend analysis report
- Prototype inheritance..
猜你喜欢
PHP MySQL create database
Module 9 operation
What London Silver Trading software supports multiple languages
PHP MySQL inserts data
The second largest gay dating website in the world was exposed, and the status of programmers in 2022
MySQL duplicate check
On Data Mining
网格图中递增路径的数目[dfs逆向路径+记忆dfs]
2022-2028 global copper foil (thickness 12 μ M) industry research and trend analysis report
Lesson 13 of the Blue Bridge Cup -- tree array and line segment tree [exercise]
随机推荐
How many convolution methods does deep learning have? (including drawings)
多媒体NFT聚合平台OKALEIDO即将上线,全新的NFT时代或将来临
An academic paper sharing and approval system based on PHP for computer graduation design
A. Odd Selection【BruteForce】
2022-2028 global lithium battery copper foil industry research and trend analysis report
Change the single node of Postgres database into master-slave
How to draw non overlapping bubble chart in MATLAB
English grammar_ Noun classification
SDNUOJ1015
[combinatorics] exponential generating function (concept of exponential generating function | permutation number exponential generating function = combinatorial number ordinary generating function | e
ES7 - Optimization of promise
Have you learned the correct expression posture of programmers on Valentine's day?
Torch learning notes (2) -- 11 common operation modes of tensor
Bidding procurement scheme management of Oracle project management system
2022-2028 global solid phase extraction column industry research and trend analysis report
PHP determines which constellation it belongs to today
What problems can cross-border e-commerce sellers solve with multi platform ERP management system
041. (2.10) talk about manpower outsourcing
Real time split network (continuous update)
Opencv learning notes (continuously updated)