C++20拥有一个全新的特性:协程。
我来从python的角度来解释C++这个特性设计与其他语言的不同,目的以及意义。
协程是一种可以挂起和恢复执行的函数。C++20协程跟python的生成器是很相似的,如果函数中出现了co_yield, co_return, co_await,那么这个函数就是协程函数。而协程的本质就是将一个函数拆分成多个不能控制执行顺序,但是可以控制执行时机的语言结构。
对普通函数而言,执行一个函数是开始运行你的逻辑;但是对于协程来说,执行协程函数会先创建一个协程对象,但是是否开始执行还是挂起是视情况而定的。
例如这个python代码:
def hello():
print("Start run")
ret = yield2
print("After suspend", ret)
yield3
print("After Suspend")
def main():
generator=hello()
print(generator)
ret1 = next(generator)
print("ret1: ", ret1)
ret2 = generator.send(23)
print("ret2: ", ret2)
generator.send(23)
在这里hello就是一个协程函数,执行之后会获得一个generator,对generator执行send或者next才会开始真正的执行协程逻辑,从头或者从上次执行的地方一直直行到下一个yield,然后再挂起返回给外面。
python的生成器跟C++协程很像,都是无栈协程,但是C++的更复杂,因为C++是需要自定义协程对象。
例如这个简单的C++逻辑:
TaskCoroutine task_func() {
std::cout << "task first run" << std::endl;
co_yield 6;
std::cout << "---before await task2---" << std::endl;
co_await task2();
std::cout << "task resume" << std::endl;
co_return 3;
}
int main() {
std::cout << "Before task_func" << std::endl;
TaskCoroutine load_task = task_func();
std::cout << "After task_func" << std::endl;
load_task.resume();
std::cout << "After resume" << std::endl;
return 0;
}
这里因为有co_yield,所以task_func是一个协程函数,但是跟python不同,C++需要定义携程的返回类型,是一个自定义类型,代表的这个携程的Task或者Coroutine。
这个类型类型必须包含promise_type名字的PromiseType类,例如:
struct TaskCoroutine
{
using promise_type = PromiseType;
}
没有这个那编译就会异常,感觉这个是类似于C++20的概念约束做的。
promise_type又是另外一个约束的类,必须拥有几个必须定义的函数,以及几个可选定义的函数:
struct PromiseType {
PromiseType()
{
std::cout << "PromiseType" << std::endl;
}
TaskCoroutine get_return_object() {
std::cout << "get_return_object" << std::endl;
return TaskCoroutine{std::coroutine_handle<PromiseType>::from_promise(*this)};
}
std::suspend_never initial_suspend() noexcept {
std::cout << "initial_suspend" << std::endl;
return {};
}
Awaiter<true> final_suspend() noexcept {
std::cout << "final_suspend" << std::endl;
return {};
}
void unhandled_exception() {
std::cout << "unhandled_exception" << std::endl;
}
std::suspend_always yield_value(int x) noexcept {
std::cout << "yield_value" << std::endl;
return {};
}
void return_value(int x) noexcept {
std::cout << "return_value" << std::endl;
}
};
剩下的内容实在是不想写了,看我的视频吧:
https://www.bilibili.com/video/BV1H66aYTE84