// asio_ioservice.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <iostream>
/*
asio是boost提供的一个c++异步编程模型库,其核心类io_service,在多线程编程里面提供了任务队列和任务分发功能,
在socket、io编程里主要作为一个事件驱动器(完成端口、select、poll、epoll等)。以下是我们常用对象:
boost::asio::ip::tcp::socket
boost::asio::ip::tcp::acceptor
boost::asio::ip::udp::socket
这些对象的构造函数里都有一个必须的参数就是io_service&,也就是说每个异步对像都需要1个io_service。但可以共用一个公共的io_service。
*/
int test_run()
{
boost::asio::io_service io_service;
boost::asio::io_service::work work(io_service);
io_service.run();
std::cout << "Do you reckon this line displays?" << std::endl;
return 0;
}
/*
运行这个示例,我们获得之前同样的输出。因为poll函数在没有任务运行时候不
会阻塞。poll函数简单执行当前任务组并且返回。
选择poll函数或者run函数取决于函数的设置。这些函数带来更多的兼容性,程序
员可以更好的调整程序。run函数将阻塞并等待任务,poll函数则不。
*/
int test_poll()
{
boost::asio::io_service io_service;
///< work是一个很小的辅助类,只支持构造函数和析构函数。 - 2018/05/14
///< 因此work如果析构,则io.run会在处理完所有消息之后正常退出。work如果不析构,则io.run会一直运行不退出。如果用户直接调用io.stop,则会让io.run立刻退出。 - 2018/05/14
boost::asio::io_service::work work(io_service);
for (int x = 0; x < 42; ++x)
{
io_service.poll();
std::cout << "Counter: " << x << std::endl;
}
return 0;
}
/*
如果我们想从io_service移除一个work对象。通过查看文档,没有函数提供此种
功能。为了实现此种功能,我们必须使用work对象的智能指针。
程序显示如何让从io_service移除work对象,这个功能对于我们优雅的关闭一个挂起的任务很重要。
*/
int test_shared_ptr()
{
boost::asio::io_service io_service;
///< io_service::work类可以使io_service::run函数在没有任务的时候仍然不返回,直至work对象被销毁。 - 2018/05/14
boost::shared_ptr< boost::asio::io_service::work > work(
new boost::asio::io_service::work(io_service)
);
///< 如果不调用reset,io.run会一直阻塞直到work析构掉 - 2018/05/14
work.reset();
///< Run方法执行队列中的所有任务,直到任务执行完毕。
io_service.run();
std::cout << "Do you reckon this line displays?" << std::endl;
return 0;
}
/*
注意:stop的作用->阻止队列外新的任务
不要期待stop能停止run线程退出,如果任务队列执行的时间较长,只有任务执行完成之后,run线程才真正退出;
stop函数的意义是阻止任务队列接收外面新的任务,比如stop之后再post任务,此时post无效。
假如stop之后任务队列还有一条未执行完的任务,在此任务执行完之前外面析构或是反初始化此条任务需要使用的实例对象,当然会产生core。
所以不能想当然认为stop就是run线程退出了,让任务队列里面任务不再执行,那是不行的。
stop阻止任务队列接收新任务,并在执行完成之后退出run线程,若已存在任务队列中的任务一直无法执行完,则无法退出run线程。
*/
/*
reset()的作用
在Windows下,boost::asio::io_service类里面有一个数据成员为"stopped_"(Flag to indicate whether the event loop has been stopped.)。
它是一个标志,它标志着事件循环是不是被stopped了。
而boost::asio::io_service::reset()函数仅仅是赋值"stopped_=0"。
简而言之,io.stop()负责阻止队列外新任务,work.reset()将_stop的标志位置位为0;
*/
int _tmain(int argc, _TCHAR* argv[])
{
test_poll();
test_shared_ptr();
system("pause");
return 0;
}
// Test_ThreadPool.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <iostream>
boost::asio::io_service io_service;
/*
程序显示如何让从io_service移除work对象,这个功能对于我们优雅的关闭一个挂起的任务很重要。
多线程下呼叫run函数设置执行处理器的线程池。池中等待的线程是同等优先级,io_service随机选择一个触发处理器。
*/
void WorkerThread()
{
std::cout << "Thread Start\n";
io_service.run();
std::cout << "Thread Finish\n";
}
/*
示例介绍stop成员函数。
stop成员函数将发信号给io_service,提示所有任务将停止。
所以在当前任务结束后,不再有任务发起。示例中另一个变化就是io_service对象成为全局对象。
运行程序后将有4个线程开始传输信息,并且在我们敲击回车后停止。
*/
int main(int argc, char * argv[])
{
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;
boost::thread_group worker_threads;
for (int x = 0; x < 4; ++x)
{
worker_threads.create_thread(WorkerThread);
}
std::cin.get();
io_service.stop();
worker_threads.join_all();
system("pause");
return 0;
}
io_service对象是asio框架中的调度器,所有异步io事件都是通过它来分发处理的(io对象的构造函数中都需要传入一个io_service对象)。
asio::io_service io_service;
asio::ip::tcp::socket socket(io_service);
在asio框架中,同步的io主要流程如下:
-
应用程序调用IO对象成员函数执行IO操作
-
IO对象向io_service 提出请求.
-
io_service 调用操作系统的功能执行连接操作.
-
操作系统向io_service 返回执行结果.
-
io_service将错误的操作结果翻译为boost::system::error_code类型,再传递给IO对象.
-
如果操作失败,IO对象抛出boost::system::system_error类型的异常.
而异步IO的处理流程则有些不同:
-
应用程序调用IO对象成员函数执行IO操作
-
IO对象请求io_service的服务
-
io_service 通知操作系统其需要开始一个异步连接.
-
操作系统指示连接操作完成, io_service从队列中获取操作结果
-
应用程序必须调用io_service::run()以便于接收结果
-
调用io_service::run()后,io_service返回一个操作结果,并将其翻译为error_code,传递到事件回调函数中