深入promise_type内部:揭开C++20协程状态管理的秘密

第一章:深入promise_type内部:揭开C++20协程状态管理的秘密

C++20 引入的协程特性为异步编程提供了语言级别的支持,而 `promise_type` 是协程状态管理的核心组件。每个协程在挂起、恢复和销毁过程中,都依赖于其关联的 `promise_type` 对象来维护执行上下文与控制流。

promise_type 的基本结构

每个协程返回类型必须定义一个嵌套的 `promise_type`,该类型提供协程生命周期的关键钩子函数。编译器会自动生成对这些方法的调用。
struct Task {
    struct promise_type {
        Task get_return_object() { /* 返回协程句柄 */ }
        std::suspend_always initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void return_void() {}
        void unhandled_exception() {}
    };
};
上述代码展示了最简化的 `promise_type` 实现。其中: - `get_return_object()` 在协程启动前被调用,用于构造返回值; - `initial_suspend` 控制协程是否在开始时挂起; - `final_suspend` 决定协程结束后是否保持挂起以允许外部清理; - `return_void` 处理无返回值的 `co_return` 语句。

状态存储与协程句柄交互

`promise_type` 不仅是控制协程行为的接口,还充当协程局部状态的存储容器。当协程被挂起时,其参数和局部变量可通过 `promise_type` 成员访问。
  • 协程句柄(`coroutine_handle`)可直接绑定到 `promise_type` 实例
  • 通过 `handle.promise()` 可获取引用,实现跨挂起点的状态共享
  • 异常处理逻辑可在 `unhandled_exception` 中统一捕获
方法名调用时机典型用途
get_return_object协程创建后立即调用返回用户可见的协程对象
initial_suspend协程函数体执行前决定是否延迟启动
final_suspend协程结束时等待异步操作完成

第二章:promise_type的核心机制与设计原理

2.1 理解协程框架中的promise_type角色

在C++20协程中,`promise_type` 是协程行为的核心控制机制。它定义了协程如何启动、暂停、返回值处理以及最终销毁。每个协程对象都关联一个 `promise_type` 实例,用于定制协程的生命周期逻辑。
基本结构与作用
`promise_type` 必须定义在可等待类型(如 `task`)的嵌套类中,并实现关键方法:`get_return_object()`、`initial_suspend()`、`final_suspend()` 和 `unhandled_exception()`。

struct Task {
    struct promise_type {
        Task get_return_object() { return {}; }
        std::suspend_always initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void unhandled_exception() { std::terminate(); }
    };
};
上述代码中,`initial_suspend` 控制协程是否立即执行;`get_return_object` 返回协程句柄。通过重写这些函数,开发者能精确控制协程状态机的行为路径,实现延迟启动或异步资源管理。
挂起点的调度控制
`promise_type` 还可通过返回不同 suspend 类型来决定挂起策略。例如,`std::suspend_always` 表示始终挂起,而 `std::suspend_never` 则不挂起。这种机制为异步任务提供了灵活的执行模型基础。

2.2 promise_type如何参与协程的创建与销毁

在C++协程中,`promise_type` 是协程状态的核心组成部分,由编译器在协程初始化时自动实例化。
构造与初始化阶段
当协程被调用时,编译器会创建一个协程帧(coroutine frame),并在其中构造 `promise_type` 实例。该实例通过 `get_return_object()` 提供对外可见的协程句柄。
struct Task {
    struct promise_type {
        Task get_return_object() { return Task{this}; }
        suspend_always initial_suspend() { return {}; }
        suspend_always final_suspend() noexcept { return {}; }
        void unhandled_exception() { std::terminate(); }
    };
};
上述代码中,`get_return_object()` 在协程启动时被调用,返回用户可操作的对象。
销毁与清理机制
当协程执行结束或异常终止时,`promise_type` 的 `final_suspend()` 决定是否挂起以等待外部清理。若返回 `suspend_never`,协程帧将立即释放,触发 `promise_type` 析构。
  • `initial_suspend` 控制协程启动后是否立即挂起
  • `final_suspend` 影响协程结束后的资源释放时机
  • 异常处理由 `unhandled_exception` 统一接管

2.3 协程句柄与promise对象的绑定过程

