当前位置:网站首页>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 .

原网站

版权声明
本文为[It's haohaozi]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/184/202207031813135914.html

随机推荐