行业知识
2403C++,C++11玩转无栈协程
2026-10-31 10:15:48
来源:互联网转载
原���
()C++11里也能玩无栈协程了?
答案是:可以!
事实上异网在很早时,C++11里就可用无栈协程写异步代码了,只不过用起来不太方便,来看看C++11里怎么用异网无栈协程写一个回音服务器的吧.
()#包含 #包含 #包含 #包含 用 异网::异步写;用 异网::缓冲;用 异网::ip::传控;用 异网::错误码;用 大小型;构 会话:异网::协程{ 共针套接字_; 共针缓冲_; 会话(共针 套接字) : 套接字_(套接字), 缓冲_(新 向量(1024)) { } 空 符号()(错误码 ec = 错误码(), 大小型 n = 0){ 如 (!ec) 再入 (本) { 对 (;;) { 产生 套接字_->异步读些(缓冲(*缓冲_), *本); 产生 异步写(*套接字_, 缓冲(*缓冲_, n), *本); } } }};构 服务器 : 异网::协程{ 异网::io服务& io服务_; 共针 受者_; 共针 套接字_; 服务器(异网::io服务& io服务) : io服务_(io服务), 受者_(新 传控::受者(io服务, 传控::端点(传控::v4(), 54321))) { } 空 符号()(错误码 ec = 错误码()){ 再入 (本) { 对 (;;) { 套接字_.重置(新 传控::套接字(io服务_)); 产生 受者_->异步接受(*套接字_, *本); io服务_.提交(会话(套接字_)); } } }};#包含 整 主(){ 异网::io服务 io服务; io服务.提交(服务器(io服务)); io服务.跑();} 先看回声会话部分的代码:
空 符号()(错误码 ec = 错误码(), 大小型 n = 0){ 如 (!ec) 再入 (本) { 对 (;;) { 产生 套接字_->异步读些(缓冲(*缓冲_), *本); 产生 异步写(*套接字_, 缓冲(*缓冲_, n), *本); } } }//其中对 (;;){ 产生 套接字_->异步读些(缓冲(*缓冲_), *本); 产生 异步写(*套接字_, 缓冲(*缓冲_, n), *本); } 和C++20的协程代码是不是很像:
对 (;;){ 协待 套接字_->异步读些(缓冲(*缓冲_), 异网::用可等待); 协待 异步写(*套接字_, 缓冲(*缓冲_, n), 异网::用可等待); } 所以C++11里面也是可通过协程来写异步代码的.
但是异网的无栈协程实现比较简陋,使用起来有不少约束.首先要把用无栈协程的文件用两个头文件包装起来,因为内部是宏实现的,编译完之后需要解定义.
#包含 #包含
第二个不便之处是不自由,使用协程的对象要从异网::协程继承,然后定义符号,注意该符号是怎么写的:
空 符号()(错误码 ec = 错误码(), 大小型 n = 0){ 如 (!ec) 再入 (本) { 对 (;;) { 产生 套接字_->异步读些(缓冲(*缓冲_), *本); 产生 异步写(*套接字_, 缓冲(*缓冲_, n), *本); } } } 相信你第一次看到该代码时会很懵,这是个啥意思,再入是什么鬼,看不懂该代码.不要着急,听我来给你解惑该符号.
参数是错误码和传输大小,最开始时是默认的,为何这两个参数呢?注意函数中的再入(本),它表明当前该函数是可重入的,则何时会重入呢?
每次产生返回时就重入了,产生之后ec和大小就是新的了.比如产生 套接字_->异步读些(缓冲(*缓冲_),*本);
返回后,就可得到错误码和读到的大小了,所以完整写法应该是:
空 符号()(错误码 ec = 错误码(), 大小型 n = 0){ 如 (!ec) 再入 (本) { 对 (;;) { 产生 套接字_->异步读些(缓冲(*缓冲_), *本); //协程重入 如(ec){ 输出 输出 再入 (本) { 对 (;;) { 套接字_.重置(新 传控::套接字(io服务_)); 产生 受者_-异步接受(*套接字_, *本); io服务_.提交(会话(套接字_)); } } } 如 (!ec) { 再入 (本) { 干 { 套接字_.重置(新 传控::套接字(受者_-取执行器())); 产生 受者_-异步接受(*套接字_, *本); 分叉 服务器(*本)(); //`分叉`之后父子协程都会往下执行到此 } 当 (是父()); 产生 套接字_-异步读些(缓冲(*缓冲_), *本); 产生 异步写(*套接字_, 缓冲(*缓冲_, n), *本); } }}
下一篇:服务器时间怎么显示的准?