在协程启动时,运行时系统会自动生成一个协程句柄(coroutine handle)和一个promise对象。二者通过内部机制进行绑定,确保控制流与结果传递的正确性。
绑定流程解析
  • 协程函数被调用时,编译器生成promise对象实例
  • 运行时创建协程帧(coroutine frame),并将句柄指向该帧
  • promise地址被写入协程帧,实现句柄与promise的双向关联
struct promise_type {
    auto get_return_object() { 
        return std::coroutine_handle::from_promise(*this); 
    }
    auto initial_suspend() { return std::suspend_always{}; }
    void return_void() {}
    auto unhandled_exception() { std::terminate(); }
};
上述代码中,get_return_object 返回由当前promise生成的协程句柄,完成绑定。该句柄可用于外部控制协程的恢复与销毁,是用户与协程交互的核心接口。

2.4 自定义promise_type实现状态封装

在C++20协程中,`promise_type` 是协程状态管理的核心。通过自定义 `promise_type`,可精确控制协程的初始挂起、最终挂起、结果获取与异常处理。
核心成员函数
自定义 `promise_type` 需实现关键方法:
  • get_return_object():生成协程返回值对象
  • initial_suspend():决定是否初始挂起
  • final_suspend():决定协程结束时是否挂起
  • return_value(T):处理 return 语句传入的值
  • unhandled_exception():异常处理逻辑
struct MyPromise {
    int value;
    auto get_return_object() { return Task{Handle::from_promise(*this)}; }
    auto initial_suspend() { return std::suspend_always{}; }
    auto final_suspend() noexcept { return std::suspend_always{}; }
    void return_value(int v) { value = v; }
    void unhandled_exception() { std::terminate(); }
};
上述代码定义了一个携带整型结果的 promise。`get_return_object` 返回封装的 task 类型,`return_value` 将返回值存储于 promise 实例中,实现状态的安全封装与传递。

2.5 异常传播与final_suspend的协同机制

在协程执行过程中,异常的传播路径与 final_suspend 的挂起决策密切相关。当协程体抛出未捕获异常时,运行时会将异常对象转移至协程帧中,并在销毁前交由 promise 对象处理。
异常传递流程
  • 协程内部抛出异常后,控制流跳转至协程销毁逻辑
  • 运行时调用 promise 的 unhandled_exception() 保存异常
  • 随后触发 final_suspend() 决定是否挂起
代码示例
struct Task {
  struct promise_type {
    std::exception_ptr ex;
    void unhandled_exception() { ex = std::current_exception(); }
    suspend_always final_suspend() noexcept { return {}; }
  };
};
上述代码中,unhandled_exception() 捕获异常指针,而 final_suspend 返回 suspend_always 确保协程暂停,使调用方有机会通过 awaiter 重新获取并处理异常。

第三章:从编译器视角解析promise_type调用流程

3.1 编译器如何生成对promise_type成员的调用

在协程启动时,编译器会自动创建一个协程帧(coroutine frame),并查找返回类型中的嵌套 promise_type。该类型决定了协程的行为。
调用生成机制
编译器按固定规则插入对 promise_type 成员函数的调用:
  • get_return_object():创建返回值对象
  • initial_suspend():决定是否初始挂起
  • final_suspend():决定结束时是否挂起
  • unhandled_exception():异常处理
struct Task {
    struct promise_type {
        Task get_return_object() { return {}; }
        std::suspend_always initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void unhandled_exception() {}
    };
};
上述代码中,当函数返回 Task 时,编译器自动调用 promise_type 的各成员函数,构建协程控制流。每个调用都在特定生命周期阶段插入,实现无侵入式控制。

3.2 co_await、co_yield与promise_type的交互细节

C++20协程中,co_await和co_yield的操作行为由promise_type决定。当协程函数被调用时,编译器会生成一个协程帧,并通过promise_type管理其生命周期。
核心交互流程
  • co_yield value等价于co_await promise.yield_value(value)
  • co_await expr触发expr的await_ready、await_suspend和await_resume
  • promise.get_return_object()在协程启动时构造返回值
struct Task {
  struct promise_type {
    Task get_return_object() { return {}; }
    suspend_always initial_suspend() { return {}; }
    suspend_always final_suspend() noexcept { return {}; }
    void return_void() {}
    suspend_always yield_value(int) { return {}; }
  };
};
上述代码中,yield_value返回suspend_always,表示每次co_yield后协程挂起。该机制使promise_type能精确控制协程的暂停、恢复与结果传递,实现灵活的异步语义。

3.3 返回对象构造与get_return_object的时机分析

