Boost.asio C + + Network programming translator (13)

Source: Internet
Author: User

Asynchronous work asynchronous work involves not only asynchronously accepting a client-to-server connection, asynchronously reading from or writing to a socket. It contains all the operations that can be performed asynchronously. By default, you are not aware of the order in which each asynchronous handler is called. In addition to the usual asynchronous calls (read/write/accept from asynchronous sockets). You can use Service.post () to make your custom method be called asynchronously. For example:

#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 <; ++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::p osix_time::millisec (500));

Threads.join_all ();

}

In the example above, Service.post (some_function) Adds an asynchronous method call. This method requests the Io_service instance in a thread that calls Service.run (), and then returns immediately after the given Some_funtion is called. In our example, this thread is one of the three threads we created earlier. You cannot determine the order of asynchronous method calls. You don't expect them to be called in the order that we call the post () method. Here are the possible results from running the previous code:

Func called, i= 0

Func called, i= 2

Func called, i= 1

Func called, i= 4

Func called, i= 3

Func called, i= 6

Func called, i= 7

Func called, i= 8

Func called, i= 5

Func called, i= 9

Sometimes you want to have some asynchronous processing methods executed sequentially. For example, you go to a restaurant (go_to_restaurant), place a order, and then eat (EAT). You need to go to the restaurant first and then place your order and eat it last. In this case, you need to use the Io_service::strand, which will let your async method be called sequentially. Look at the following example:

using namespace Boost::asio;

Io_service Service;

void func (int i) {

Std::cout << "Func called, i=" << i << "/"

<< boost::this_thread::get_id () << Std::endl;

}

void Worker_thread () {

Service.run ();

}

int main (int argc, char* argv[])

{

Io_service::strand Strand_one (Service), strand_two (service);

for (int i = 0; i < 5; ++i)

Service.post (Strand_one.wrap (Boost::bind (func, i));

for (int i = 5; i <; ++i)

Service.post (Strand_two.wrap (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::p osix_time::millisec (500));

Threads.join_all ();

}

In the above code, we guarantee that the previous 5 threads and the next 5 threads are executed sequentially. Func called, i = 0 is called before func called, i = 1, and then called func called, I = 2 ... Similarly func called, i = 5 before the func called, I = 6, func called, i = 6 in func called, I = 7 are called ... You need to be aware that although methods are called sequentially, they do not mean that they are executed on the same thread. One possible result of running this program would be as follows:

Func called, i= 0/002a60c8

Func called, i= 5/002a6138

Func called, i= 6/002a6530

Func called, i= 1/002a6138

Func called, i= 7/002a6530

Func called, i= 2/002a6138

Func called, i= 8/002a6530

Func called, i= 3/002a6138

Func called, i= 9/002a6530

Func called, i= 4/002a6138


Asynchronous post () vs dispatch () vs wrap ()

Boost.asio provides three ways that you could add a processing method to an asynchronous call:

Service.post (Handler): This method ensures that it returns immediately after the request Io_service instance invokes the specified processing method. Handler will be called later in a thread that calls Service.run () .

Service.dispatch (Handler): This method requests the Io_service instance to invoke the given processing method, but in addition, if the current thread calls Service.run (), it can call handler directly in the method.

Service.wrap (Handler): This method creates a wrapper method that calls Service.dispatch (handler) when it is called, which is a bit confusing, and then I'll simply explain what it means.

In the previous chapters you will see an example of Service.post () and a possible result of running this example. Let's make some changes to it and then look at the service.

Dispatch () How the results of the output are affected:

using namespace Boost::asio;

Io_service Service;

void func (int i) {

Std::cout << "Func called, i=" << i << Std::endl;

}

void Run_dispatch_and_post () {

for (int i = 0; i <; i + = 2) {

Service.dispatch (Boost::bind (func, i));

Service.post (Boost::bind (func, i + 1));

}

}

int main (int argc, char* argv[]) {

Service.post (Run_dispatch_and_post);

Service.run ();

}

Before explaining what happened, we ran the program and observed the results:

Func called, i= 0

Func called, i= 2

Func called, i= 4

Func called, i= 6

Func called, i= 8

Func called, i= 1

Func called, i= 3

Func called, i= 5

Func called, i= 7

Func called, i= 9

The even output is first, then an odd number. This is because I output an even number with dispatch (), and then the post () output is odd. Dispatch () calls Hanlder before returning, because the current thread calls Service.run (), and post () returns immediately.

Now, let's talk about Service.wrap (handler). Wrap () returns an imitation function that can be used as a parameter to another method:

using namespace Boost::asio;

Io_service Service;

void Dispatched_func_1 () {

Std::cout << "dispatched 1" << Std::endl;

}

void dispatched_func_2 () {

Std::cout << "dispatched 2" << Std::endl;

}

void Test (Boost::function<void () > Func) {

Std::cout << "test" << Std::endl;

Service.dispatch (dispatched_func_1);

Func ();

}

void Service_run () {

Service.run ();

}

int main (int argc, char* argv[]) {

Test (Service.wrap (dispatched_func_2));

Boost::thread th (Service_run);

Boost::this_thread::sleep (boost::p osix_time::millisec (500));

Th.join ();

}

Test (Service.wrap (dispatched_func_2)); Dispatched_ func_2 is packaged to create an functor and pass it to test as a parameter. When test () is called, it distributes call Method 1 and then calls Func (). At this point, you will find that calling Func () and Service.dispatch (dispatched_func_2) are equivalent because they are called consecutively. The output of the program is as follows:

Test

Dispatched 1

Dispatched 2


Boost.asio C + + Network programming translator (13)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.