吴江网站建设收费,做网站选择系统,网站建设创业经历,WordPress图片资源4041 介绍协程是比线程更加轻量级并发编程方式#xff0c;CPU资源在用户态进行切换,CPU切换信息在用户态保存。协程完成异步的调用流程#xff0c;并对用户展示出同步的使用方式。协程的调度由应用层决定#xff0c;所以不同的实现会有不同的调度方式#xff0c;调度策略比较灵…1 介绍协程是比线程更加轻量级并发编程方式CPU资源在用户态进行切换,CPU切换信息在用户态保存。协程完成异步的调用流程并对用户展示出同步的使用方式。协程的调度由应用层决定所以不同的实现会有不同的调度方式调度策略比较灵活。协程是基于线程之上运行同一个线程中协程是串行的不会产生线程资源的竞争不同的协程间却是相互交叉运行的只要依赖的线程没有终止协程最终会跳转回来。协程可以充分利用单核CPU的资源但是不太好利用多核CPU资源。c20 协程使用三大关键字 co_wait,co_return,co_yield 在函数中使用到以上关键字的函数被称为协程函数并且通过该关键字完成跳转。2 使用如果要使用协程函数需要定义promise_type以及基本成员函数实现。包括get_return_object、initial_suspend、final_suspend、unhandled_exception。演示代码最下面展示co_return 执行完协程函数并返回结果需要额外定义return_void函数。流程分析1 可以看出调用co_return跳转到return_voidreturn_void执行完后main函数向下执行。2 co_test1 end并没有打印说明协程函数co_test1分割开来通过co_return切换了CPU资源使主线程继续执行。 co_await 执行到异步操作处判断并进行挂起操作。使用co_await 还需要再定义xxxx类并实现await_ready、await_suspend、await_resume函数。1 协程函数中调用co_await后跳转xxx的await_ready并判断是否就绪如果是true则协程函数调回继续运行反之进入await_suspend挂起协程函数跳出直到调用await_resume后再次跳入协程函数执行余下操作。2 可以看到在“co_test2 result”打印之前main函数已执行完成等到await_resume后依然会跳回协程函数并执行余下部分。co_yield 让出操作需要额外定义yield_value函数。1 执行co_yield 会跳转到yield_value函数中通过resume以及promise操作获取结果。3 代码用例以下代码在linux下测试gcc版本需要 linux-gcc10.1以上。编译指令g faw.cpp -fcoroutines -stdc20#include iostream
#include coroutine
#include thread
#include functional
#include chronotemplate typename... Args
void print_log(const char* fmt, Args... args) {char log_buf[128] { 0 };snprintf(log_buf, 128, fmt, args...);char time_buf[64] { 0 };unsigned long tid pthread_self();char buf[160] { 0 };snprintf(buf, 160, [%lu] [%s], tid, log_buf);std::cout buf std::endl;
}using callback_t std::functionvoid(int);
void async_op(int value, callback_t cb) {std::thread t([value, cb]() {std::this_thread::sleep_for(std::chrono::milliseconds(1000));cb(value1000);});t.detach();
}struct MyTask {struct promise_type;using handle_t std::coroutine_handlepromise_type; //yield操作MyTask() {}MyTask(handle_t handle): handle_(handle) {}struct promise_type {MyTask get_return_object() {print_log(get_return_object beg);return MyTask(handle_t::from_promise(*this));}std::suspend_never initial_suspend() {print_log(initial_suspend beg);return std::suspend_never();}std::suspend_never final_suspend() noexcept {print_log(final_suspend beg);return std::suspend_never();}//co_returnvoid return_void() {print_log(return_void beg);std::this_thread::sleep_for(std::chrono::milliseconds(1000)); //测试异步}void unhandled_exception() {}//co_yieldauto yield_value(int v) {data_ v;return std::suspend_always();}int data_ 0;};int get_value() {handle_.resume();if(!handle_.done()){return handle_.promise().data_;}return -1;}handle_t handle_;
};//co_await操作
class AwaitOp {
public:AwaitOp(int value): input_(value), result_(0) {}bool await_ready() {print_log(await_ready beg);std::this_thread::sleep_for(std::chrono::milliseconds(1000)); //测试阻塞情况return false;}void await_suspend(std::coroutine_handle handle) {auto cb [handle, this](int value) mutable {result_ value;print_log(----------);handle.resume(); //执行完后调回};async_op(input_, cb);}int await_resume() {print_log(await_resume beg);return result_;}
private:int input_;;int result_;
};#if 1
MyTask co_test1(){print_log(co_test1 beg);co_return; //业务跳转协程函数退出print_log(co_test1 end);
}MyTask co_test2(){print_log(co_test2 beg);int input 999;int result co_await AwaitOp(input); //业务跳转协程函数退出print_log(co_test2 result%d,result);co_return;print_log(co_test2 end);
}#endif
MyTask co_test3_2(){print_log(co_test3_2 beg);int t 99;co_yield t; //切换出去print_log(co_test3_2 end);
}void co_test3(){MyTask task co_test3_2();int result task.get_value(); //切换结果print_log(co_test3 result%d,result);
}int main() {print_log(main beg);co_test1(); //co_return测试//co_test2(); //co_await测试//co_test3(); //co_yield测试print_log(main end);getchar();return 0;
}