在协程执行流程中,`get_return_object` 是返回对象构造的关键入口点。该函数在协程初始挂起阶段被调用,负责创建并返回一个协程句柄可操作的对象实例。
调用时机与生命周期
  • 在协程首次被调用时立即触发
  • 早于 `initial_suspend` 的执行
  • 确保返回对象在协程上下文中始终可用
struct Task {
  struct promise_type {
    Task get_return_object() { 
      return Task{Handle::from_promise(*this)}; 
    }
    suspend_always initial_suspend() { return {}; }
    // ...
  };
};
上述代码中,`get_return_object` 构造并返回一个包含协程句柄的 `Task` 对象。此过程发生在协程栈帧初始化后、用户逻辑执行前,确保外部可及时获取协程控制权。返回对象的生存周期由外部持有者管理,直接影响协程状态的观察与等待机制。

第四章:构建可复用的协程任务类型

4.1 实现一个支持Awaitable的通用task类

在异步编程中,构建一个支持 `Awaitable` 协议的通用 `Task` 类是实现高效协程调度的核心。通过遵循 awaitable 对象必须具备 `__await__` 方法并返回迭代器的规则,可设计出既能被 `await` 又能管理执行状态的任务单元。
核心结构设计
一个通用 Task 需封装协程对象、运行状态及结果回调:
class Task:
    def __init__(self, coro):
        self.coro = coro
        self.done = False
        self.result = None

    def __await__(self):
        result = yield from self.coro
        return result
上述代码中,`__await__` 将协程的控制权交还事件循环,`yield from` 转发其内部的暂停与恢复机制。`Task` 实例因此可被 `await` 直接使用。
状态管理与扩展性
为增强实用性,Task 应支持添加完成回调、异常捕获等机制,使其成为事件驱动架构中的基本调度单位。

4.2 在promise_type中管理协程上下文状态

在C++协程中,`promise_type` 是协程状态管理的核心。通过自定义 `promise_type`,开发者可在协程句柄与调用方之间传递上下文数据。
状态存储与访问
`promise_type` 可内嵌成员变量,用于保存协程执行过程中的状态信息:
struct TaskPromise {
    int state = 0;
    std::suspend_always initial_suspend() { return {}; }
    auto return_void() { return std::suspend_never{}; }
    void unhandled_exception() {}
    Task get_return_object() { return Task{this}; }
};
上述代码中,`state` 成员可被协程内外安全访问,实现上下文共享。
生命周期协同
  • 协程启动时调用 initial_suspend()
  • 返回对象由 get_return_object() 构造
  • 异常处理交由 unhandled_exception()
这些方法共同维护协程状态的完整性。

4.3 支持链式调用与回调注册的扩展设计

为了提升API的可读性与灵活性,本设计引入链式调用与回调注册机制。通过返回实例自身(this 或对应对象指针),实现方法的连续调用。
链式调用实现
type Client struct {
    timeout int
    retries int
}

func (c *Client) SetTimeout(t int) *Client {
    c.timeout = t
    return c
}

func (c *Client) SetRetries(r int) *Client {
    c.retries = r
    return c
}
上述代码中,每个设置方法均返回指向当前实例的指针,允许连续调用如 client.SetTimeout(5).SetRetries(3),显著提升配置效率。
回调注册机制
支持在关键执行点注册回调函数,便于监控状态或注入逻辑:
  • 支持多回调注册,按注册顺序执行
  • 回调函数统一使用 func(*Response) 签名
  • 线程安全的注册与触发机制

4.4 资源清理与异常安全性的实践策略

在现代系统开发中,资源清理与异常安全性是保障程序健壮性的核心环节。未正确释放资源可能导致内存泄漏、文件句柄耗尽等问题。
RAII 与自动资源管理
通过构造函数获取资源,析构函数释放,确保异常发生时仍能正确清理。

class FileHandler {
    FILE* file;
public:
    FileHandler(const char* path) {
        file = fopen(path, "r");
        if (!file) throw std::runtime_error("无法打开文件");
    }
    ~FileHandler() { if (file) fclose(file); }
};
上述代码利用 C++ 的 RAII 机制,在栈对象析构时自动关闭文件,无需手动干预。
异常安全的三个级别
  • 基本保证:异常抛出后对象处于有效状态
  • 强保证:操作要么完全成功,要么回滚
  • 无异常保证:操作不会抛出异常
