Boost中的协程—Boost.Asio中的stackful协程

Boost.asio中stackful协程是由Boost::Asio::spawn开启的,文档说,spawn是协程的一种高层次的封装,spawn由许多版本,多用以下定义:

template<
    typename Function>
void spawn(
    const boost::asio::io_context::strand & s,
    Function && function,
    const boost::coroutines::attributes & attributes = boost::coroutines::attributes());

function定义中用到了yield_context,从名字看是协程执行时的上下文,对其描述的相关文档不多,在异步操作函数中,它可以代替handler函数,可以有两种方式来理解其效果:

  1. 运行到非阻塞函数(向io_context提交任务,这里为方便用A表示,运行任务A),返回,即跳出该函数,记录为代码点1,将控制权交给io_context,io_context的任务队列中如有其他任务(为方便用B表示),则执行任务B,当任务A成后,重新进入代码点1的函数,接着代码点1继续运行
  2. 虽然是非阻塞函数(向io_context提交任务,这里为方便用A表示,运行任务A),但“阻塞”了当前执行的代码(用代码点1表示),将控制权交给io_context,io_context的任务队列中如有其他任务(为方便用B表示),则执行任务B,当“阻塞”的任务完(任务A)成后,接着“阻塞”的代码(代码点1)继续运行。

以上方式1就是典型的协程方式,方式2则更“直白“些。

作为对比,如果不采用协程,而用异步回调函数的话,以上的运行顺序可能是:提交任务A,继续执行代码,执行任务A或B,也就是说,代码点1之后的代码是先于任务A完成之前运行,它们之间并没有如代码顺序那样先后运行。

可以通过以下的示例来理解上面的运行顺序。

	void other_work()
	{
	  std::cout << "Other work" << std::endl;
	}
	void echo(boost::asio::io_context &io_context, boost::asio::yield_context context)
	{
	     io_context.post(&other_work);	 
		 boost::system::error_code  ec;
		boost::asio::ip::tcp::endpoint endp(boost::asio::ip::address_v4::from_string("127.0.0.1"),8000);
		boost::asio::ip::tcp::socket sock(io_context);
		sock.async_connect(endp,context);
		std::cout << "connect ends" << std::endl;	
		char *request="GET / HTTP/1.1\r\nAccept: */*\r\n\r\n";
		sock.async_write_some(boost::asio::buffer(request, strlen(request)),context[ec]);
		std::cout << "write ends" << std::endl;	
		char data[10096];
		memset(data,0,sizeof(data));
		size_t len=sock.async_read_some(boost::asio::buffer(data, sizeof(data)), context[ec]);
		std::cout << "read ends: " <<len<< std::endl;	
		std::cout << data << std::endl;			
		sock.close();	}
	void demo1()
	{
	boost::asio::io_context io_service;
    spawn(io_service, [&](boost::asio::yield_context context)
      {
		  io_service.post(&other_work);
		  boost::asio::deadline_timer timer(io_service);
		  timer.expires_from_now(boost::posix_time::seconds(10));
		  std::cout << "Start wait" << std::endl;
		  timer.async_wait(context);
		  std::cout << "Woke up" << std::endl;
	  }); 
  	  io_service.run();
	}
	static void demo2()
	{
		boost::asio::io_context io_context;
		spawn(io_context, [&io_context](boost::asio::yield_context context)
		  {
			 echo(io_context,context);
		  }); 		 
		io_context.run();
	}

Demo1的运行结果
Start wait
Other work
Woke up

Demo2的运行结果
connect ends
write ends
read ends: …    以下是字节数和内容

可以看出,上面运行的异步函数似乎变成同步(阻塞)了,在“阻塞”期间,控制权在io_context(其实是操作系统)手中,还可以运行其他任务。

以上两个示例仅用于演示,未考虑其他因素。

 

【目前版本spwan(boost v1.67)用到了Boost.Coroutine,而Boost.Coroutine已被标记为deprecated,导致编译warning,Boost.Coroutine又用到了Boost.Context,Boost.Context才是保存运行环境用到的库,它与操作系统相关,所以要使示例能够编译成功,需要已编译好的Boost.Coroutine,Boost.Thread,Boost.Context三个库,且注意它们在连接命令中出现的顺序。Boost.Coroutine2时,仅依赖,Boost.Context了。】

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值