C++新特性 协程

简介: C++新特性 协程

本篇文章我们来讲述一下C++协程

协程(Coroutine)是一种能够挂起个恢复的函数过程 是一种轻量级的并发编程方式,也称为用户级线程。它与传统的线程(Thread)相比,具有更低的开销和更高的执行效率。 协程通常运用在异步调用中。

同步和异步 (拓展):同步是指线程要同时执行 如果没有两者没有同步 则需要线程A 等待线程B 或者主线程等待子线程  而异步编程就不需要线程的等待 但是也要注意线程争夺的问题

协程要讲清楚非常的抽象和复杂 我们直接从实际入手

代码实例:

大家看完以上代码结果可能会有一点懵 这是什么? 这是怎么回事?下面 让我们来分析一下代码:

大家观察这段代码就知道 main函数创建了一个进程 进程里面创建了一个主线程  然后执行每个函数就是子线程  先进入bar()函数  先执行call bar 然后执行before bar 经过挂起点然后挂起  这时候一个线程跳出了bar函数 到main里面 另一个线程执行fool函数  fool函数执行完以后 再回到bar 函数里面继续执行 这就是本代码的大概思路

下面我们来介绍一下   co_return 和co_await

co_return :co_return 是 C++20 中引入的关键字,用于在协程中返回结果或结束协程。它用于替代 return 关键字,在协程函数中表示返回值,并触发协程的完成。

co_return代码实例:

#include <iostream>
#include <experimental/coroutine>
std::experimental::coroutine_handle<> myCoroutine;
void myTask() {
    std::cout << "Starting coroutine..." << std::endl;
    myCoroutine.resume(); // 启动协程
    std::cout << "Resuming execution..." << std::endl;
}
struct MyAwaitable {
    bool await_ready() const { return false; }
    void await_suspend(std::experimental::coroutine_handle<> handle) const {
        myCoroutine = handle; // 将当前协程保存起来
    }
    void await_resume() const {}
};
MyAwaitable asyncFunc() {
    std::cout << "Suspending execution..." << std::endl;
    co_await MyAwaitable{}; // 挂起协程,等待恢复
    std::cout << "Resumed execution..." << std::endl;
}
int main() {
    myTask();
    asyncFunc().await_resume();
    
    return 0;
}

在这个示例中,co_await 表达式会挂起 asyncFunc() 协程的执行,然后将控制权交还给 myTask() 协程。当我们调用 myCoroutine.resume() 时,asyncFunc() 的执行恢复,并继续执行后面的语句。

co_await介绍:

co_await 是 C++20 中引入的关键字,用于在协程中挂起当前的执行,并等待某个操作完成或者恢复执行。它是协程内部使用的一种语法,用于表示异步操作的等待。

在一个可暂停函数(协程)中,当遇到 co_await 表达式时,会发生以下几个步骤:

  1. 暂停当前协程的执行,并保存当前状态。
  2. 将控制权返回给调用方(如上层协程或者普通函数)。
  3. 在某个事件发生或者异步操作完成后,恢复之前保存的状态并继续执行。

具体来说,在使用 co_await 时需要满足两个条件:

  1. 表达式必须是一个可暂停的类型(也称为 Awaitable 类型),它要么定义了 bool await_ready() 方法来判断是否可以直接返回结果,要么定义了 void await_suspend(std::coroutine_handle<>) 方法和 void await_resume() 方法来进行挂起和恢复操作。
  2. 协程函数本身必须是异步上下文(比如异步任务、生成器)或者包含了异步操作。

代码实例:

#include <iostream>
#include <experimental/coroutine>
struct MyAwaitable {
    bool await_ready() const { return false; }
    void await_suspend(std::experimental::coroutine_handle<> handle) const {
        std::cout << "Suspending coroutine..." << std::endl;
        handle.resume(); // 恢复协程的执行
    }
    void await_resume() const {}
};
std::experimental::suspend_always asyncFunc() {
    std::cout << "Starting coroutine..." << std::endl;
    co_await MyAwaitable{}; // 使用 co_await 挂起协程
    std::cout << "Resuming execution..." << std::endl;
}
int main() {
    auto coro = asyncFunc();
    coro.resume(); // 启动协程
    
    return 0;
}

代码总结:在这个示例中,MyAwaitable 是一个自定义的可暂停类型,它定义了 bool await_ready() 方法void await_suspend(std::coroutine_handle<>) 方法来控制协程的挂起和恢复。当我们调用 co_await MyAwaitable{} 时,协程会被挂起,并且打印出相应的消息。然后通过 handle.resume() 来恢复协程的执行。