结合智能指针和异常安全准则,可大幅提升系统的稳定性。

第五章:总结与展望

技术演进的实际影响
在微服务架构中,服务间通信的稳定性直接影响系统整体表现。例如某电商平台在大促期间因服务雪崩导致订单丢失,通过引入熔断机制得以缓解。以下是使用 Go 实现简单熔断器的核心逻辑:

type CircuitBreaker struct {
    failureCount int
    threshold    int
    state        string // "closed", "open", "half-open"
}

func (cb *CircuitBreaker) Call(serviceCall func() error) error {
    if cb.state == "open" {
        return errors.New("circuit breaker is open")
    }
    if err := serviceCall(); err != nil {
        cb.failureCount++
        if cb.failureCount >= cb.threshold {
            cb.state = "open" // 触发熔断
        }
        return err
    }
    cb.failureCount = 0
    return nil
}
未来架构趋势的实践路径
企业级系统正逐步向边缘计算与服务网格融合。以下为某金融客户在生产环境中采用 Istio 进行流量管理的配置片段:
配置项值说明
trafficPolicyROUND_ROBIN负载均衡策略
outlierDetectionconsecutive_5xx:3自动剔除异常实例
timeout10s防止请求堆积
  • 零信任安全模型要求所有服务调用必须经过 mTLS 加密
  • 可观测性需集成分布式追踪(如 OpenTelemetry)
  • CI/CD 流水线应包含金丝雀发布验证环节
入口网关 认证服务 订单服务
YOLOv8作物病害检测实战源码 这是一套基于YOLOv8n的农田病虫害目标检测系统,对叶片照片做目标检测,识别健康叶片、褐斑病、白粉病、锈病四类,并给出对应防治建议。全流程纯CPU可跑,配套交付完整Python源码、9章实战教程(md/html/pdf三种格式)、100张自造样本及YOLO标签、训练曲线与混淆矩阵截图、Tkinter界面和答辩PPT。 系统围绕五项功能展开:同一套推理逻辑覆盖图像、视频、摄像头三种来源;图形界面选文件即检测,画面叠彩色框标注病名与置信度,右侧面板同步给出症状与防治措施;检测记录自动写入CSV,统计页一键生成四类病害占比饼图;训练结束自动产出损失与精度曲线;内置防治建议文案库,检测命中即回填面板。 选型用YOLOv8n nano档,参数量约320万、权重约6.2MB,CPU单帧几十毫秒,小样本训练5到8分钟完成。数据由data_gen.py程序化绘制100张叶片图,固定随机种子,重跑分布一致,不依赖公开数据集。依赖全部锁版本,教程第7章整理了19条真实报错及排查方法,第8章给出换模型档、换PlantVillage数据集的迁移路径。 适合做计算机视觉方向课程设计或毕业设计的学生,也适合智慧农业方向想了解检测模型如何落进业务面板的学习者。不需要GPU,不需要系统学过目标检测,教程第3章会按需补齐原理。 使用时先pip install -r requirements.txt装好依赖,download_data.py下载预训练权重,data_gen.py生成样本后train.py训练,完成后用main.py infer批量检测或main.py gui启动界面。 立即下载

相关推荐

数据挖掘实战:决策树 + 聚类 + 关联规则,零 Key 离线可跑(Python 源码)

数据挖掘实战包。用 Python 标准库实现 CART 风格决策树、K-Means 聚类与 Apriori 关联规则,在虚构「星河便利店」会员表和购物篮上跑通分类、分群与购物篮分析,并给出准确率、轮廓系数、支持度/置信度/提升度。零第三方依赖、零 API Key 即可离线跑通。含 4 个样例、离线冒烟、中文 README(含「使用方法」)。均为作者原创可运行源码。MIT。作者 blog.youkuaiyun.com/mtl1994

产业园区运营负责人如何利用平台实现企业创新需求的精准分析与服务推送?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

科技中介服务机构在技术供需对接中如何实现服务流程的自动化与标准化?.docx

科技中介服务机构在技术供需对接中如何实现服务流程的自动化与标准化?

高校技术转移办公室人员在推动成果转化落地过程中,如何实现科技成果的高效推介与价值评估?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

产业园区如何高效对接企业技术需求与高校科研成果?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

国央企创新负责人如何快速掌握本地科技资源分布与匹配情况?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

科技中介服务机构如何通过数智工具提升技术需求挖掘的精准度?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

