受到avplayer群里的aver的影响,我也开始对asio感兴趣了,本着啥都要参和参和的思想,我也来搞一把asio,学到点东西就记录一下,由于是初学,可能会有很多错误,各位看官如果发现问题请不吝赐教或者尽情开喷。
一般来说大多数人使用asio都是用它来做异步的网络库来使用,但是asio本质上是一个通用的异步库,并不是只能用来做网络通信,所以我不打算一上来就搞网络方面的东西。
异步的概念其实很简单,你把要做的事情告诉可以完成这件事的库或者操作系统,由库或者系统帮你完成并通知你,在此期间你可以做其他的操作。
asio 异步的核心其实就是一个boost::asio::io_service类,可以想象成是一个发动机,你有事情要做,就扔给他,他就帮你完成,你把事情告 诉他之后并不需要一直等待事情的完成,而是可以马上去做其他的事情。其中类的成员函数post()就是提交要做的事情,成员函数run()就是启动发动机。就像下面的代码:
#include <boost/asio.hpp>
#include <iostream>
void foo()
{
std::cout << "Hello asio!" << std::endl;
}
int main(int argc, char* argv[])
{
boost::asio::io_service ios;
ios.post(foo);
std::cout << "after post" << std::endl;
ios.run();
return 0;
}
运行结果:
可以看到提交了“任务”之后并没有马上执行,而是等到了run的时候才执行的。看起来很简单是吧,那就再加点东西,假设foo函数式是统提供的,但是提供了个回调函数在完成后会进行调用来通知我们,代码就变成这样了:
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <iostream>
#include <functional>
typedef std::function<void()> handler_t;
void foo(handler_t handler)
{
std::cout << "Hello asio!" << std::endl;
handler();
}
void handler_fun()
{
std::cout << "mission complete!" << std::endl;
}
int main(int argc, char* argv[])
{
boost::asio::io_service ios;
ios.post(boost::bind(foo, handler_fun));
std::cout << "after post" << std::endl;
ios.run();
return 0;
}
运行结果:
其实asio的网络操作函数也与此类似,foo是执行指定任务的函数,执行完后就调用我们的handler来通知我们,这样我们就可以不用一直等待操作完成,立即去执行其他的任务。
这样做还有一个优点是可以在多个线程上执行run函数,可以更充分利用多核的性能,“任务”并不是在提交任务的线程中执行的,而是在执行run的线程中执行 的,如果多个线程同时执行同一个io_service对象的run函数,则会每个线程都去从这个service的“任务列表”里面获取任务去执行。
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <boost/thread.hpp>
#include <iostream>
void foo()
{
std::cout << "Hello asio! thread ID:" << boost::this_thread::get_id() << std::endl;
}
int main(int argc, char* argv[])
{
boost::asio::io_service ios;
for (int i = 0; i < 1000; ++i)
{
ios.post(foo);
}
boost::thread_group thrds;
for (int i = 0; i < 4; ++i)
{
thrds.create_thread(boost::bind(&boost::asio::io_service::run, &ios));
}
thrds.join_all();
return 0;
}
运行结果如下:
为了简单起见没有加锁,所以会有换行不正常的现象,希望大家不要介意。。。但是还是很容易看出这些代码是在不同的线程中执行的。
本文转自:往事如风