co_await实现对象:

co_await 来实现协程等待一个对象时,该对象需要满足特定的条件和接口。在 C++ 中,需要实现以下几个关键的部分:

  1. 实现 awaitable 类型:这是一个自定义的类型,表示可以被协程等待的对象。它需要定义 await_ready()await_suspend()await_resume() 这三个成员函数。
  • await_ready(): 返回一个 bool 值,表示对象是否已经准备好(即不需要暂停协程)。如果对象已经可用,则返回 true;否则返回 false。
  • await_suspend(): 返回一个指定异步操作完成后应该如何恢复协程执行的 awaiter 类型。
  • await_resume(): 返回异步操作结果的值。

代码实例:

#include <iostream>
#include <future>
#include <experimental/coroutine>
struct Awaitable {
    std::future<int> fut;
    bool await_ready() {
        return fut.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
    }
    void await_suspend(std::experimental::coroutine_handle<> handle) {
        fut.then([handle](std::future<int> f) mutable {
            // 异步操作完成后恢复协程执行
            handle.resume();
        });
    }
    int await_resume() {
        return fut.get();
    }
};
Awaitable makeAsyncRequest() {
    std::promise<int> p;
    auto fut = p.get_future();
    // 模拟异步操作
    std::thread([&p]() mutable {
        std::this_thread::sleep_for(std::chrono::seconds(2));
        p.set_value(42);
    }).detach();
    return Awaitable{std::move(fut)};
}
std::experimental::suspend_always task() {
    auto result = co_await makeAsyncRequest(); // 等待异步操作完成,并获取结果
    std::cout << "Result: " << result << std::endl;
}
int main() {
   auto coro = task();
   coro.resume(); // 启动协程
   return 0;
}

总结:协程是应用于异步编程的一种方法 co_await函数用于当前的协程的挂起 这样可以更深层次的满足异步编程 要注意co_await函数的使用 co_return是用来返回结果和结束协程

好了 本篇内容就到这里 这篇文章可能有些难度 大家慢慢理解

在这里小编想向大家推荐一个课程:https://xxetb.xetslk.com/s/2PjJ3T

相关文章
|
1月前
|
编译器 程序员 定位技术
C++ 20新特性之Concepts
在C++ 20之前,我们在编写泛型代码时,模板参数的约束往往通过复杂的SFINAE(Substitution Failure Is Not An Error)策略或繁琐的Traits类来实现。这不仅难以阅读,也非常容易出错,导致很多程序员在提及泛型编程时,总是心有余悸、脊背发凉。 在没有引入Concepts之前,我们只能依靠经验和技巧来解读编译器给出的错误信息,很容易陷入“类型迷路”。这就好比在没有GPS导航的年代,我们依靠复杂的地图和模糊的方向指示去一个陌生的地点,很容易迷路。而Concepts的引入,就像是给C++的模板系统安装了一个GPS导航仪
105 59
|
1月前
|
存储 编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(三)
【C++】面向对象编程的三大特性:深入解析多态机制
|
1月前
|
存储 编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(二)
【C++】面向对象编程的三大特性:深入解析多态机制
|
1月前
|
编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(一)
【C++】面向对象编程的三大特性:深入解析多态机制
|
1月前
|
存储 安全 编译器
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(一)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
|
30天前
|
C++
C++ 20新特性之结构化绑定
在C++ 20出现之前,当我们需要访问一个结构体或类的多个成员时,通常使用.或->操作符。对于复杂的数据结构,这种访问方式往往会显得冗长,也难以理解。C++ 20中引入的结构化绑定允许我们直接从一个聚合类型(比如:tuple、struct、class等)中提取出多个成员,并为它们分别命名。这一特性大大简化了对复杂数据结构的访问方式,使代码更加清晰、易读。
32 0
|
2月前
|
编译器 C++ 计算机视觉
C++ 11新特性之完美转发
C++ 11新特性之完美转发
50 4
|
2月前
|
Java C# C++
C++ 11新特性之语法甜点1
C++ 11新特性之语法甜点1
33 4
|
2月前
|
安全 程序员 编译器
C++ 11新特性之auto和decltype
C++ 11新特性之auto和decltype
39 3
|
2月前
|
设计模式 缓存 安全
C++ 11新特性之week_ptr
C++ 11新特性之week_ptr
35 2