国央企创新负责人如何实现科技成果的精准识别与高效筛选?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

政府科技管理者如何在政策支持中更精准地识别和支持高价值科技项目?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

高校技术转移办公室人员如何系统化管理科技成果信息?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

科技中介服务机构如何构建标准化、模块化的智能服务工具?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

全桥LLC谐振变化器参数设计资料(闭环仿真+参数设计报告)

内容概要:本文档系统性地介绍了全桥LLC谐振变换器的闭环仿真建模与关键参数设计方法,涵盖其工作原理、谐振元件(如谐振电感、谐振电容、励磁电感)的计算与优化流程,并结合Simulink或Plecs等仿真平台构建闭环控制系统模型,重点验证变频控制策略下的软开关实现、系统增益特性、效率优化及动态响应性能。资料包含完整的仿真模型、参数设计报告、数学计算书及参考文献,支持从理论分析到工程实践的全流程研究,适用于高频高效DC-DC变换器的研发与教学应用。; 适合人群:电力电子、电气工程及其自动化等相关专业的高校学生、科研人员,以及从事开关电源、新能源变换器、工业电源研发的工程技术人员,具备电路拓扑基础与仿真软件操作能力者更佳。; 使用场景及目标:①深入掌握全桥LLC谐振变换器的工作机理与谐振参数设计准则;②学习并实现闭环反馈控制系统的建模与稳定性分析;③支撑科研课题、课程设计、毕业设计或实际产品开发中的拓扑选型与性能验证需求;④通过仿真与计算联动提升对软开关技术与效率优化的理解与应用能力。; 阅读建议:建议结合所提供的仿真文件与设计文档同步操作,按照“建模—参数计算—仿真验证—性能分析”的流程逐步推进,重点关注频率调节对ZVS/ZCS实现的影响,对比不同负载条件下的闭环响应差异,深化对谐振腔特性和控制策略协同作用的理解。

fab-pm-optimizer-python-entry-py39-20261021-v1-1-0

fab-pm-optimizer-python-entry-py39-20261021-v1-1-0

政府科技管理者如何提升区域科技成果转化项目的评价与筛选效率?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

PSIM-三相维也纳VIENNA整流器电压电流双闭环+中点电位平衡SVPWM控制仿真

内容概要:本文档详细介绍了一种基于PSIM软件实现的三相维也纳(VIENNA)整流器仿真模型,重点实现了电压电流双闭环控制与中点电位平衡的SVPWM调制策略。该仿真系统通过精确的控制算法有效提升了整流器的功率因数,降低了输入电流谐波含量,并解决了三电平拓扑中常见的直流侧中点电位偏移问题,具有较高的工程实用价值,适用于高效率、高功率密度的电力电子系统设计与科研验证。文档还整合了丰富的配套资源,涵盖多种电力电子变换器拓扑结构、先进控制算法及典型应用场景,形成了系统化的技术资料体系,有助于深入理解现代整流技术的核心原理与发展动态。; 适合人群:面向从事电力电子、电气工程、新能源变换系统等领域的科研人员、高校研究生以及具备一定仿真基础的工程技术人员。; 使用场景及目标:①深入研究三相VIENNA整流器的工作机理与控制特性;②掌握电压外环、电流内环双闭环控制结构的设计方法;③理解并实现SVPWM调制技术与中点电位平衡控制策略的协同作用;④开展相关控制算法的仿真验证、性能优化与实验对比,为高性能整流装置的研发提供理论支撑和技术原型。; 阅读建议:建议结合文中列出的其他仿真案例(如PWM整流器、LLC谐振变换器、DAB变换器等)进行横向对比学习,充分利用所提供的PSIM、MATLAB/Simulink等多平台仿真资源,重点关注控制逻辑与主电路的耦合关系,通过参数调试与波形分析深化对系统动态响应和稳态性能的理解,强化“理论—建模—仿真—优化”的闭环研究能力。

产业园区运营负责人如何利用数智工具提升园区企业的技术对接效率?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

jp-host-release.apk

jp-host-release.apk

ICD10 openGauss版

ICD10 openGauss版

上一篇: 【Spring Boot线程池调优实战】:从默认配置到生产级异步架构的跃迁之路
下一篇: 结构体内存浪费严重?,用alignas实现精准对齐的秘诀全公开
IterStream
博客等级 码龄1年 152粉丝 2112原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值