1484543d1Sopenharmony_ci## FFRT 用户编程指南 2484543d1Sopenharmony_ci 3484543d1Sopenharmony_ci> Function Flow编程模型是一种基于任务和数据驱动的并发编程模型,允许开发者通过任务及其依赖关系描述的方式进行应用开发。FFRT(Function Flow运行时)是支持Function Flow编程模型的软件运行时库,用于调度执行开发者基于Function Flow编程模型开发的应用。通过Function Flow编程模型和FFRT,开发者可专注于应用功能开发,由FFRT在运行时根据任务依赖状态和可用执行资源自动并发调度和执行任务。 4484543d1Sopenharmony_ci> 5484543d1Sopenharmony_ci> 本文用于指导开发者基于Function Flow编程模型和FFRT实现并行编程。 6484543d1Sopenharmony_ci 7484543d1Sopenharmony_ci<hr/> 8484543d1Sopenharmony_ci# 版本 9484543d1Sopenharmony_ci 10484543d1Sopenharmony_ci| 版本 | 编辑 | 主要变更 | 日期 | 11484543d1Sopenharmony_ci| ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | ---------- | 12484543d1Sopenharmony_ci| V0.1 | linjiashu <br />zhangguowei <br />huangyouzhong | 发布以下API:<br />1. task 管理,包括:submit,wait,task_attr, task_handle/submit_h<br />2. 同步原语,包括:mutex,shared_mutex, condition_variable<br />3. Deadline 调度<br />4. 杂项:sleep,yield<br /> | 2022/09/26 | 13484543d1Sopenharmony_ci| V0.1.1 | shengxia | 部分描述更新 | 2023/08/24 | 14484543d1Sopenharmony_ci| V0.1.2 | wanghuachen | 新增串行队列相关接口以及说明,增加规范以避免double free问题 | 2023/10/07 | 15484543d1Sopenharmony_ci| V0.1.3 | shengxia | 优化串行队列内容描述 | 2024/01/12 | 16484543d1Sopenharmony_ci 17484543d1Sopenharmony_ci<br/> 18484543d1Sopenharmony_ci 19484543d1Sopenharmony_ci<hr/> 20484543d1Sopenharmony_ci# 缩写 21484543d1Sopenharmony_ci 22484543d1Sopenharmony_ci| 缩略语 | 英文全名 | 中文解释 | 23484543d1Sopenharmony_ci| ------------- | ------------------------------- | ------------------------------------------------------------ | 24484543d1Sopenharmony_ci| FFRT | Function Flow Run Time | 软件实现Function Flow运行时用于任务调度和执行 | 25484543d1Sopenharmony_ci| Function Flow | Function Flow Programming Model | Function Flow编程模型 | 26484543d1Sopenharmony_ci| Pure Function | Pure Function | 纯函数,注意本文中定义的纯函数指的是通过表达相互间数据依赖即可由调度系统保证正确执行的任务。 | 27484543d1Sopenharmony_ci 28484543d1Sopenharmony_ci 29484543d1Sopenharmony_ci<br/> 30484543d1Sopenharmony_ci<hr/> 31484543d1Sopenharmony_ci# 编程模型 32484543d1Sopenharmony_ci## 两种编程模型 33484543d1Sopenharmony_ci 34484543d1Sopenharmony_ci| | 线程编程模型 | FFRT任务编程模型 | 35484543d1Sopenharmony_ci| -------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | 36484543d1Sopenharmony_ci| 并行度挖掘方式 | 程序员通过创建多线程并把任务分配到每个线程中执行来挖掘运行时的并行度 | 程序员(编译器工具或语言特性配合)静态编程时将应用分解成任务及其数据依赖关系,运行时调度器分配任务到工作线程执行 | 37484543d1Sopenharmony_ci| 谁负责线程创建 | 程序员负责创建线程,线程编程模型无法约束线程的创建,滥用可能造成系统中大量线程 | FFRT运行时负责工作线程池的创建和管理由调度器负责,程序员无法直接创建线程 | 38484543d1Sopenharmony_ci| 负载均衡 | 程序员静态编程时将任务映射到线程,映射不合理或任务执行时间不确定造成线程负载不均 | FFRT运行时根据线程执行状态调度就绪任务到空闲线程执行,减轻了线程负载不均问题 | 39484543d1Sopenharmony_ci| 调度开销 | 线程调度由内核态调度器完成,调度开销大 | FFRT运行时在用户态以协程方式调度执行,相比内核线程调度机制更为轻量,减小调度的开销,并可通过硬化调度卸载进一步减小调度开销 | 40484543d1Sopenharmony_ci| 依赖表达 | 线程创建时即处于可执行状态,执行时与其他线程同步操作,增加线程切换 | FFRT运行时根据任务创建时显式表达的输入依赖和输出依赖关系判断任务可执行状态,当输入依赖不满足时,任务不被调度执行 | 41484543d1Sopenharmony_ci 42484543d1Sopenharmony_ci 43484543d1Sopenharmony_ci 44484543d1Sopenharmony_ci## Function Flow 任务编程模型 45484543d1Sopenharmony_ci 46484543d1Sopenharmony_ciFunction Flow编程模型允许开发者通过任务及其依赖关系描述的方式进行应用开发,其主要特性包括`Task-Based` 和 `Data-Driven` 。 47484543d1Sopenharmony_ci 48484543d1Sopenharmony_ci### Task-Based 特性 49484543d1Sopenharmony_ci 50484543d1Sopenharmony_ci`Task-Based` 指在Function Flow编程模型中开发者以任务方式来组织应用程序表达,运行时以任务粒度执行调度。 51484543d1Sopenharmony_ci 52484543d1Sopenharmony_ci任务定义为一种面向开发者的编程线索和面向运行时的执行对象,通常包含一组指令序列及其操作的数据上下文环境。 53484543d1Sopenharmony_ci 54484543d1Sopenharmony_ciFunction Flow编程模型中的任务包含以下主要特征: 55484543d1Sopenharmony_ci 56484543d1Sopenharmony_ci- 任务之间可指定依赖关系,依赖关系通过`Data-Driven`方式表达。 57484543d1Sopenharmony_ci- 任务可支持嵌套,即任务在执行过程中可生成新的任务下发给运行时,形成父子任务关系。 58484543d1Sopenharmony_ci- 多任务支持互同步操作,例如等待,锁,条件变量等。 59484543d1Sopenharmony_ci 60484543d1Sopenharmony_ci> 注意 61484543d1Sopenharmony_ci> 62484543d1Sopenharmony_ci> 任务颗粒度影响应用执行性能,颗粒度过小增加调度开销,颗粒度过大降低并行度。Function Flow编程模型中任务的目标颗粒度最小为100us量级,开发者应注意合理控制任务颗粒度。 63484543d1Sopenharmony_ci 64484543d1Sopenharmony_ci### Data-Driven 特性 65484543d1Sopenharmony_ci 66484543d1Sopenharmony_ci`Data-Driven`指任务之间的依赖关系通过数据依赖表达。 67484543d1Sopenharmony_ci 68484543d1Sopenharmony_ci任务执行过程中对其关联的数据对象进行读写操作。在Function Flow编程模型中,数据对象表达抽象为数据签名,每个数据签名唯一对应一个数据对象。 69484543d1Sopenharmony_ci 70484543d1Sopenharmony_ci数据依赖抽象为任务所操作的数据对象的数据签名列表,包括输入数据依赖`in_deps`和输出数据依赖`out_deps`。数据对象的签名出现在一个任务的`in_deps`中时,该任务称为数据对象的消费者任务,消费者任务执行不改变其输入数据对象的内容;数据对象的签名出现在任务的`out_deps`中时,该任务称为数据对象的生产者任务,生产者任务执行改变其输出数据对象的内容,从而生成该数据对象的一个新的版本。 71484543d1Sopenharmony_ci 72484543d1Sopenharmony_ci一个数据对象可能存在多个版本,每个版本对应一个生产者任务和零个,一个或多个消费者任务,根据生产者任务和消费者任务的下发顺序定义数据对象的多个版本的顺序以及每个版本所对应的生产者和消费者任务。 73484543d1Sopenharmony_ci 74484543d1Sopenharmony_ci数据依赖解除的任务进入就绪状态允许被调度执行,依赖解除状态指任务所有输入数据对象版本的生产者任务执行完成,且所有输出数据对象版本的所有消费者任务执行完成的状态。 75484543d1Sopenharmony_ci 76484543d1Sopenharmony_ci通过上述`Data-Driven`的数据依赖表达,FFRT在运行时可动态构建任务之间的基于生产者/消费者的数据依赖关系并遵循任务数据依赖状态执行调度,包括: 77484543d1Sopenharmony_ci 78484543d1Sopenharmony_ci- Producer-Consumer 依赖 79484543d1Sopenharmony_ci 80484543d1Sopenharmony_ci 一个数据对象版本的生产者任务和该数据对象版本的消费者任务之间形成的依赖关系,也称为Read-after-Write依赖。 81484543d1Sopenharmony_ci 82484543d1Sopenharmony_ci- Consumer-Producer 依赖 83484543d1Sopenharmony_ci 84484543d1Sopenharmony_ci 一个数据对象版本的消费者任务和该数据对象的下一个版本的生产者任务之间形成的依赖关系,也称为Write-after-Read依赖。 85484543d1Sopenharmony_ci 86484543d1Sopenharmony_ci- Producer-Producer 依赖 87484543d1Sopenharmony_ci 88484543d1Sopenharmony_ci 一个数据对象版本的生产者任务和该数据对象的下一个版本的生产者任务之间形成的依赖关系,也称为Write-after-Write依赖。 89484543d1Sopenharmony_ci 90484543d1Sopenharmony_ci 91484543d1Sopenharmony_ci例如,如果有这么一些任务,与数据A的关系表述为: 92484543d1Sopenharmony_ci```{.cpp} 93484543d1Sopenharmony_citask1(OUT A); 94484543d1Sopenharmony_citask2(IN A); 95484543d1Sopenharmony_citask3(IN A); 96484543d1Sopenharmony_citask4(OUT A); 97484543d1Sopenharmony_citask5(OUT A); 98484543d1Sopenharmony_ci``` 99484543d1Sopenharmony_ci 100484543d1Sopenharmony_ci<img src="images/image-20220926150341102.png" style="zoom:60%" /> 101484543d1Sopenharmony_ci 102484543d1Sopenharmony_ci> 为表述方便,本文中的数据流图均以圆圈表示 Task,方块表示数据。 103484543d1Sopenharmony_ci 104484543d1Sopenharmony_ci可以得出以下结论: 105484543d1Sopenharmony_ci- task1 与task2/task3 构成Producer-Consumer 依赖,即:task2/task3 需要等到task1 写完A之后才能读A 106484543d1Sopenharmony_ci- task2/task3 与task4 构成Consumer-Producer 依赖,即:task4 需要等到task2/task3 读完A之后才能写A 107484543d1Sopenharmony_ci- task4 与task5 构成Producer-Producer 依赖,即:task5 需要等到task4 写完A之后才能写A 108484543d1Sopenharmony_ci 109484543d1Sopenharmony_ci 110484543d1Sopenharmony_ci 111484543d1Sopenharmony_ci# C++ API 112484543d1Sopenharmony_ci 113484543d1Sopenharmony_ci> C++ API采用接近C++11的命名风格,以`ffrt`命名空间替代`std`命名空间 114484543d1Sopenharmony_ci> 需编译使用-std=c++17 115484543d1Sopenharmony_ci 116484543d1Sopenharmony_ci## 任务管理 117484543d1Sopenharmony_ci### submit 118484543d1Sopenharmony_ci<hr/> 119484543d1Sopenharmony_ci* 向调度器提交一个task 120484543d1Sopenharmony_ci* 该接口是异步的,即该接口不等到task完成即可返回,因此,通常与[wait](#wait) 配合使用 121484543d1Sopenharmony_ci 122484543d1Sopenharmony_ci* 建议FFRT任务上下文使用ffrt::mutex替代std::mutex 123484543d1Sopenharmony_ci * API上,二者仅在命令空间上有差异,可平滑替换(ffrt::mutex可在非ffrt task中调用,效果与普通的锁一致) 124484543d1Sopenharmony_ci * ffrt::mutex相对std::mutex开销更小,且不会阻塞FFRT的worker线程(提交到FFRT的任务中大量使用std::mutex有FFRT worker线程被耗尽而死锁的风险) 125484543d1Sopenharmony_ci 126484543d1Sopenharmony_ci#### 声明 127484543d1Sopenharmony_ci 128484543d1Sopenharmony_ci```{.cpp} 129484543d1Sopenharmony_cinamespace ffrt { 130484543d1Sopenharmony_civoid submit(std::function<void()>&& func, const std::vector<const void*>& in_deps = {}, const std::vector<const void*>& out_deps = {}, const task_attr& attr = {}); 131484543d1Sopenharmony_civoid submit(const std::function<void()>& func, const std::vector<const void*>& in_deps = {}, const std::vector<const void*>& out_deps = {}, const task_attr& attr = {}); 132484543d1Sopenharmony_ci} 133484543d1Sopenharmony_ci``` 134484543d1Sopenharmony_ci 135484543d1Sopenharmony_ci#### 参数 136484543d1Sopenharmony_ci 137484543d1Sopenharmony_ci`func` 138484543d1Sopenharmony_ci 139484543d1Sopenharmony_ci* 可被std::function 接收的一切CPU 可执行体,可以为C++ 定义的Lambda 函数闭包,函数指针,甚至是函数对象 140484543d1Sopenharmony_ci 141484543d1Sopenharmony_ci`in_deps` 142484543d1Sopenharmony_ci 143484543d1Sopenharmony_ci* 该参数是可选的 144484543d1Sopenharmony_ci* 该参数用于描述该任务的输入依赖,FFRT 通过数据的虚拟地址作为数据的Signature 来建立依赖 145484543d1Sopenharmony_ci 146484543d1Sopenharmony_ci`out_deps` 147484543d1Sopenharmony_ci 148484543d1Sopenharmony_ci* 该参数是可选的 149484543d1Sopenharmony_ci* 该参数用于描述该任务的输出依赖 150484543d1Sopenharmony_ci* `注意`:该依赖值本质上是一个数值,ffrt没办法区分该值是合理的还是不合理的,会假定输入的值是合理的进行处理;但不建议采用NULL,1, 2 等值来建立依赖关系,建议采用实际的内存地址,因为前者使用不当会建立起不必要的依赖,影响并发 151484543d1Sopenharmony_ci 152484543d1Sopenharmony_ci`attr` 153484543d1Sopenharmony_ci 154484543d1Sopenharmony_ci* 该参数是可选的 155484543d1Sopenharmony_ci* 该参数用于描述Task 的属性,比如qos 等,详见 [task_attr](#task_attr)章节 156484543d1Sopenharmony_ci 157484543d1Sopenharmony_ci#### 返回值 158484543d1Sopenharmony_ci 159484543d1Sopenharmony_ci* 不涉及 160484543d1Sopenharmony_ci 161484543d1Sopenharmony_ci#### 描述 162484543d1Sopenharmony_ci* 该接口支持在FFRT task 内部调用,也支持在FFRT task 外部调用 163484543d1Sopenharmony_ci 164484543d1Sopenharmony_ci* 该接口支持嵌套调用,即任务中可以继续提交子任务 165484543d1Sopenharmony_ci 166484543d1Sopenharmony_ci* 该接口在实现上使用多个重载版本以优化性能(基于移动语义,初始化列表等),用户只需按上述原型使用,编译时会自动选择最佳版本,支持的重载版本有: 167484543d1Sopenharmony_ci 168484543d1Sopenharmony_ci ```{.cpp} 169484543d1Sopenharmony_ci void submit(std::function<void()>&& func); 170484543d1Sopenharmony_ci void submit(std::function<void()>&& func, std::initializer_list<const void*> in_deps); 171484543d1Sopenharmony_ci void submit(std::function<void()>&& func, std::initializer_list<const void*> in_deps, std::initializer_list<const void*> out_deps); 172484543d1Sopenharmony_ci void submit(std::function<void()>&& func, std::initializer_list<const void*> in_deps, std::initializer_list<const void*> out_deps, const task_attr& attr); 173484543d1Sopenharmony_ci 174484543d1Sopenharmony_ci void submit(std::function<void()>&& func, const std::vector<const void*>& in_deps); 175484543d1Sopenharmony_ci void submit(std::function<void()>&& func, const std::vector<const void*>& in_deps, const std::vector<const void*>& out_deps); 176484543d1Sopenharmony_ci void submit(std::function<void()>&& func, const std::vector<const void*>& in_deps, const std::vector<const void*>& out_deps, const task_attr& attr); 177484543d1Sopenharmony_ci 178484543d1Sopenharmony_ci void submit(const std::function<void()>& func); 179484543d1Sopenharmony_ci void submit(const std::function<void()>& func, std::initializer_list<const void*> in_deps); 180484543d1Sopenharmony_ci void submit(const std::function<void()>& func, std::initializer_list<const void*> in_deps, std::initializer_list<const void*> out_deps); 181484543d1Sopenharmony_ci void submit(const std::function<void()>& func, std::initializer_list<const void*> in_deps, std::initializer_list<const void*> out_deps, const task_attr& attr); 182484543d1Sopenharmony_ci 183484543d1Sopenharmony_ci void submit(const std::function<void()>& func, const std::vector<const void*>& in_deps); 184484543d1Sopenharmony_ci void submit(const std::function<void()>& func, const std::vector<const void*>& in_deps, const std::vector<const void*>& out_deps); 185484543d1Sopenharmony_ci void submit(const std::function<void()>& func, const std::vector<const void*>& in_deps, const std::vector<const void*>& out_deps, const task_attr& attr); 186484543d1Sopenharmony_ci ``` 187484543d1Sopenharmony_ci 188484543d1Sopenharmony_ci 189484543d1Sopenharmony_ci#### 样例 190484543d1Sopenharmony_ci 191484543d1Sopenharmony_ci**submit and wait** 192484543d1Sopenharmony_ci 193484543d1Sopenharmony_ci```{.cpp} 194484543d1Sopenharmony_ci#include <iostream> 195484543d1Sopenharmony_ci#include "ffrt.h" 196484543d1Sopenharmony_ci 197484543d1Sopenharmony_ciint main(int narg, char** argv) 198484543d1Sopenharmony_ci{ 199484543d1Sopenharmony_ci int i = 0; 200484543d1Sopenharmony_ci for (i = 0; i < 3; i++) { 201484543d1Sopenharmony_ci ffrt::submit([i] { std::cout << "num: " << i << std::endl; }); 202484543d1Sopenharmony_ci } 203484543d1Sopenharmony_ci ffrt::wait(); 204484543d1Sopenharmony_ci return 0; 205484543d1Sopenharmony_ci} 206484543d1Sopenharmony_ci``` 207484543d1Sopenharmony_ci 208484543d1Sopenharmony_ci`解析`: 209484543d1Sopenharmony_ci 210484543d1Sopenharmony_ci1) 该示例中连续下发了3个Task,Task 使用C++ 11 Lambda 来描述(实际中Task 还可以使用函数指针,函数对象来描述),这些 Task 都会读取i,但是不会写任何变量; 211484543d1Sopenharmony_ci 212484543d1Sopenharmony_ci2) ffrt::submit 为异步下发,因此,Task2 并不会等到 Task1 执行完成之后再下发; 213484543d1Sopenharmony_ci 214484543d1Sopenharmony_ci3) ffrt::wait 用于实现待所有Task 都执行完成之后 main 函数再退出; 215484543d1Sopenharmony_ci 216484543d1Sopenharmony_ci4) 由于3个Task 在数据依赖关系上没有生产者-消费者或生产者-生产者依赖关系,因此3个 Task 是可以并行的,1种可能的输出是: 217484543d1Sopenharmony_ci 218484543d1Sopenharmony_ci```{.cpp} 219484543d1Sopenharmony_cinum: 0 220484543d1Sopenharmony_cinum: 2 221484543d1Sopenharmony_cinum: 1 222484543d1Sopenharmony_ci``` 223484543d1Sopenharmony_ci 224484543d1Sopenharmony_ci`注意`: 225484543d1Sopenharmony_ci 226484543d1Sopenharmony_ci如果将Lambda 表达式中的值捕获设置成引用捕获(即`[&i] { std::cout << "num: " << i << std::endl; }`),可能得到的输出为: 227484543d1Sopenharmony_ci 228484543d1Sopenharmony_ci```{.cpp} 229484543d1Sopenharmony_cinum: 2 230484543d1Sopenharmony_cinum: 2 231484543d1Sopenharmony_cinum: 2 232484543d1Sopenharmony_ci``` 233484543d1Sopenharmony_ci 234484543d1Sopenharmony_ci这是因为FFRT 是异步编程模型,在第一个task 真正开始执行的时候,i 的值可能已经被修改为1或者2 235484543d1Sopenharmony_ci 236484543d1Sopenharmony_ci 237484543d1Sopenharmony_ci 238484543d1Sopenharmony_ci**data verison** 239484543d1Sopenharmony_ci 240484543d1Sopenharmony_ci<img src="images/image-20220926150341102.png" style="zoom:60%" /> 241484543d1Sopenharmony_ci 242484543d1Sopenharmony_ci```{.cpp} 243484543d1Sopenharmony_ci#include <iostream> 244484543d1Sopenharmony_ci#include "ffrt.h" 245484543d1Sopenharmony_ci 246484543d1Sopenharmony_ciint main(int narg, char** argv) 247484543d1Sopenharmony_ci{ 248484543d1Sopenharmony_ci int x = 1; 249484543d1Sopenharmony_ci ffrt::submit([&] {x = 100; std::cout << "x:" << x << std::endl;}, {}, {&x}); 250484543d1Sopenharmony_ci ffrt::submit([&] {std::cout << "x:" << x << std::endl;}, {&x}, {}); 251484543d1Sopenharmony_ci ffrt::submit([&] {std::cout << "x:" << x << std::endl;}, {&x}, {}); 252484543d1Sopenharmony_ci ffrt::submit([&] {x++; std::cout << "x:" << x << std::endl;}, {}, {&x}); 253484543d1Sopenharmony_ci ffrt::submit([&] {x++; std::cout << "x:" << x << std::endl;}, {}, {&x}); 254484543d1Sopenharmony_ci 255484543d1Sopenharmony_ci ffrt::wait(); 256484543d1Sopenharmony_ci return 0; 257484543d1Sopenharmony_ci} 258484543d1Sopenharmony_ci``` 259484543d1Sopenharmony_ci 260484543d1Sopenharmony_ci `解析`: 261484543d1Sopenharmony_ci 262484543d1Sopenharmony_ci1) 按上一章节[Data-Driven 特性](#Data-Driven 特性)的描述,输出一定为: 263484543d1Sopenharmony_ci 264484543d1Sopenharmony_ci```{.cpp} 265484543d1Sopenharmony_cix:100 266484543d1Sopenharmony_cix:100 267484543d1Sopenharmony_cix:100 268484543d1Sopenharmony_cix:101 269484543d1Sopenharmony_cix:102 270484543d1Sopenharmony_ci``` 271484543d1Sopenharmony_ci 272484543d1Sopenharmony_ci**nested task** 273484543d1Sopenharmony_ci 274484543d1Sopenharmony_ci```{.cpp} 275484543d1Sopenharmony_ci#include <iostream> 276484543d1Sopenharmony_ci#include "ffrt.h" 277484543d1Sopenharmony_ci 278484543d1Sopenharmony_ciint main(int narg, char** argv) 279484543d1Sopenharmony_ci{ 280484543d1Sopenharmony_ci ffrt::submit([&] { 281484543d1Sopenharmony_ci std::cout << "task 1" << std::endl; 282484543d1Sopenharmony_ci ffrt::submit([&] {std::cout << "nested task 1.1" << std::endl;}, {}, {}); 283484543d1Sopenharmony_ci ffrt::submit([&] {std::cout << "nested task 1.2" << std::endl;}, {}, {}); 284484543d1Sopenharmony_ci ffrt::wait(); 285484543d1Sopenharmony_ci }, {}, {}); 286484543d1Sopenharmony_ci 287484543d1Sopenharmony_ci ffrt::submit([&] { 288484543d1Sopenharmony_ci std::cout << "task 2" << std::endl; 289484543d1Sopenharmony_ci ffrt::submit([&] {std::cout << "nested task 2.1" << std::endl;}, {}, {}); 290484543d1Sopenharmony_ci ffrt::submit([&] {std::cout << "nested task 2.2" << std::endl;}, {}, {}); 291484543d1Sopenharmony_ci ffrt::wait(); 292484543d1Sopenharmony_ci }, {}, {}); 293484543d1Sopenharmony_ci ffrt::wait(); 294484543d1Sopenharmony_ci return 0; 295484543d1Sopenharmony_ci} 296484543d1Sopenharmony_ci``` 297484543d1Sopenharmony_ci 298484543d1Sopenharmony_ci `解析`: 299484543d1Sopenharmony_ci 300484543d1Sopenharmony_ci1) FFRT允许在 Task 内部继续提交多个SubTask,这样 Task 之间可以建立起一颗调用树; 301484543d1Sopenharmony_ci 302484543d1Sopenharmony_ci2) Task1 和Task2 可以并行,Task 1.1/1.2/2.1/2.2 之间也可以并行,因此1种可行的输出为: 303484543d1Sopenharmony_ci 304484543d1Sopenharmony_ci``` 305484543d1Sopenharmony_citask 1 306484543d1Sopenharmony_cinested task 1.1 307484543d1Sopenharmony_citask 2 308484543d1Sopenharmony_cinested task 1.2 309484543d1Sopenharmony_cinested task 2.2 310484543d1Sopenharmony_cinested task 2.1 311484543d1Sopenharmony_ci``` 312484543d1Sopenharmony_ci 313484543d1Sopenharmony_ci### wait 314484543d1Sopenharmony_ci<hr/> 315484543d1Sopenharmony_ci* 同步等待,与[submit](#submit) 配合使用 316484543d1Sopenharmony_ci* 等待指定的数据被生产完成,或等待当前任务的所有子任务完成,在不满足条件之前,当前的执行上下文被suspend,在满足条件后恢复执行 317484543d1Sopenharmony_ci 318484543d1Sopenharmony_ci#### 声明 319484543d1Sopenharmony_ci 320484543d1Sopenharmony_ci```{.cpp} 321484543d1Sopenharmony_cinamespace ffrt { 322484543d1Sopenharmony_civoid wait(const std::vector<const void*>& deps); 323484543d1Sopenharmony_civoid wait(); 324484543d1Sopenharmony_ci} 325484543d1Sopenharmony_ci``` 326484543d1Sopenharmony_ci 327484543d1Sopenharmony_ci#### 参数 328484543d1Sopenharmony_ci 329484543d1Sopenharmony_ci`deps` 330484543d1Sopenharmony_ci 331484543d1Sopenharmony_ci* 需要等待被生产完成的数据的虚拟地址,这些地址可能作为某些任务在submit 时的out_deps 332484543d1Sopenharmony_ci 333484543d1Sopenharmony_ci#### 返回值 334484543d1Sopenharmony_ci 335484543d1Sopenharmony_ci* 不涉及 336484543d1Sopenharmony_ci 337484543d1Sopenharmony_ci#### 描述 338484543d1Sopenharmony_ci* wait(deps) 用于等待deps指代的数据被生产完成才能执行后面的代码 339484543d1Sopenharmony_ci* wait() 用于等待当前上下文提交的所有子任务(`注意:不包括孙子任务`)都完成才能执行后面的代码 340484543d1Sopenharmony_ci* 该接口支持在FFRT task 内部调用,也支持在FFRT task 外部调用 341484543d1Sopenharmony_ci* 在FFRT task 外部调用的wait 是OS 能够感知的等待,相对于FFRT task 内部调用的wait 是更加昂贵的,因此我们希望尽可能让更多的wait 发生在FFRT task 内部 ,而不是FFRT task 外部 342484543d1Sopenharmony_ci 343484543d1Sopenharmony_ci#### 样例 344484543d1Sopenharmony_ci 345484543d1Sopenharmony_ci**recursive fibonacci** 346484543d1Sopenharmony_ci 347484543d1Sopenharmony_ci串行版的fibonacci 可以实现为: 348484543d1Sopenharmony_ci 349484543d1Sopenharmony_ci```{.cpp} 350484543d1Sopenharmony_ci#include <iostream> 351484543d1Sopenharmony_ci 352484543d1Sopenharmony_civoid fib(int x, int& y) { 353484543d1Sopenharmony_ci if (x <= 1) { 354484543d1Sopenharmony_ci y = x; 355484543d1Sopenharmony_ci } else { 356484543d1Sopenharmony_ci int y1, y2; 357484543d1Sopenharmony_ci fib(x - 1, y1); 358484543d1Sopenharmony_ci fib(x - 2, y2); 359484543d1Sopenharmony_ci y = y1 + y2; 360484543d1Sopenharmony_ci } 361484543d1Sopenharmony_ci} 362484543d1Sopenharmony_ci 363484543d1Sopenharmony_ciint main(int narg, char** argv) 364484543d1Sopenharmony_ci{ 365484543d1Sopenharmony_ci int r; 366484543d1Sopenharmony_ci fib(10, r); 367484543d1Sopenharmony_ci std::cout << "fibonacci 10: " << r << std::endl; 368484543d1Sopenharmony_ci return 0; 369484543d1Sopenharmony_ci} 370484543d1Sopenharmony_ci``` 371484543d1Sopenharmony_ci 372484543d1Sopenharmony_ci若要使用 FFRT 实现并行(注,对于单纯的fibonacci,单个 Task 的计算量极小,不具有并行加速的意义,但这种调用pattern 对并行编程模型的灵活性考验是非常高的),其中1种可行的实现为: 373484543d1Sopenharmony_ci 374484543d1Sopenharmony_ci```{.cpp} 375484543d1Sopenharmony_ci#include <iostream> 376484543d1Sopenharmony_ci 377484543d1Sopenharmony_ci#include "ffrt.h" 378484543d1Sopenharmony_ci 379484543d1Sopenharmony_civoid fib_ffrt(int x, int& y) 380484543d1Sopenharmony_ci{ 381484543d1Sopenharmony_ci if (x <= 1) { 382484543d1Sopenharmony_ci y = x; 383484543d1Sopenharmony_ci } else { 384484543d1Sopenharmony_ci int y1, y2; 385484543d1Sopenharmony_ci ffrt::submit([&] {fib_ffrt(x - 1, y1);}, {&x}, {&y1} ); 386484543d1Sopenharmony_ci ffrt::submit([&] {fib_ffrt(x - 2, y2);}, {&x}, {&y2} ); 387484543d1Sopenharmony_ci ffrt::wait({&y1, &y2}); 388484543d1Sopenharmony_ci y = y1 + y2; 389484543d1Sopenharmony_ci } 390484543d1Sopenharmony_ci} 391484543d1Sopenharmony_ci 392484543d1Sopenharmony_ciint main(int narg, char** argv) 393484543d1Sopenharmony_ci{ 394484543d1Sopenharmony_ci int r; 395484543d1Sopenharmony_ci ffrt::submit([&] { fib_ffrt(10, r); }, {}, {&r}); 396484543d1Sopenharmony_ci ffrt::wait({&r}); 397484543d1Sopenharmony_ci std::cout << "fibonacci 10: " << r << std::endl; 398484543d1Sopenharmony_ci return 0; 399484543d1Sopenharmony_ci} 400484543d1Sopenharmony_ci``` 401484543d1Sopenharmony_ci 402484543d1Sopenharmony_ci`解析`: 403484543d1Sopenharmony_ci 404484543d1Sopenharmony_ci1) 将fibonacci (x-1)和fibonacci (x-2) 作为2个Task 提交给FFRT,在两个Task 完成之后将结果累加; 405484543d1Sopenharmony_ci 406484543d1Sopenharmony_ci2) 虽然单个Task 只能拆分成2个SubTask 但是子Task 可以继续拆分,因此,整个计算图的并行度是非常高的,Task 之间在FFRT 内部形成了一颗调用树; 407484543d1Sopenharmony_ci 408484543d1Sopenharmony_ci<img src="images/image-20220926152331554.png" style="zoom:100%" /> 409484543d1Sopenharmony_ci 410484543d1Sopenharmony_ci 411484543d1Sopenharmony_ci### task_attr 412484543d1Sopenharmony_ci<hr/> 413484543d1Sopenharmony_ci* 定义task 的属性的辅助类,与[submit](#submit) 配合使用 414484543d1Sopenharmony_ci 415484543d1Sopenharmony_ci#### 声明 416484543d1Sopenharmony_ci 417484543d1Sopenharmony_ci```{.cpp} 418484543d1Sopenharmony_cinamespace ffrt { 419484543d1Sopenharmony_cienum qos { 420484543d1Sopenharmony_ci qos_inherit = -1, 421484543d1Sopenharmony_ci qos_background, 422484543d1Sopenharmony_ci qos_utility, 423484543d1Sopenharmony_ci qos_default, 424484543d1Sopenharmony_ci qos_user_initiated, 425484543d1Sopenharmony_ci}; 426484543d1Sopenharmony_ci 427484543d1Sopenharmony_ciclass task_attr { 428484543d1Sopenharmony_cipublic: 429484543d1Sopenharmony_ci task_attr& qos(enum qos qos); // set qos 430484543d1Sopenharmony_ci enum qos qos() const; // get qos 431484543d1Sopenharmony_ci task_attr& name(const char* name); // set name 432484543d1Sopenharmony_ci const char* name() const; // get name 433484543d1Sopenharmony_ci}; 434484543d1Sopenharmony_ci} 435484543d1Sopenharmony_ci``` 436484543d1Sopenharmony_ci 437484543d1Sopenharmony_ci#### 参数 438484543d1Sopenharmony_ci 439484543d1Sopenharmony_ci`qos` 440484543d1Sopenharmony_ci 441484543d1Sopenharmony_ci* qos 设定的枚举类型 442484543d1Sopenharmony_ci* inherent 是一个qos 设定策略,代表即将submit 的task 的qos 继承当前task 的qos 443484543d1Sopenharmony_ci 444484543d1Sopenharmony_ci#### 返回值 445484543d1Sopenharmony_ci 446484543d1Sopenharmony_ci* 不涉及 447484543d1Sopenharmony_ci 448484543d1Sopenharmony_ci#### 描述 449484543d1Sopenharmony_ci* 约定 450484543d1Sopenharmony_ci * 在submit 时,如果不通过task_attr 设定qos,那么默认该提交的task的qos 为`qos_default` 451484543d1Sopenharmony_ci * 在submit 时,如果通过task_attr 设定qos 为`qos_inherent`,表示将该提交的task 的qos 与当前task 的qos 相同,在FFRT task 外部提交的属性为`qos_inherent` 的task,其qos 为`qos_default` 452484543d1Sopenharmony_ci * 其他情况下,该提交的task 的qos 被设定为指定的值 453484543d1Sopenharmony_ci* qos 级别从上到下依次递增,qos_user_interactive拥有最高优先级 454484543d1Sopenharmony_ci 455484543d1Sopenharmony_ci#### 样例 456484543d1Sopenharmony_ci 457484543d1Sopenharmony_ci```{.cpp} 458484543d1Sopenharmony_ci#include <iostream> 459484543d1Sopenharmony_ci#include "ffrt.h" 460484543d1Sopenharmony_ci 461484543d1Sopenharmony_ciint main(int narg, char** argv) 462484543d1Sopenharmony_ci{ 463484543d1Sopenharmony_ci ffrt::submit([] { std::cout << "hello ffrt" << std::endl; }, {}, {}, 464484543d1Sopenharmony_ci ffrt::task_attr().qos(ffrt::qos_background)); 465484543d1Sopenharmony_ci ffrt::wait(); 466484543d1Sopenharmony_ci return 0; 467484543d1Sopenharmony_ci} 468484543d1Sopenharmony_ci``` 469484543d1Sopenharmony_ci 470484543d1Sopenharmony_ci* 提交一个qos 级别为background 的任务 471484543d1Sopenharmony_ci 472484543d1Sopenharmony_ci 473484543d1Sopenharmony_ci 474484543d1Sopenharmony_ci### submit_h 475484543d1Sopenharmony_ci 476484543d1Sopenharmony_ci<hr/> 477484543d1Sopenharmony_ci 478484543d1Sopenharmony_ci* 向调度器提交一个task,与[submit](#submit) 的差别在于返回task 的句柄,该句柄可以用于建立task 之间的依赖,或用于在wait 语句中实现同步 479484543d1Sopenharmony_ci 480484543d1Sopenharmony_ci#### 声明 481484543d1Sopenharmony_ci 482484543d1Sopenharmony_ci```{.cpp} 483484543d1Sopenharmony_cinamespace ffrt { 484484543d1Sopenharmony_ciclass task_handle { 485484543d1Sopenharmony_cipublic: 486484543d1Sopenharmony_ci task_handle(); 487484543d1Sopenharmony_ci task_handle(ffrt_task_handle_t p); 488484543d1Sopenharmony_ci 489484543d1Sopenharmony_ci task_handle(task_handle const&) = delete; 490484543d1Sopenharmony_ci void operator=(task_handle const&) = delete; 491484543d1Sopenharmony_ci 492484543d1Sopenharmony_ci task_handle(task_handle&& h); 493484543d1Sopenharmony_ci task_handle& operator=(task_handle&& h); 494484543d1Sopenharmony_ci 495484543d1Sopenharmony_ci operator void* () const; 496484543d1Sopenharmony_ci}; 497484543d1Sopenharmony_ci 498484543d1Sopenharmony_citask_handle submit_h(std::function<void()>&& func, const std::vector<const void*>& in_deps = {}, const std::vector<const void*>& out_deps = {}, const task_attr& attr = {}); 499484543d1Sopenharmony_citask_handle submit_h(const std::function<void()>& func, const std::vector<const void*>& in_deps = {}, const std::vector<const void*>& out_deps = {}, const task_attr& attr = {}); 500484543d1Sopenharmony_ci} 501484543d1Sopenharmony_ci``` 502484543d1Sopenharmony_ci 503484543d1Sopenharmony_ci#### 参数 504484543d1Sopenharmony_ci 505484543d1Sopenharmony_ci`func` 506484543d1Sopenharmony_ci 507484543d1Sopenharmony_ci* 同submit,详见[submit](#submit) 定义 508484543d1Sopenharmony_ci 509484543d1Sopenharmony_ci`in_deps` 510484543d1Sopenharmony_ci 511484543d1Sopenharmony_ci* 同submit,详见[submit](#submit) 定义 512484543d1Sopenharmony_ci 513484543d1Sopenharmony_ci`out_deps` 514484543d1Sopenharmony_ci 515484543d1Sopenharmony_ci* 同submit,详见[submit](#submit) 定义 516484543d1Sopenharmony_ci 517484543d1Sopenharmony_ci`attr` 518484543d1Sopenharmony_ci 519484543d1Sopenharmony_ci* 同submit,详见[submit](#submit) 定义 520484543d1Sopenharmony_ci 521484543d1Sopenharmony_ci#### 返回值 522484543d1Sopenharmony_ci 523484543d1Sopenharmony_ci* task 的句柄,该句柄可以用于建立task 之间的依赖,或用于在wait 语句中实现同步 524484543d1Sopenharmony_ci 525484543d1Sopenharmony_ci#### 描述 526484543d1Sopenharmony_ci 527484543d1Sopenharmony_ci* 该接口与submit 使用基本相同,从性能的角度,在不需要返回task handle 的场景,可以调用submit 接口相对于submit_h 有更好的性能 528484543d1Sopenharmony_ci* task_handle 可以和其他的数据depends 同时作为某个task 的in_deps,表示该task 的执行依赖task_handle 对应的task 执行完成 529484543d1Sopenharmony_ci* task_handle 可以和其他的数据depends 同时作为wait 的deps,表示当前任务将被suspend,直到task_handle 对应的task 执行完成后将被恢复 530484543d1Sopenharmony_ci* task_handle 不建议作为某个task 的out_deps,其行为是未定义的 531484543d1Sopenharmony_ci 532484543d1Sopenharmony_ci 533484543d1Sopenharmony_ci#### 样例 534484543d1Sopenharmony_ci 535484543d1Sopenharmony_ci```{.cpp} 536484543d1Sopenharmony_ci#include <iostream> 537484543d1Sopenharmony_ci#include "ffrt.h" 538484543d1Sopenharmony_ci 539484543d1Sopenharmony_ciint main(int narg, char** argv) 540484543d1Sopenharmony_ci{ 541484543d1Sopenharmony_ci // handle work with submit 542484543d1Sopenharmony_ci ffrt::task_handle h = ffrt::submit_h([] { std::cout << "hello "; }); // not need some data in this task 543484543d1Sopenharmony_ci int x = 1; 544484543d1Sopenharmony_ci ffrt::submit([&] { x++; }, {}, {&x}); 545484543d1Sopenharmony_ci ffrt::submit([&] { std::cout << "world, x = " << x << std::endl; }, {&x, h}); // this task depend x and h 546484543d1Sopenharmony_ci 547484543d1Sopenharmony_ci // handle work with wait 548484543d1Sopenharmony_ci ffrt::task_handle h2 = ffrt::submit_h([&] { std::cout << "handle wait" << std::endl; x++; }); 549484543d1Sopenharmony_ci ffrt::wait({h2}); 550484543d1Sopenharmony_ci std::cout << "x = " << x << std::endl; 551484543d1Sopenharmony_ci ffrt::wait(); 552484543d1Sopenharmony_ci return 0; 553484543d1Sopenharmony_ci} 554484543d1Sopenharmony_ci``` 555484543d1Sopenharmony_ci 556484543d1Sopenharmony_ci* 预期的输出为 557484543d1Sopenharmony_ci 558484543d1Sopenharmony_ci``` 559484543d1Sopenharmony_cihello world, x = 2 560484543d1Sopenharmony_cihandle wait 561484543d1Sopenharmony_cix = 3 562484543d1Sopenharmony_ci``` 563484543d1Sopenharmony_ci 564484543d1Sopenharmony_ci### get_id 565484543d1Sopenharmony_ci 566484543d1Sopenharmony_ci<hr/> 567484543d1Sopenharmony_ci 568484543d1Sopenharmony_ci* 返回当前task的id标识,更多使用用于维测(原因是task name可能重名) 569484543d1Sopenharmony_ci 570484543d1Sopenharmony_ci#### 声明 571484543d1Sopenharmony_ci 572484543d1Sopenharmony_ci```{.cpp} 573484543d1Sopenharmony_cinamespace ffrt { 574484543d1Sopenharmony_cinamespace this_task { 575484543d1Sopenharmony_ciuint64_t get_id(); 576484543d1Sopenharmony_ci} 577484543d1Sopenharmony_ci} 578484543d1Sopenharmony_ci``` 579484543d1Sopenharmony_ci 580484543d1Sopenharmony_ci#### 参数 581484543d1Sopenharmony_ci 582484543d1Sopenharmony_ci* 不涉及 583484543d1Sopenharmony_ci 584484543d1Sopenharmony_ci#### 返回值 585484543d1Sopenharmony_ci 586484543d1Sopenharmony_ci* 当前task的id 587484543d1Sopenharmony_ci 588484543d1Sopenharmony_ci#### 描述 589484543d1Sopenharmony_ci 590484543d1Sopenharmony_ci* 该接口在task内部调用将返回当前task的id标识,在task外部调用将返回0 591484543d1Sopenharmony_ci* 可以基于该接口在task外部调用返回0的特性来区分函数是运行在FFRT 工作线程上还是非FFRT工作线程上 592484543d1Sopenharmony_ci* task id为从1开始编码,每提交一个task便增加1,被设计成64bit,即便是每秒百万次提交,也需要292471.2年才会发生翻转 593484543d1Sopenharmony_ci 594484543d1Sopenharmony_ci#### 样例 595484543d1Sopenharmony_ci 596484543d1Sopenharmony_ci```{.cpp} 597484543d1Sopenharmony_ci#include <iostream> 598484543d1Sopenharmony_ci#include "ffrt.h" 599484543d1Sopenharmony_ci 600484543d1Sopenharmony_ciint main(int narg, char** argv) 601484543d1Sopenharmony_ci{ 602484543d1Sopenharmony_ci ffrt::submit([] { std::cout << "task id: " << ffrt::this_task::get_id() << std::endl; }); 603484543d1Sopenharmony_ci ffrt::submit([] { std::cout <<"task id: " << ffrt::this_task::get_id() << std::endl; }); 604484543d1Sopenharmony_ci ffrt::wait(); 605484543d1Sopenharmony_ci std::cout << "task id: " << ffrt::this_task::get_id() << std::endl; 606484543d1Sopenharmony_ci return 0; 607484543d1Sopenharmony_ci} 608484543d1Sopenharmony_ci``` 609484543d1Sopenharmony_ci 610484543d1Sopenharmony_ci* 可能的输出为: 611484543d1Sopenharmony_ci 612484543d1Sopenharmony_ci``` 613484543d1Sopenharmony_citask id: 1 614484543d1Sopenharmony_citask id: 2 615484543d1Sopenharmony_citask id: 0 616484543d1Sopenharmony_ci``` 617484543d1Sopenharmony_ci 618484543d1Sopenharmony_ci### update_qos 619484543d1Sopenharmony_ci 620484543d1Sopenharmony_ci<hr/> 621484543d1Sopenharmony_ci 622484543d1Sopenharmony_ci* 更新当前正在执行的task的优先级 623484543d1Sopenharmony_ci 624484543d1Sopenharmony_ci#### 声明 625484543d1Sopenharmony_ci 626484543d1Sopenharmony_ci```{.cpp} 627484543d1Sopenharmony_cinamespace ffrt { 628484543d1Sopenharmony_cinamespace this_task { 629484543d1Sopenharmony_ciint update_qos(enum qos qos); 630484543d1Sopenharmony_ci} 631484543d1Sopenharmony_ci} 632484543d1Sopenharmony_ci``` 633484543d1Sopenharmony_ci 634484543d1Sopenharmony_ci#### 参数 635484543d1Sopenharmony_ci 636484543d1Sopenharmony_ci`qos` 637484543d1Sopenharmony_ci* 新的qos等级 638484543d1Sopenharmony_ci 639484543d1Sopenharmony_ci#### 返回值 640484543d1Sopenharmony_ci 641484543d1Sopenharmony_ci* 0表示成功,非0表示失败 642484543d1Sopenharmony_ci 643484543d1Sopenharmony_ci#### 描述 644484543d1Sopenharmony_ci 645484543d1Sopenharmony_ci* 该接口对当前task的qos调整会立即生效 646484543d1Sopenharmony_ci* 如果新设定的qos与当前的qos不一致,则会block当前task的执行,再按照新的qos恢复执行 647484543d1Sopenharmony_ci* 如果新设定的qos与当前的qos一致,则接口会立即返回,不做任何处理 648484543d1Sopenharmony_ci* **如果在非task内部调用该接口,则返回非0值,用户可以选择忽略或其他处理** 649484543d1Sopenharmony_ci 650484543d1Sopenharmony_ci#### 样例 651484543d1Sopenharmony_ci 652484543d1Sopenharmony_ci```{.cpp} 653484543d1Sopenharmony_ci#include <iostream> 654484543d1Sopenharmony_ci#include <thread> 655484543d1Sopenharmony_ci#include "ffrt.h" 656484543d1Sopenharmony_ci 657484543d1Sopenharmony_ciint main(int narg, char** argv) 658484543d1Sopenharmony_ci{ 659484543d1Sopenharmony_ci ffrt::submit([] { 660484543d1Sopenharmony_ci std::cout << "thread id: " << std::this_thread::get_id() << std::endl; 661484543d1Sopenharmony_ci std::cout << "return " << ffrt::this_task::update_qos(ffrt::qos_user_initiated) << std::endl; 662484543d1Sopenharmony_ci std::cout << "thread id: " << std::this_thread::get_id() << std::endl; 663484543d1Sopenharmony_ci }); 664484543d1Sopenharmony_ci ffrt::wait(); 665484543d1Sopenharmony_ci std::cout << "return " << ffrt::this_task::update_qos(ffrt::qos_user_initiated) << std::endl; 666484543d1Sopenharmony_ci return 0; 667484543d1Sopenharmony_ci} 668484543d1Sopenharmony_ci``` 669484543d1Sopenharmony_ci 670484543d1Sopenharmony_ci* 可能的输出为: 671484543d1Sopenharmony_ci 672484543d1Sopenharmony_ci``` 673484543d1Sopenharmony_cithread id: 1024 674484543d1Sopenharmony_cireturn 0 675484543d1Sopenharmony_cithread id: 2222 676484543d1Sopenharmony_cireturn 1 677484543d1Sopenharmony_ci``` 678484543d1Sopenharmony_ci 679484543d1Sopenharmony_ci 680484543d1Sopenharmony_ci 681484543d1Sopenharmony_ci## 串行队列 682484543d1Sopenharmony_ci<hr /> 683484543d1Sopenharmony_ci 684484543d1Sopenharmony_ci串行队列基于FFRT协程调度模型,实现了消息队列功能。串行任务执行在FFRT worker上,用户无需维护一个专用的线程,拥有更轻量级的调度开销。 685484543d1Sopenharmony_ci 686484543d1Sopenharmony_ci支持以下基本功能: 687484543d1Sopenharmony_ci 688484543d1Sopenharmony_ci* 支持创建队列,创建队列时可指定队列名称和优先级,每个队列在功能上相当于一个单独的线程,队列中的任务相对于用户线程异步执行。 689484543d1Sopenharmony_ci 690484543d1Sopenharmony_ci* 支持延时任务,向队列提交任务时支持设置 delay 属性,单位为微秒 us,提交给队列的延时任务,在提交时刻+delay时间后才会被调度执行。 691484543d1Sopenharmony_ci 692484543d1Sopenharmony_ci* 支持串行调度,同一个队列中的多个任务按照 uptime (提交时刻+delay时间)升序排列、串行执行,队列中一个任务完成后下一个任务才会开始。 693484543d1Sopenharmony_ci 694484543d1Sopenharmony_ci* 支持取消任务,支持根据任务句柄取消单个未执行的任务,如果这个任务已出队(开始执行或已执行完),取消接口返回异常值。 695484543d1Sopenharmony_ci 696484543d1Sopenharmony_ci* 支持同步等待,支持根据任务句柄等待指定任务完成,该任务完成,也代表同一队列中uptime在此任务之前的所有任务都已完成。 697484543d1Sopenharmony_ci 698484543d1Sopenharmony_ci### queue 699484543d1Sopenharmony_ci<hr/> 700484543d1Sopenharmony_ci 701484543d1Sopenharmony_ci#### 描述 702484543d1Sopenharmony_ciFFRT串行队列 C++ API,提供提交任务、取消任务、等待任务执行完成等功能 703484543d1Sopenharmony_ci 704484543d1Sopenharmony_ci#### 声明 705484543d1Sopenharmony_ci 706484543d1Sopenharmony_ci```{.cpp} 707484543d1Sopenharmony_cinamespace ffrt { 708484543d1Sopenharmony_ciclass queue { 709484543d1Sopenharmony_cipublic: 710484543d1Sopenharmony_ci queue(queue const&) = delete; 711484543d1Sopenharmony_ci void operator=(queue const&) = delete; 712484543d1Sopenharmony_ci 713484543d1Sopenharmony_ci void submit(const std::function<void()>& func); 714484543d1Sopenharmony_ci void submit(const std::function<void()>& func, const task_attr& attr); 715484543d1Sopenharmony_ci void submit(std::function<void()>&& func); 716484543d1Sopenharmony_ci void submit(std::function<void()>&& func, const task_attr& attr); 717484543d1Sopenharmony_ci 718484543d1Sopenharmony_ci task_handle submit_h(const std::function<void()>& func); 719484543d1Sopenharmony_ci task_handle submit_h(const std::function<void()>& func, const task_attr& attr); 720484543d1Sopenharmony_ci task_handle submit_h(std::function<void()>&& func); 721484543d1Sopenharmony_ci task_handle submit_h(std::function<void()>&& func, const task_attr& attr); 722484543d1Sopenharmony_ci 723484543d1Sopenharmony_ci int cancel(const task_handle& handle); 724484543d1Sopenharmony_ci 725484543d1Sopenharmony_ci void wait(const task_handle& handle); 726484543d1Sopenharmony_ci}; 727484543d1Sopenharmony_ci} 728484543d1Sopenharmony_ci``` 729484543d1Sopenharmony_ci 730484543d1Sopenharmony_ci#### 方法 731484543d1Sopenharmony_ci 732484543d1Sopenharmony_ci##### submit 733484543d1Sopenharmony_ci 734484543d1Sopenharmony_ci```{.cpp} 735484543d1Sopenharmony_cinamespace ffrt { 736484543d1Sopenharmony_civoid queue::submit(const std::function<void()>& func); 737484543d1Sopenharmony_civoid queue::submit(const std::function<void()>& func, const task_attr& attr); 738484543d1Sopenharmony_civoid queue::submit(std::function<void()>&& func); 739484543d1Sopenharmony_civoid queue::submit(std::function<void()>&& func, const task_attr& attr); 740484543d1Sopenharmony_ci} 741484543d1Sopenharmony_ci``` 742484543d1Sopenharmony_ci 743484543d1Sopenharmony_ci* 描述:提交一个任务到队列中调度执行 744484543d1Sopenharmony_ci 745484543d1Sopenharmony_ci* 参数: 746484543d1Sopenharmony_ci 747484543d1Sopenharmony_ci `func`:可被std::function接收的一切CPU可执行体,可以为C++定义的Lambda函数闭包,函数指针,甚至是函数对象 748484543d1Sopenharmony_ci 749484543d1Sopenharmony_ci `attr`:该参数是可选的,用于描述task的属性,如qos、delay、timeout等,详见[task_attr](#task_attr)章节 750484543d1Sopenharmony_ci 751484543d1Sopenharmony_ci* 返回值:不涉及 752484543d1Sopenharmony_ci 753484543d1Sopenharmony_ci##### submit_h 754484543d1Sopenharmony_ci 755484543d1Sopenharmony_ci```{.cpp} 756484543d1Sopenharmony_cinamespace ffrt { 757484543d1Sopenharmony_citask_handle queue::submit_h(const std::function<void()>& func); 758484543d1Sopenharmony_citask_handle queue::submit_h(const std::function<void()>& func, const task_attr& attr); 759484543d1Sopenharmony_citask_handle queue::submit_h(std::function<void()>&& func); 760484543d1Sopenharmony_citask_handle queue::submit_h(std::function<void()>&& func, const task_attr& attr); 761484543d1Sopenharmony_ci} 762484543d1Sopenharmony_ci``` 763484543d1Sopenharmony_ci 764484543d1Sopenharmony_ci* 描述:提交一个任务到队列中调度执行,并返回一个句柄 765484543d1Sopenharmony_ci 766484543d1Sopenharmony_ci* 参数: 767484543d1Sopenharmony_ci 768484543d1Sopenharmony_ci `func`:可被std::function接收的一切CPU可执行体,可以为C++定义的Lambda函数闭包,函数指针,甚至是函数对象 769484543d1Sopenharmony_ci 770484543d1Sopenharmony_ci `attr`:该参数时可选的,用于描述task的属性,如qos、delay、timeout等,详见[task_attr](#task_attr)章节 771484543d1Sopenharmony_ci 772484543d1Sopenharmony_ci* 返回值: 773484543d1Sopenharmony_ci 774484543d1Sopenharmony_ci `task_handle`:task的句柄,该句柄可以用于建立task之间的依赖 775484543d1Sopenharmony_ci 776484543d1Sopenharmony_ci##### cancel 777484543d1Sopenharmony_ci 778484543d1Sopenharmony_ci```{.cpp} 779484543d1Sopenharmony_cinamespace ffrt { 780484543d1Sopenharmony_ciint queue::cancel(const task_handle& handle); 781484543d1Sopenharmony_ci} 782484543d1Sopenharmony_ci``` 783484543d1Sopenharmony_ci 784484543d1Sopenharmony_ci* 描述:根据句柄取消对应的任务 785484543d1Sopenharmony_ci 786484543d1Sopenharmony_ci* 参数: 787484543d1Sopenharmony_ci 788484543d1Sopenharmony_ci `handle`:任务的句柄 789484543d1Sopenharmony_ci 790484543d1Sopenharmony_ci* 返回值: 791484543d1Sopenharmony_ci 792484543d1Sopenharmony_ci 若成功返回0,否则返回其他非0值 793484543d1Sopenharmony_ci 794484543d1Sopenharmony_ci##### wait 795484543d1Sopenharmony_ci 796484543d1Sopenharmony_ci```{.cpp} 797484543d1Sopenharmony_cinamespace ffrt { 798484543d1Sopenharmony_civoid queue::wait(const task_handle& handle); 799484543d1Sopenharmony_ci} 800484543d1Sopenharmony_ci``` 801484543d1Sopenharmony_ci 802484543d1Sopenharmony_ci* 描述:等待句柄对应的任务执行完成 803484543d1Sopenharmony_ci 804484543d1Sopenharmony_ci* 参数: 805484543d1Sopenharmony_ci 806484543d1Sopenharmony_ci `handle`:任务的句柄 807484543d1Sopenharmony_ci 808484543d1Sopenharmony_ci* 返回值:不涉及 809484543d1Sopenharmony_ci 810484543d1Sopenharmony_ci 811484543d1Sopenharmony_ci#### 样例 812484543d1Sopenharmony_ci 813484543d1Sopenharmony_ci```{.cpp} 814484543d1Sopenharmony_ci#include "ffrt.h" 815484543d1Sopenharmony_ci 816484543d1Sopenharmony_ciint main(int narg, char** argv) 817484543d1Sopenharmony_ci{ 818484543d1Sopenharmony_ci // 创建队列,可设置队列优先级,默认为default等级 819484543d1Sopenharmony_ci ffrt::queue q("test_queue", ffrt::queue_attr().qos(ffrt::qos_utility)); 820484543d1Sopenharmony_ci 821484543d1Sopenharmony_ci int x = 0; 822484543d1Sopenharmony_ci // 提交串行任务 823484543d1Sopenharmony_ci q.submit([&x] { x += 10; }); 824484543d1Sopenharmony_ci 825484543d1Sopenharmony_ci // 提交串行任务,并返回任务句柄 826484543d1Sopenharmony_ci ffrt::task_handle t1 = q.submit_h([&x] { x += 10; }); 827484543d1Sopenharmony_ci 828484543d1Sopenharmony_ci // 提交串行任务,设置延时时间1000us,并返回任务句柄 829484543d1Sopenharmony_ci ffrt::task_handle t2 = q.submit_h([&x] { x += 10; }, ffrt::task_attr().delay(1000)); 830484543d1Sopenharmony_ci 831484543d1Sopenharmony_ci // 等待指定任务执行完成 832484543d1Sopenharmony_ci q.wait(t1); 833484543d1Sopenharmony_ci 834484543d1Sopenharmony_ci // 取消句柄为t2的任务 835484543d1Sopenharmony_ci q.cancel(t2); 836484543d1Sopenharmony_ci} 837484543d1Sopenharmony_ci``` 838484543d1Sopenharmony_ci 839484543d1Sopenharmony_ci#### 使用约束 840484543d1Sopenharmony_ci 841484543d1Sopenharmony_ci* 队列销毁时,会等待正在执行的任务执行完成,队列中还没有开始执行的任务会被取消。 842484543d1Sopenharmony_ci 843484543d1Sopenharmony_ci* 任务粒度,串行队列支持任务执行超时检测(默认阈值30s,进程可配),因此队列中的单个任务不应该常驻(如循环任务),超过30s会向DFX上报超时。 844484543d1Sopenharmony_ci 845484543d1Sopenharmony_ci* 同步原语,任务中如果使用了 std::mutex/std::shared_mutex/std::condition_variable等std同步原语,会影响协程效率,需修改ffrt同步原语。 846484543d1Sopenharmony_ci 847484543d1Sopenharmony_ci 当前FFRT仅支持ffrt::mutex / ffrt::shared_mutex / ffrt::recursive_mutex / ffrt::condition_variable,用法和std相同,在ffrt的任务中使用未支持同步原语可能导致未定义的行为。 848484543d1Sopenharmony_ci 849484543d1Sopenharmony_ci* 生命周期,进程结束前需要释放FFRT资源。 850484543d1Sopenharmony_ci 851484543d1Sopenharmony_ci 例如SA业务,会在全局变量中管理串行队列。由于进程会先卸载libffrt.so再释放全局变量,如果进程结束时,SA未显示释放持有的串行队列,队列将随全局变量析构,析构时会访问已释放的ffrt资源,导致Fuzz用例出现use-after-free问题。 852484543d1Sopenharmony_ci 853484543d1Sopenharmony_ci* 不允许在串行任务中调用ffrt::submit和ffrt::wait,其行为是未定义的 854484543d1Sopenharmony_ci 855484543d1Sopenharmony_ci* 不允许使用ffrt::wait等待一个串行任务 856484543d1Sopenharmony_ci 857484543d1Sopenharmony_ci### queue_attr 858484543d1Sopenharmony_ci<hr/> 859484543d1Sopenharmony_ci 860484543d1Sopenharmony_ci#### 描述 861484543d1Sopenharmony_ciFFRT串行队列 C++ API,提供设置与获取串行队列优先级、设置与获取串行队列任务执行超时时间、设置与获取串行队列超时回调函数等功能 862484543d1Sopenharmony_ci 863484543d1Sopenharmony_ci#### 声明 864484543d1Sopenharmony_ci 865484543d1Sopenharmony_ci```{.cpp} 866484543d1Sopenharmony_cinamespace ffrt { 867484543d1Sopenharmony_ciclass queue_attr { 868484543d1Sopenharmony_cipublic: 869484543d1Sopenharmony_ci queue_attr(const queue_attr&) = delete; 870484543d1Sopenharmony_ci queue_attr& operator=(const queue_attr&) = delete; 871484543d1Sopenharmony_ci 872484543d1Sopenharmony_ci queue_attr& qos(qos qos_); 873484543d1Sopenharmony_ci uint64_t timeout() const; 874484543d1Sopenharmony_ci 875484543d1Sopenharmony_ci queue_attr& callback(const std::function<void()>& func); 876484543d1Sopenharmony_ci ffrt_function_header_t* callback() const; 877484543d1Sopenharmony_ci}; 878484543d1Sopenharmony_ci} 879484543d1Sopenharmony_ci``` 880484543d1Sopenharmony_ci 881484543d1Sopenharmony_ci#### 方法 882484543d1Sopenharmony_ci 883484543d1Sopenharmony_ci##### set qos 884484543d1Sopenharmony_ci 885484543d1Sopenharmony_ci```{.cpp} 886484543d1Sopenharmony_cinamespace ffrt { 887484543d1Sopenharmony_ciqueue_attr& queue_attr::qos(qos qos_); 888484543d1Sopenharmony_ci} 889484543d1Sopenharmony_ci``` 890484543d1Sopenharmony_ci 891484543d1Sopenharmony_ci* 描述:设置队列属性的qos成员 892484543d1Sopenharmony_ci 893484543d1Sopenharmony_ci* 参数: 894484543d1Sopenharmony_ci 895484543d1Sopenharmony_ci `qos_`:串行队列的优先级 896484543d1Sopenharmony_ci 897484543d1Sopenharmony_ci* 返回值: 898484543d1Sopenharmony_ci 899484543d1Sopenharmony_ci `queue_attr`:串行队列的属性 900484543d1Sopenharmony_ci 901484543d1Sopenharmony_ci##### get qos 902484543d1Sopenharmony_ci 903484543d1Sopenharmony_ci```{.cpp} 904484543d1Sopenharmony_cinamespace ffrt { 905484543d1Sopenharmony_ciint queue_attr::qos() const; 906484543d1Sopenharmony_ci} 907484543d1Sopenharmony_ci``` 908484543d1Sopenharmony_ci 909484543d1Sopenharmony_ci* 描述:获取队列的优先级 910484543d1Sopenharmony_ci 911484543d1Sopenharmony_ci* 参数:不涉及 912484543d1Sopenharmony_ci 913484543d1Sopenharmony_ci* 返回值: 914484543d1Sopenharmony_ci 915484543d1Sopenharmony_ci `qos`:串行队列的优先级 916484543d1Sopenharmony_ci 917484543d1Sopenharmony_ci##### set timeout 918484543d1Sopenharmony_ci 919484543d1Sopenharmony_ci```{.cpp} 920484543d1Sopenharmony_cinamespace ffrt { 921484543d1Sopenharmony_ciqueue_attr& queue_attr::timeout(uint64_t timeout_us); 922484543d1Sopenharmony_ci} 923484543d1Sopenharmony_ci``` 924484543d1Sopenharmony_ci 925484543d1Sopenharmony_ci* 描述:设置串行队列任务执行超时时间 926484543d1Sopenharmony_ci 927484543d1Sopenharmony_ci* 参数: 928484543d1Sopenharmony_ci 929484543d1Sopenharmony_ci `timeout_us`:串行队列任务执行超时时间,单位为us 930484543d1Sopenharmony_ci 931484543d1Sopenharmony_ci* 返回值: 932484543d1Sopenharmony_ci 933484543d1Sopenharmony_ci `queue_attr`:串行队列的属性 934484543d1Sopenharmony_ci 935484543d1Sopenharmony_ci##### get timeout 936484543d1Sopenharmony_ci 937484543d1Sopenharmony_ci```{.cpp} 938484543d1Sopenharmony_cinamespace ffrt { 939484543d1Sopenharmony_ciuint64_t queue_attr::timeout() const; 940484543d1Sopenharmony_ci} 941484543d1Sopenharmony_ci``` 942484543d1Sopenharmony_ci 943484543d1Sopenharmony_ci* 描述:获取所设的串行队列任务执行超时时间 944484543d1Sopenharmony_ci 945484543d1Sopenharmony_ci* 参数:不涉及 946484543d1Sopenharmony_ci 947484543d1Sopenharmony_ci* 返回值: 948484543d1Sopenharmony_ci 949484543d1Sopenharmony_ci `timeout`:串行队列任务执行超时时间,单位为us 950484543d1Sopenharmony_ci 951484543d1Sopenharmony_ci##### set timeout callback 952484543d1Sopenharmony_ci 953484543d1Sopenharmony_ci```{.cpp} 954484543d1Sopenharmony_cinamespace ffrt { 955484543d1Sopenharmony_ciqueue_attr& callback(std::function<void()>& func); 956484543d1Sopenharmony_ci} 957484543d1Sopenharmony_ci``` 958484543d1Sopenharmony_ci 959484543d1Sopenharmony_ci* 描述:设置串行队列超时回调函数 960484543d1Sopenharmony_ci 961484543d1Sopenharmony_ci* 参数: 962484543d1Sopenharmony_ci 963484543d1Sopenharmony_ci `func`:可被std::function接收的一切CPU可执行体,可以为C++定义的Lambda函数闭包,函数指针,甚至是函数对象 964484543d1Sopenharmony_ci 965484543d1Sopenharmony_ci* 返回值: 966484543d1Sopenharmony_ci 967484543d1Sopenharmony_ci `queue_attr`:串行队列的属性 968484543d1Sopenharmony_ci 969484543d1Sopenharmony_ci##### get timeout callback 970484543d1Sopenharmony_ci 971484543d1Sopenharmony_ci```{.cpp} 972484543d1Sopenharmony_cinamespace ffrt { 973484543d1Sopenharmony_ciffrt_function_header_t* callback() const; 974484543d1Sopenharmony_ci} 975484543d1Sopenharmony_ci``` 976484543d1Sopenharmony_ci 977484543d1Sopenharmony_ci* 描述:获取所设的串行队列超时回调函数 978484543d1Sopenharmony_ci 979484543d1Sopenharmony_ci* 参数:不涉及 980484543d1Sopenharmony_ci 981484543d1Sopenharmony_ci* 返回值: 982484543d1Sopenharmony_ci 983484543d1Sopenharmony_ci `ffrt_function_header_t`:任务执行器,描述了该CPU Task如何执行和销毁的函数指针 984484543d1Sopenharmony_ci 985484543d1Sopenharmony_ci#### 样例 986484543d1Sopenharmony_ci```{.cpp} 987484543d1Sopenharmony_ci#include <stdio.h> 988484543d1Sopenharmony_ci#include "ffrt.h" 989484543d1Sopenharmony_ci 990484543d1Sopenharmony_ciint main(int narg, char** argv) 991484543d1Sopenharmony_ci{ 992484543d1Sopenharmony_ci int x = 0; 993484543d1Sopenharmony_ci std::function<void()> callbackFunc = [&x]() { 994484543d1Sopenharmony_ci x++; 995484543d1Sopenharmony_ci }; 996484543d1Sopenharmony_ci 997484543d1Sopenharmony_ci // 创建队列,可设置队列优先级,默认为default等级 998484543d1Sopenharmony_ci ffrt::queue q1("test_queue", queue_attr().qos(qos_utility)); 999484543d1Sopenharmony_ci 1000484543d1Sopenharmony_ci // 创建队列,可通过设置timeout打开队列任务超时监测,默认不设置(关闭) 1001484543d1Sopenharmony_ci // 超时会打印Error日志并执行用户设置的callback(可选) 1002484543d1Sopenharmony_ci ffrt::queue q2("test_queue", ffrt::queue_attr().timeout(1000).callback(callbackFunc)); 1003484543d1Sopenharmony_ci 1004484543d1Sopenharmony_ci return 0; 1005484543d1Sopenharmony_ci} 1006484543d1Sopenharmony_ci``` 1007484543d1Sopenharmony_ci 1008484543d1Sopenharmony_ci 1009484543d1Sopenharmony_ci## 同步原语 1010484543d1Sopenharmony_ci 1011484543d1Sopenharmony_ci### mutex 1012484543d1Sopenharmony_ci<hr/> 1013484543d1Sopenharmony_ci* FFRT提供的类似std::mutex 的性能实现 1014484543d1Sopenharmony_ci 1015484543d1Sopenharmony_ci#### 声明 1016484543d1Sopenharmony_ci 1017484543d1Sopenharmony_ci```{.cpp} 1018484543d1Sopenharmony_cinamespace ffrt { 1019484543d1Sopenharmony_ciclass mutex { 1020484543d1Sopenharmony_cipublic: 1021484543d1Sopenharmony_ci mutex(mutex const &) = delete; 1022484543d1Sopenharmony_ci void operator =(mutex const &) = delete; 1023484543d1Sopenharmony_ci 1024484543d1Sopenharmony_ci void lock(); 1025484543d1Sopenharmony_ci void unlock(); 1026484543d1Sopenharmony_ci bool try_lock(); 1027484543d1Sopenharmony_ci}; 1028484543d1Sopenharmony_ci} 1029484543d1Sopenharmony_ci``` 1030484543d1Sopenharmony_ci 1031484543d1Sopenharmony_ci#### 参数 1032484543d1Sopenharmony_ci 1033484543d1Sopenharmony_ci* 不涉及 1034484543d1Sopenharmony_ci 1035484543d1Sopenharmony_ci#### 返回值 1036484543d1Sopenharmony_ci 1037484543d1Sopenharmony_ci* 不涉及 1038484543d1Sopenharmony_ci 1039484543d1Sopenharmony_ci#### 描述 1040484543d1Sopenharmony_ci* 该功能能够避免传统的std::mutex 在抢不到锁时陷入内核的问题,在使用得当的条件下将会有更好的性能 1041484543d1Sopenharmony_ci 1042484543d1Sopenharmony_ci#### 样例 1043484543d1Sopenharmony_ci 1044484543d1Sopenharmony_ci```{.cpp} 1045484543d1Sopenharmony_ci#include <iostream> 1046484543d1Sopenharmony_ci#include "ffrt.h" 1047484543d1Sopenharmony_ci 1048484543d1Sopenharmony_civoid ffrt_mutex_task() 1049484543d1Sopenharmony_ci{ 1050484543d1Sopenharmony_ci int sum = 0; 1051484543d1Sopenharmony_ci ffrt::mutex mtx; 1052484543d1Sopenharmony_ci for (int i = 0; i < 10; i++) { 1053484543d1Sopenharmony_ci ffrt::submit([&sum, i, &mtx] { 1054484543d1Sopenharmony_ci mtx.lock(); 1055484543d1Sopenharmony_ci sum = sum + i; 1056484543d1Sopenharmony_ci mtx.unlock(); 1057484543d1Sopenharmony_ci }, {}, {}); 1058484543d1Sopenharmony_ci } 1059484543d1Sopenharmony_ci ffrt::wait(); 1060484543d1Sopenharmony_ci std::cout << "sum = " << sum << std::endl; 1061484543d1Sopenharmony_ci} 1062484543d1Sopenharmony_ci 1063484543d1Sopenharmony_ciint main(int narg, char** argv) 1064484543d1Sopenharmony_ci{ 1065484543d1Sopenharmony_ci int r; 1066484543d1Sopenharmony_ci ffrt::submit(ffrt_mutex_task); 1067484543d1Sopenharmony_ci ffrt::wait(); 1068484543d1Sopenharmony_ci return 0; 1069484543d1Sopenharmony_ci} 1070484543d1Sopenharmony_ci``` 1071484543d1Sopenharmony_ci 1072484543d1Sopenharmony_ci预期输出为 1073484543d1Sopenharmony_ci 1074484543d1Sopenharmony_ci``` 1075484543d1Sopenharmony_cisum=45 1076484543d1Sopenharmony_ci``` 1077484543d1Sopenharmony_ci 1078484543d1Sopenharmony_ci* 该例子为功能示例,实际中并不鼓励这样使用 1079484543d1Sopenharmony_ci 1080484543d1Sopenharmony_ci### shared_mutex 1081484543d1Sopenharmony_ci<hr/> 1082484543d1Sopenharmony_ci* FFRT提供的类似std::shared_mutex 的性能实现 1083484543d1Sopenharmony_ci 1084484543d1Sopenharmony_ci#### 声明 1085484543d1Sopenharmony_ci 1086484543d1Sopenharmony_ci```{.cpp} 1087484543d1Sopenharmony_cinamespace ffrt { 1088484543d1Sopenharmony_ciclass shared_mutex { 1089484543d1Sopenharmony_cipublic: 1090484543d1Sopenharmony_ci shared_mutex(shared_mutex const &) = delete; 1091484543d1Sopenharmony_ci void operator =(shared_mutex const &) = delete; 1092484543d1Sopenharmony_ci 1093484543d1Sopenharmony_ci void lock(); 1094484543d1Sopenharmony_ci void unlock(); 1095484543d1Sopenharmony_ci bool try_lock(); 1096484543d1Sopenharmony_ci 1097484543d1Sopenharmony_ci void lock_shared(); 1098484543d1Sopenharmony_ci void unlock_shared(); 1099484543d1Sopenharmony_ci bool try_lock_shared(); 1100484543d1Sopenharmony_ci}; 1101484543d1Sopenharmony_ci} 1102484543d1Sopenharmony_ci``` 1103484543d1Sopenharmony_ci 1104484543d1Sopenharmony_ci#### 参数 1105484543d1Sopenharmony_ci 1106484543d1Sopenharmony_ci* 不涉及 1107484543d1Sopenharmony_ci 1108484543d1Sopenharmony_ci#### 返回值 1109484543d1Sopenharmony_ci 1110484543d1Sopenharmony_ci* 不涉及 1111484543d1Sopenharmony_ci 1112484543d1Sopenharmony_ci#### 描述 1113484543d1Sopenharmony_ci* 该功能能够避免传统的std::shared_mutex 在抢不到锁时陷入内核的问题,在使用得当的条件下将会有更好的性能 1114484543d1Sopenharmony_ci 1115484543d1Sopenharmony_ci#### 样例 1116484543d1Sopenharmony_ci 1117484543d1Sopenharmony_ci```{.cpp} 1118484543d1Sopenharmony_ci#include <iostream> 1119484543d1Sopenharmony_ci#include "ffrt_inner.h" 1120484543d1Sopenharmony_ci 1121484543d1Sopenharmony_civoid ffrt_shared_mutex_task() 1122484543d1Sopenharmony_ci{ 1123484543d1Sopenharmony_ci int sum = 0; 1124484543d1Sopenharmony_ci ffrt::shared_mutex mtx; 1125484543d1Sopenharmony_ci for (int i = 0; i < 10; i++) { 1126484543d1Sopenharmony_ci ffrt::submit([&sum, i, &mtx] { 1127484543d1Sopenharmony_ci mtx.lock(); 1128484543d1Sopenharmony_ci sum = sum + i; 1129484543d1Sopenharmony_ci mtx.unlock(); 1130484543d1Sopenharmony_ci }, {}, {}); 1131484543d1Sopenharmony_ci for (int j = 0; j < 5; j++) { 1132484543d1Sopenharmony_ci ffrt::submit([&sum, j, &mtx] { 1133484543d1Sopenharmony_ci mtx.lock_shared(); 1134484543d1Sopenharmony_ci std::cout << "sum = " << sum << std::endl; 1135484543d1Sopenharmony_ci mtx.unlock_shared(); 1136484543d1Sopenharmony_ci }, {}, {}); 1137484543d1Sopenharmony_ci } 1138484543d1Sopenharmony_ci } 1139484543d1Sopenharmony_ci ffrt::wait(); 1140484543d1Sopenharmony_ci std::cout << "sum = " << sum << std::endl; 1141484543d1Sopenharmony_ci} 1142484543d1Sopenharmony_ci 1143484543d1Sopenharmony_ciint main(int narg, char** argv) 1144484543d1Sopenharmony_ci{ 1145484543d1Sopenharmony_ci int r; 1146484543d1Sopenharmony_ci ffrt::submit(ffrt_shared_mutex_task); 1147484543d1Sopenharmony_ci ffrt::wait(); 1148484543d1Sopenharmony_ci return 0; 1149484543d1Sopenharmony_ci} 1150484543d1Sopenharmony_ci``` 1151484543d1Sopenharmony_ci 1152484543d1Sopenharmony_ci预期输出为 1153484543d1Sopenharmony_ci 1154484543d1Sopenharmony_ci``` 1155484543d1Sopenharmony_cisum=45 1156484543d1Sopenharmony_ci``` 1157484543d1Sopenharmony_ci 1158484543d1Sopenharmony_ci* 该例子为功能示例,实际中并不鼓励这样使用 1159484543d1Sopenharmony_ci 1160484543d1Sopenharmony_ci### condition_variable 1161484543d1Sopenharmony_ci<hr/> 1162484543d1Sopenharmony_ci 1163484543d1Sopenharmony_ci* FFRT提供的类似std::condition_variable 的性能实现 1164484543d1Sopenharmony_ci 1165484543d1Sopenharmony_ci#### 声明 1166484543d1Sopenharmony_ci 1167484543d1Sopenharmony_ci```{.cpp} 1168484543d1Sopenharmony_cinamespace ffrt { 1169484543d1Sopenharmony_cienum class cv_status { 1170484543d1Sopenharmony_ci no_timeout, 1171484543d1Sopenharmony_ci timeout 1172484543d1Sopenharmony_ci}; 1173484543d1Sopenharmony_ci 1174484543d1Sopenharmony_ciclass condition_variable { 1175484543d1Sopenharmony_cipublic: 1176484543d1Sopenharmony_ci using TimePoint = std::chrono::steady_clock::time_point; 1177484543d1Sopenharmony_ci template<typename Clock, typename Duration, typename Pred> 1178484543d1Sopenharmony_ci bool wait_until(std::unique_lock<mutex>& lk, 1179484543d1Sopenharmony_ci const std::chrono::time_point<Clock, Duration>& tp, 1180484543d1Sopenharmony_ci Pred&& pred) noexcept; 1181484543d1Sopenharmony_ci 1182484543d1Sopenharmony_ci template<typename Clock, typename Duration> 1183484543d1Sopenharmony_ci cv_status wait_until(std::unique_lock<mutex>& lk, 1184484543d1Sopenharmony_ci const std::chrono::time_point<Clock, Duration>& tp) noexcept; 1185484543d1Sopenharmony_ci 1186484543d1Sopenharmony_ci template<typename Rep, typename Period> 1187484543d1Sopenharmony_ci cv_status wait_for(std::unique_lock<mutex>& lk, 1188484543d1Sopenharmony_ci const std::chrono::duration<Rep, Period>& sleep_time) noexcept; 1189484543d1Sopenharmony_ci 1190484543d1Sopenharmony_ci template<typename Rep, typename Period, typename Pred> 1191484543d1Sopenharmony_ci bool wait_for(std::unique_lock<mutex>& lk, 1192484543d1Sopenharmony_ci const std::chrono::duration<Rep, Period>& sleepTime, 1193484543d1Sopenharmony_ci Pred&& pred) noexcept; 1194484543d1Sopenharmony_ci 1195484543d1Sopenharmony_ci void wait(std::unique_lock<mutex>& lk); 1196484543d1Sopenharmony_ci 1197484543d1Sopenharmony_ci template<typename Pred> 1198484543d1Sopenharmony_ci void wait(std::unique_lock<mutex>& lk, Pred&& pred); 1199484543d1Sopenharmony_ci 1200484543d1Sopenharmony_ci void notify_one() noexcept; 1201484543d1Sopenharmony_ci 1202484543d1Sopenharmony_ci void notify_all() noexcept; 1203484543d1Sopenharmony_ci}; 1204484543d1Sopenharmony_ci} 1205484543d1Sopenharmony_ci``` 1206484543d1Sopenharmony_ci 1207484543d1Sopenharmony_ci#### 参数 1208484543d1Sopenharmony_ci 1209484543d1Sopenharmony_ci`lk` 1210484543d1Sopenharmony_ci* mutex互斥量 1211484543d1Sopenharmony_ci`tp` 1212484543d1Sopenharmony_ci* 等待时间 1213484543d1Sopenharmony_ci`sleep_time` 1214484543d1Sopenharmony_ci* 等待时间 1215484543d1Sopenharmony_ci`pred` 1216484543d1Sopenharmony_ci* 检查是否等待函数 1217484543d1Sopenharmony_ci#### 返回值 1218484543d1Sopenharmony_ci 1219484543d1Sopenharmony_ci* 不涉及 1220484543d1Sopenharmony_ci 1221484543d1Sopenharmony_ci#### 描述 1222484543d1Sopenharmony_ci* 该接口只能在FFRT task 内部调用,在FFRT task 外部调用存在未定义的行为 1223484543d1Sopenharmony_ci* 该功能能够避免传统的std::condition_variable 在条件不满足时陷入内核的问题,在使用得当的条件下将会有更好的性能 1224484543d1Sopenharmony_ci 1225484543d1Sopenharmony_ci#### 样例 1226484543d1Sopenharmony_ci 1227484543d1Sopenharmony_ci```{.cpp} 1228484543d1Sopenharmony_ci#include <iostream> 1229484543d1Sopenharmony_ci#include "ffrt.h" 1230484543d1Sopenharmony_ci 1231484543d1Sopenharmony_civoid ffrt_cv_task() 1232484543d1Sopenharmony_ci{ 1233484543d1Sopenharmony_ci ffrt::condition_variable cond; 1234484543d1Sopenharmony_ci int a = 0; 1235484543d1Sopenharmony_ci ffrt::mutex lock_; 1236484543d1Sopenharmony_ci ffrt::submit([&] { 1237484543d1Sopenharmony_ci std::unique_lock lck(lock_); 1238484543d1Sopenharmony_ci cond.wait(lck, [&] { return a == 1; }); 1239484543d1Sopenharmony_ci std::cout << "a = " << a << std::endl; 1240484543d1Sopenharmony_ci }, {}, {}); 1241484543d1Sopenharmony_ci ffrt::submit([&] { 1242484543d1Sopenharmony_ci std::unique_lock lck(lock_); 1243484543d1Sopenharmony_ci a = 1; 1244484543d1Sopenharmony_ci cond.notify_one(); 1245484543d1Sopenharmony_ci }, {}, {}); 1246484543d1Sopenharmony_ci 1247484543d1Sopenharmony_ci ffrt::wait(); 1248484543d1Sopenharmony_ci} 1249484543d1Sopenharmony_ci 1250484543d1Sopenharmony_ciint main(int narg, char** argv) 1251484543d1Sopenharmony_ci{ 1252484543d1Sopenharmony_ci int r; 1253484543d1Sopenharmony_ci ffrt::submit(ffrt_cv_task); 1254484543d1Sopenharmony_ci ffrt::wait(); 1255484543d1Sopenharmony_ci return 0; 1256484543d1Sopenharmony_ci} 1257484543d1Sopenharmony_ci 1258484543d1Sopenharmony_ci``` 1259484543d1Sopenharmony_ci 1260484543d1Sopenharmony_ci预期输出为: 1261484543d1Sopenharmony_ci 1262484543d1Sopenharmony_ci``` 1263484543d1Sopenharmony_cia=1 1264484543d1Sopenharmony_ci``` 1265484543d1Sopenharmony_ci 1266484543d1Sopenharmony_ci* 该例子为功能示例,实际中并不鼓励这样使用 1267484543d1Sopenharmony_ci 1268484543d1Sopenharmony_ci## 杂项 1269484543d1Sopenharmony_ci 1270484543d1Sopenharmony_ci### sleep 1271484543d1Sopenharmony_ci 1272484543d1Sopenharmony_ci<hr/> 1273484543d1Sopenharmony_ci* FFRT提供的类似std::this_thread::sleep_for / std::this_thread::sleep_until 的性能实现 1274484543d1Sopenharmony_ci 1275484543d1Sopenharmony_ci#### 声明 1276484543d1Sopenharmony_ci 1277484543d1Sopenharmony_ci```{.cpp} 1278484543d1Sopenharmony_cinamespace ffrt { 1279484543d1Sopenharmony_cinamespace this_task { 1280484543d1Sopenharmony_citemplate<class _Rep, class _Period> 1281484543d1Sopenharmony_civoid sleep_for(const std::chrono::duration<_Rep, _Period>& sleep_duration); 1282484543d1Sopenharmony_ci 1283484543d1Sopenharmony_citemplate<class _Clock, class _Duration> 1284484543d1Sopenharmony_civoid sleep_until(const std::chrono::time_point<_Clock, _Duration>& sleep_time); 1285484543d1Sopenharmony_ci} 1286484543d1Sopenharmony_ci} 1287484543d1Sopenharmony_ci``` 1288484543d1Sopenharmony_ci 1289484543d1Sopenharmony_ci#### 参数 1290484543d1Sopenharmony_ci 1291484543d1Sopenharmony_ci`sleep_duration` 1292484543d1Sopenharmony_ci 1293484543d1Sopenharmony_ci* 睡眠的时长 1294484543d1Sopenharmony_ci 1295484543d1Sopenharmony_ci`sleep_time` 1296484543d1Sopenharmony_ci 1297484543d1Sopenharmony_ci* 睡眠到达的时间点 1298484543d1Sopenharmony_ci 1299484543d1Sopenharmony_ci#### 返回值 1300484543d1Sopenharmony_ci 1301484543d1Sopenharmony_ci* 不涉及 1302484543d1Sopenharmony_ci 1303484543d1Sopenharmony_ci#### 描述 1304484543d1Sopenharmony_ci* 该接口只能在FFRT task 内部调用,在FFRT task 外部调用存在未定义的行为 1305484543d1Sopenharmony_ci* 该功能能够避免传统的std::this_thread::sleep_for 睡眠时陷入内核的问题,在使用得当的条件下将会有更好的性能 1306484543d1Sopenharmony_ci* 该接口调用后实际睡眠时长不小于配置值 1307484543d1Sopenharmony_ci 1308484543d1Sopenharmony_ci#### 样例 1309484543d1Sopenharmony_ci 1310484543d1Sopenharmony_ci```{.cpp} 1311484543d1Sopenharmony_ci#include <chrono> 1312484543d1Sopenharmony_ci#include <iostream> 1313484543d1Sopenharmony_ci#include "ffrt.h" 1314484543d1Sopenharmony_ci 1315484543d1Sopenharmony_ciusing namespace std::chrono_literals; 1316484543d1Sopenharmony_ciint main(int narg, char** argv) 1317484543d1Sopenharmony_ci{ 1318484543d1Sopenharmony_ci ffrt::submit([] { 1319484543d1Sopenharmony_ci std::cout << "Hello waiter\n" << std::flush; 1320484543d1Sopenharmony_ci auto start = std::chrono::high_resolution_clock::now(); 1321484543d1Sopenharmony_ci ffrt::this_task::sleep_for(2000ms); 1322484543d1Sopenharmony_ci auto end = std::chrono::high_resolution_clock::now(); 1323484543d1Sopenharmony_ci std::chrono::duration<double, std::milli> elapsed = end-start; 1324484543d1Sopenharmony_ci std::cout << "Waited " << elapsed.count() << " ms\n"; 1325484543d1Sopenharmony_ci }); 1326484543d1Sopenharmony_ci ffrt::wait(); 1327484543d1Sopenharmony_ci return 0; 1328484543d1Sopenharmony_ci} 1329484543d1Sopenharmony_ci``` 1330484543d1Sopenharmony_ci 1331484543d1Sopenharmony_ci* 预期输出为 1332484543d1Sopenharmony_ci 1333484543d1Sopenharmony_ci``` 1334484543d1Sopenharmony_ciHello waiter 1335484543d1Sopenharmony_ciWaited 2000.12 ms 1336484543d1Sopenharmony_ci``` 1337484543d1Sopenharmony_ci 1338484543d1Sopenharmony_ci### yield 1339484543d1Sopenharmony_ci<hr/> 1340484543d1Sopenharmony_ci* 当前task 主动让出CPU 执行资源,让其他可以被执行的task 先执行,如果没有其他可被执行的task,yield 无效 1341484543d1Sopenharmony_ci 1342484543d1Sopenharmony_ci#### 声明 1343484543d1Sopenharmony_ci 1344484543d1Sopenharmony_ci```{.cpp} 1345484543d1Sopenharmony_cinamespace ffrt { 1346484543d1Sopenharmony_cinamespace this_task { 1347484543d1Sopenharmony_civoid yield(); 1348484543d1Sopenharmony_ci} 1349484543d1Sopenharmony_ci} 1350484543d1Sopenharmony_ci``` 1351484543d1Sopenharmony_ci 1352484543d1Sopenharmony_ci#### 参数 1353484543d1Sopenharmony_ci 1354484543d1Sopenharmony_ci* 不涉及 1355484543d1Sopenharmony_ci 1356484543d1Sopenharmony_ci#### 返回值 1357484543d1Sopenharmony_ci 1358484543d1Sopenharmony_ci* 不涉及 1359484543d1Sopenharmony_ci 1360484543d1Sopenharmony_ci#### 描述 1361484543d1Sopenharmony_ci* 该接口只能在FFRT task 内部调用,在FFRT task 外部调用存在未定义的行为 1362484543d1Sopenharmony_ci* 此函数的确切行为取决于实现,特别是使用中的FFRT 调度程序的机制和系统状态 1363484543d1Sopenharmony_ci 1364484543d1Sopenharmony_ci#### 样例 1365484543d1Sopenharmony_ci 1366484543d1Sopenharmony_ci```{.cpp} 1367484543d1Sopenharmony_ci#include <chrono> 1368484543d1Sopenharmony_ci#include "ffrt.h" 1369484543d1Sopenharmony_ci 1370484543d1Sopenharmony_ciusing namespace std::chrono_literals; 1371484543d1Sopenharmony_ci// "busy sleep" while suggesting that other tasks run 1372484543d1Sopenharmony_ci// for a small amount of time 1373484543d1Sopenharmony_civoid little_sleep(std::chrono::microseconds us) 1374484543d1Sopenharmony_ci{ 1375484543d1Sopenharmony_ci auto start = std::chrono::high_resolution_clock::now(); 1376484543d1Sopenharmony_ci auto end = start + us; 1377484543d1Sopenharmony_ci do { 1378484543d1Sopenharmony_ci ffrt::this_task::yield(); 1379484543d1Sopenharmony_ci } while (std::chrono::high_resolution_clock::now() < end); 1380484543d1Sopenharmony_ci} 1381484543d1Sopenharmony_ci 1382484543d1Sopenharmony_ciint main(int narg, char** argv) 1383484543d1Sopenharmony_ci{ 1384484543d1Sopenharmony_ci ffrt::submit([] { little_sleep(200us); }); 1385484543d1Sopenharmony_ci ffrt::wait(); 1386484543d1Sopenharmony_ci return 0; 1387484543d1Sopenharmony_ci} 1388484543d1Sopenharmony_ci``` 1389484543d1Sopenharmony_ci 1390484543d1Sopenharmony_ci* 这是一个`busy sleep`,同时允许其他可以被执行的task 插入执行 1391484543d1Sopenharmony_ci 1392484543d1Sopenharmony_ci 1393484543d1Sopenharmony_ci# C API 1394484543d1Sopenharmony_ci 1395484543d1Sopenharmony_ci> C API采用接近C11/pthread (https://zh.cppreference.com/w/c) 的命名风格,并冠以`ffrt_`前缀,以`_base`为后缀的API是内部API,通常不被用户直接调用 1396484543d1Sopenharmony_ci> 1397484543d1Sopenharmony_ci> **出于易用性方面的考虑,除非必要,强烈建议你使用C++ API(亦满足二进制兼容要求),调用C API将会使你的代码非常臃肿** 1398484543d1Sopenharmony_ci 1399484543d1Sopenharmony_ci## 任务管理 1400484543d1Sopenharmony_ci 1401484543d1Sopenharmony_ci### ffrt_submit_base 1402484543d1Sopenharmony_ci 1403484543d1Sopenharmony_ci* 该接口为ffrt动态库的导出接口,基于此可以封装出不同的C++ API ffrt::submit和C API ffrt_submit,满足二进制兼容 1404484543d1Sopenharmony_ci 1405484543d1Sopenharmony_ci#### 声明 1406484543d1Sopenharmony_ci 1407484543d1Sopenharmony_ci```{.cpp} 1408484543d1Sopenharmony_ciconst int ffrt_auto_managed_function_storage_size = 64 + sizeof(ffrt_function_header_t); 1409484543d1Sopenharmony_citypedef enum { 1410484543d1Sopenharmony_ci ffrt_function_kind_general, 1411484543d1Sopenharmony_ci ffrt_function_kind_queue 1412484543d1Sopenharmony_ci} ffrt_function_kind_t; 1413484543d1Sopenharmony_ci 1414484543d1Sopenharmony_civoid* ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_t kind); 1415484543d1Sopenharmony_ci 1416484543d1Sopenharmony_citypedef void(*ffrt_function_t)(void*); 1417484543d1Sopenharmony_citypedef struct { 1418484543d1Sopenharmony_ci ffrt_function_t exec; 1419484543d1Sopenharmony_ci ffrt_function_t destroy; 1420484543d1Sopenharmony_ci uint64_t reserve[2]; 1421484543d1Sopenharmony_ci} ffrt_function_header_t; 1422484543d1Sopenharmony_ci 1423484543d1Sopenharmony_civoid ffrt_submit_base(ffrt_function_header_t* func, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr); 1424484543d1Sopenharmony_ci``` 1425484543d1Sopenharmony_ci 1426484543d1Sopenharmony_ci#### 参数 1427484543d1Sopenharmony_ci 1428484543d1Sopenharmony_ci`kind` 1429484543d1Sopenharmony_ci 1430484543d1Sopenharmony_ci* function子类型,用于优化内部数据结构,默认使用ffrt_function_kind_general类型 1431484543d1Sopenharmony_ci 1432484543d1Sopenharmony_ci`func` 1433484543d1Sopenharmony_ci 1434484543d1Sopenharmony_ci* CPU Function的指针,该指针执行的数据结构,按照`ffrt_function_header_t`定义的描述了该CPU Task如何执行和销毁的函数指针,FFRT通过这两个函数指针完成Task的执行和销毁 1435484543d1Sopenharmony_ci 1436484543d1Sopenharmony_ci`in_deps` 1437484543d1Sopenharmony_ci 1438484543d1Sopenharmony_ci* 同ffrt_submit 1439484543d1Sopenharmony_ci 1440484543d1Sopenharmony_ci 1441484543d1Sopenharmony_ci`out_deps` 1442484543d1Sopenharmony_ci 1443484543d1Sopenharmony_ci* 同ffrt_submit 1444484543d1Sopenharmony_ci 1445484543d1Sopenharmony_ci`attr` 1446484543d1Sopenharmony_ci 1447484543d1Sopenharmony_ci* 同ffrt_submit 1448484543d1Sopenharmony_ci 1449484543d1Sopenharmony_ci#### 返回值 1450484543d1Sopenharmony_ci 1451484543d1Sopenharmony_ci* 不涉及 1452484543d1Sopenharmony_ci 1453484543d1Sopenharmony_ci#### 描述 1454484543d1Sopenharmony_ci 1455484543d1Sopenharmony_ci* ffrt_submit_base不建议用户直接调用,推荐使用基于此封装的C++接口(亦满足二进制兼容) 1456484543d1Sopenharmony_ci* **ffrt_submit_base作为底层能力,只有在用户需要自定义task类型时使用,使用时需要满足以下限制:** 1457484543d1Sopenharmony_ci * ffrt_submit_base入参中的func指针只能通过ffrt_alloc_auto_managed_function_storage_base申请,且二者的调用需一一对应 1458484543d1Sopenharmony_ci * ffrt_alloc_auto_managed_function_storage_base申请的内存为ffrt_auto_managed_function_storage_size字节,其生命周期归ffrt管理,在该task结束时,由FFRT自动释放,用户无需释放 1459484543d1Sopenharmony_ci* ffrt_function_header_t 中定义了两个函数指针: 1460484543d1Sopenharmony_ci * exec:用于描述该Task如何被执行,当FFRT需要执行该Task时由FFRT调用 1461484543d1Sopenharmony_ci * destroy:用于描述该Task如何被执行,当FFRT需要执行该Task时由FFRT调用 1462484543d1Sopenharmony_ci 1463484543d1Sopenharmony_ci#### 样例 1464484543d1Sopenharmony_ci 1465484543d1Sopenharmony_ci* 通过该接口提供C++11 Lambda表达式的支持(该代码已经在ffrr.h中提供,默认支持) 1466484543d1Sopenharmony_ci 1467484543d1Sopenharmony_ci```{.cpp} 1468484543d1Sopenharmony_citemplate<class T> 1469484543d1Sopenharmony_cistruct function { 1470484543d1Sopenharmony_ci template<class CT> 1471484543d1Sopenharmony_ci function(ffrt_function_header_t h, CT&& c) : header(h), closure(std::forward<CT>(c)) {} 1472484543d1Sopenharmony_ci ffrt_function_header_t header; 1473484543d1Sopenharmony_ci T closure; 1474484543d1Sopenharmony_ci}; 1475484543d1Sopenharmony_ci 1476484543d1Sopenharmony_citemplate<class T> 1477484543d1Sopenharmony_civoid exec_function_wrapper(void* t) 1478484543d1Sopenharmony_ci{ 1479484543d1Sopenharmony_ci auto f = (function<std::decay_t<T>>*)t; 1480484543d1Sopenharmony_ci f->closure(); 1481484543d1Sopenharmony_ci} 1482484543d1Sopenharmony_ci 1483484543d1Sopenharmony_citemplate<class T> 1484484543d1Sopenharmony_civoid destroy_function_wrapper(void* t) 1485484543d1Sopenharmony_ci{ 1486484543d1Sopenharmony_ci auto f = (function<std::decay_t<T>>*)t; 1487484543d1Sopenharmony_ci f->closure = nullptr; 1488484543d1Sopenharmony_ci} 1489484543d1Sopenharmony_ci 1490484543d1Sopenharmony_citemplate<class T> 1491484543d1Sopenharmony_ciinline ffrt_function_header_t* create_function_wrapper(T&& func) 1492484543d1Sopenharmony_ci{ 1493484543d1Sopenharmony_ci using function_type = function<std::decay_t<T>>; 1494484543d1Sopenharmony_ci static_assert(sizeof(function_type) <= ffrt_auto_managed_function_storage_size, 1495484543d1Sopenharmony_ci "size of function must be less than ffrt_auto_managed_function_storage_size"); 1496484543d1Sopenharmony_ci 1497484543d1Sopenharmony_ci auto p = ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); 1498484543d1Sopenharmony_ci auto f = new (p) function_type( 1499484543d1Sopenharmony_ci {exec_function_wrapper<T>, destroy_function_wrapper<T>}, 1500484543d1Sopenharmony_ci std::forward<T>(func)); 1501484543d1Sopenharmony_ci return (ffrt_function_header_t*)f; 1502484543d1Sopenharmony_ci} 1503484543d1Sopenharmony_ci 1504484543d1Sopenharmony_cistatic inline void submit(std::function<void()>&& func) 1505484543d1Sopenharmony_ci{ 1506484543d1Sopenharmony_ci return ffrt_submit_base(create_function_wrapper(std::move(func)), NULL, NULL, NULL); 1507484543d1Sopenharmony_ci} 1508484543d1Sopenharmony_ci``` 1509484543d1Sopenharmony_ci 1510484543d1Sopenharmony_ci### ffrt_wait 1511484543d1Sopenharmony_ci 1512484543d1Sopenharmony_ci<hr/> 1513484543d1Sopenharmony_ci* 同步等待,与ffrt_submit 配合使用 1514484543d1Sopenharmony_ci* 等待指定的数据被生产完成,或等待当前任务的所有子任务完成,在不满足条件之前,当前的执行上下文被suspend,在满足条件后恢复执行 1515484543d1Sopenharmony_ci 1516484543d1Sopenharmony_ci#### 声明 1517484543d1Sopenharmony_ci 1518484543d1Sopenharmony_ci```{.cpp} 1519484543d1Sopenharmony_civoid ffrt_wait_deps(ffrt_deps_t* deps); 1520484543d1Sopenharmony_civoid ffrt_wait(); 1521484543d1Sopenharmony_ci``` 1522484543d1Sopenharmony_ci 1523484543d1Sopenharmony_ci#### 参数 1524484543d1Sopenharmony_ci 1525484543d1Sopenharmony_ci`deps` 1526484543d1Sopenharmony_ci 1527484543d1Sopenharmony_ci* 需要等待被生产完成的数据的虚拟地址,这些地址可能作为某些任务在submit 时的out_deps,该依赖的生成见ffrt_deps_t章节,空指针表示无依赖 1528484543d1Sopenharmony_ci 1529484543d1Sopenharmony_ci#### 返回值 1530484543d1Sopenharmony_ci 1531484543d1Sopenharmony_ci* 不涉及 1532484543d1Sopenharmony_ci 1533484543d1Sopenharmony_ci#### 描述 1534484543d1Sopenharmony_ci* ffrt_wait_deps(deps) 用于等待deps指代的数据被生产完成才能执行后面的代码 1535484543d1Sopenharmony_ci* ffrt_wait() 用于等待当前上下文提交的所有子任务(`注意:不包括孙任务和下级子任务`)都完成才能执行后面的代码 1536484543d1Sopenharmony_ci* 该接口支持在FFRT task 内部调用,也支持在FFRT task 外部调用 1537484543d1Sopenharmony_ci* 在FFRT task 外部调用的wait 是OS 能够感知的等待,相对于FFRT task 内部调用的wait 是更加昂贵的,因此我们希望尽可能让更多的wait 发生在FFRT task 内部 ,而不是FFRT task 外部 1538484543d1Sopenharmony_ci 1539484543d1Sopenharmony_ci#### 样例 1540484543d1Sopenharmony_ci 1541484543d1Sopenharmony_ci**recursive fibonacci** 1542484543d1Sopenharmony_ci 1543484543d1Sopenharmony_ci串行版的fibonacci 可以实现为: 1544484543d1Sopenharmony_ci 1545484543d1Sopenharmony_ci```{.c} 1546484543d1Sopenharmony_ci#include <stdio.h> 1547484543d1Sopenharmony_ci 1548484543d1Sopenharmony_civoid fib(int x, int* y) { 1549484543d1Sopenharmony_ci if (x <= 1) { 1550484543d1Sopenharmony_ci *y = x; 1551484543d1Sopenharmony_ci } else { 1552484543d1Sopenharmony_ci int y1, y2; 1553484543d1Sopenharmony_ci fib(x - 1, &y1); 1554484543d1Sopenharmony_ci fib(x - 2, &y2); 1555484543d1Sopenharmony_ci *y = y1 + y2; 1556484543d1Sopenharmony_ci } 1557484543d1Sopenharmony_ci} 1558484543d1Sopenharmony_ciint main(int narg, char** argv) 1559484543d1Sopenharmony_ci{ 1560484543d1Sopenharmony_ci int r; 1561484543d1Sopenharmony_ci fib(10, &r); 1562484543d1Sopenharmony_ci printf("fibonacci 10: %d\n", r); 1563484543d1Sopenharmony_ci return 0; 1564484543d1Sopenharmony_ci} 1565484543d1Sopenharmony_ci``` 1566484543d1Sopenharmony_ci 1567484543d1Sopenharmony_ci若要使用 FFRT 实现并行(注,对于单纯的fibonacci,单个 Task 的计算量极小,不具有并行加速的意义,但这种调用pattern 对并行编程模型的灵活性考验是非常高的),其中1种可行的实现为: 1568484543d1Sopenharmony_ci 1569484543d1Sopenharmony_ci```{.c} 1570484543d1Sopenharmony_ci#include <stdio.h> 1571484543d1Sopenharmony_ci#include "ffrt.h" 1572484543d1Sopenharmony_ci 1573484543d1Sopenharmony_citypedef struct { 1574484543d1Sopenharmony_ci int x; 1575484543d1Sopenharmony_ci int* y; 1576484543d1Sopenharmony_ci} fib_ffrt_s; 1577484543d1Sopenharmony_ci 1578484543d1Sopenharmony_citypedef struct { 1579484543d1Sopenharmony_ci ffrt_function_header_t header; 1580484543d1Sopenharmony_ci ffrt_function_t func; 1581484543d1Sopenharmony_ci ffrt_function_t after_func; 1582484543d1Sopenharmony_ci void* arg; 1583484543d1Sopenharmony_ci} c_function; 1584484543d1Sopenharmony_ci 1585484543d1Sopenharmony_cistatic void ffrt_exec_function_wrapper(void* t) 1586484543d1Sopenharmony_ci{ 1587484543d1Sopenharmony_ci c_function* f = (c_function*)t; 1588484543d1Sopenharmony_ci if (f->func) { 1589484543d1Sopenharmony_ci f->func(f->arg); 1590484543d1Sopenharmony_ci } 1591484543d1Sopenharmony_ci} 1592484543d1Sopenharmony_ci 1593484543d1Sopenharmony_cistatic void ffrt_destroy_function_wrapper(void* t) 1594484543d1Sopenharmony_ci{ 1595484543d1Sopenharmony_ci c_function* f = (c_function*)t; 1596484543d1Sopenharmony_ci if (f->after_func) { 1597484543d1Sopenharmony_ci f->after_func(f->arg); 1598484543d1Sopenharmony_ci } 1599484543d1Sopenharmony_ci} 1600484543d1Sopenharmony_ci 1601484543d1Sopenharmony_ci#define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1]) 1602484543d1Sopenharmony_cistatic inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func, 1603484543d1Sopenharmony_ci const ffrt_function_t after_func, void* arg) 1604484543d1Sopenharmony_ci{ 1605484543d1Sopenharmony_ci FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size, 1606484543d1Sopenharmony_ci size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size); 1607484543d1Sopenharmony_ci c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); 1608484543d1Sopenharmony_ci f->header.exec = ffrt_exec_function_wrapper; 1609484543d1Sopenharmony_ci f->header.destroy = ffrt_destroy_function_wrapper; 1610484543d1Sopenharmony_ci f->func = func; 1611484543d1Sopenharmony_ci f->after_func = after_func; 1612484543d1Sopenharmony_ci f->arg = arg; 1613484543d1Sopenharmony_ci return (ffrt_function_header_t*)f; 1614484543d1Sopenharmony_ci} 1615484543d1Sopenharmony_ci 1616484543d1Sopenharmony_cistatic inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func, 1617484543d1Sopenharmony_ci void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr) 1618484543d1Sopenharmony_ci{ 1619484543d1Sopenharmony_ci ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr); 1620484543d1Sopenharmony_ci} 1621484543d1Sopenharmony_ci 1622484543d1Sopenharmony_civoid fib_ffrt(void* arg) 1623484543d1Sopenharmony_ci{ 1624484543d1Sopenharmony_ci fib_ffrt_s* p = (fib_ffrt_s*)arg; 1625484543d1Sopenharmony_ci int x = p->x; 1626484543d1Sopenharmony_ci int* y = p->y; 1627484543d1Sopenharmony_ci 1628484543d1Sopenharmony_ci if (x <= 1) { 1629484543d1Sopenharmony_ci *y = x; 1630484543d1Sopenharmony_ci } else { 1631484543d1Sopenharmony_ci int y1, y2; 1632484543d1Sopenharmony_ci fib_ffrt_s s1 = {x - 1, &y1}; 1633484543d1Sopenharmony_ci fib_ffrt_s s2 = {x - 2, &y2}; 1634484543d1Sopenharmony_ci const std::vector<ffrt_dependence_t> dx_deps = {{ffrt_dependence_data, &x}}; 1635484543d1Sopenharmony_ci ffrt_deps_t dx{static_cast<uint32_t>(dx_deps.size()), dx_deps.data()}; 1636484543d1Sopenharmony_ci const std::vector<ffrt_dependence_t> dy1_deps = {{ffrt_dependence_data, &y1}}; 1637484543d1Sopenharmony_ci ffrt_deps_t dy1{static_cast<uint32_t>(dy1_deps.size()), dy1_deps.data()}; 1638484543d1Sopenharmony_ci const std::vector<ffrt_dependence_t> dy2_deps = {{ffrt_dependence_data, &y2}}; 1639484543d1Sopenharmony_ci ffrt_deps_t dy2{static_cast<uint32_t>(dy2_deps.size()), dy2_deps.data()}; 1640484543d1Sopenharmony_ci const std::vector<ffrt_dependence_t> dy12_deps = {{ffrt_dependence_data, &y1}, {ffrt_dependence_data, &y2}}; 1641484543d1Sopenharmony_ci ffrt_deps_t dy12{static_cast<uint32_t>(dy12_deps.size()), dy12_deps.data()}; 1642484543d1Sopenharmony_ci ffrt_submit_c(fib_ffrt, NULL, &s1, &dx, &dy1, NULL); 1643484543d1Sopenharmony_ci ffrt_submit_c(fib_ffrt, NULL, &s2, &dx, &dy2, NULL); 1644484543d1Sopenharmony_ci ffrt_wait_deps(&dy12); 1645484543d1Sopenharmony_ci *y = y1 + y2; 1646484543d1Sopenharmony_ci } 1647484543d1Sopenharmony_ci} 1648484543d1Sopenharmony_ci 1649484543d1Sopenharmony_ciint main(int narg, char** argv) 1650484543d1Sopenharmony_ci{ 1651484543d1Sopenharmony_ci int r; 1652484543d1Sopenharmony_ci fib_ffrt_s s = {10, &r}; 1653484543d1Sopenharmony_ci const std::vector<ffrt_dependence_t> dr_deps = {{ffrt_dependence_data, &r}}; 1654484543d1Sopenharmony_ci ffrt_deps_t dr{static_cast<uint32_t>(dr_deps.size()), dr_deps.data()}; 1655484543d1Sopenharmony_ci ffrt_submit_c(fib_ffrt, NULL, &s, NULL, &dr, NULL); 1656484543d1Sopenharmony_ci ffrt_wait_deps(&dr); 1657484543d1Sopenharmony_ci printf("fibonacci 10: %d\n", r); 1658484543d1Sopenharmony_ci return 0; 1659484543d1Sopenharmony_ci} 1660484543d1Sopenharmony_ci``` 1661484543d1Sopenharmony_ci 1662484543d1Sopenharmony_ci`解析`: 1663484543d1Sopenharmony_ci 1664484543d1Sopenharmony_ci1) 将fibonacci (x-1)和fibonacci (x-2) 作为2个Task 提交给FFRT,在两个Task 完成之后将结果累加; 1665484543d1Sopenharmony_ci 1666484543d1Sopenharmony_ci2) 虽然单个Task 只能拆分成2个SubTask 但是子Task 可以继续拆分,因此,整个计算图的并行度是非常高的,Task 之间在FFRT 内部形成了一颗调用树; 1667484543d1Sopenharmony_ci 1668484543d1Sopenharmony_ci<img src="images/image-20220926152331554.png" style="zoom:100%" /> 1669484543d1Sopenharmony_ci 1670484543d1Sopenharmony_ci> 以上实现,逻辑上虽与C++ API中的实现类似,但是用户显式管理数据生命周期和函数入参打包两个因素将使代码异常复杂 1671484543d1Sopenharmony_ci 1672484543d1Sopenharmony_ci 1673484543d1Sopenharmony_ci 1674484543d1Sopenharmony_ci### ffrt_deps_t 1675484543d1Sopenharmony_ci 1676484543d1Sopenharmony_ci* C API中对依赖数组的抽象,逻辑上等同于C++ API中的`std::vector<void*>` 1677484543d1Sopenharmony_ci 1678484543d1Sopenharmony_ci#### 声明 1679484543d1Sopenharmony_ci 1680484543d1Sopenharmony_ci```{.cpp} 1681484543d1Sopenharmony_citypedef struct { 1682484543d1Sopenharmony_ci uint32_t len; 1683484543d1Sopenharmony_ci const ffrt_dependence_t* items; 1684484543d1Sopenharmony_ci} ffrt_deps_t; 1685484543d1Sopenharmony_ci``` 1686484543d1Sopenharmony_ci 1687484543d1Sopenharmony_ci#### 参数 1688484543d1Sopenharmony_ci 1689484543d1Sopenharmony_ci`len` 1690484543d1Sopenharmony_ci 1691484543d1Sopenharmony_ci* 所依赖的Signature的个数,取值大于等于0 1692484543d1Sopenharmony_ci 1693484543d1Sopenharmony_ci`item` 1694484543d1Sopenharmony_ci 1695484543d1Sopenharmony_ci* len个Signature的起始地址指针 1696484543d1Sopenharmony_ci 1697484543d1Sopenharmony_ci#### 返回值 1698484543d1Sopenharmony_ci 1699484543d1Sopenharmony_ci* 不涉及 1700484543d1Sopenharmony_ci 1701484543d1Sopenharmony_ci#### 描述 1702484543d1Sopenharmony_ci 1703484543d1Sopenharmony_ci* item为len个Signature的起始指针,该指针可以指向堆空间,也可以指向栈空间,但是要求分配的空间大于等于len * sizeof(void*) 1704484543d1Sopenharmony_ci 1705484543d1Sopenharmony_ci#### 样例 1706484543d1Sopenharmony_ci 1707484543d1Sopenharmony_ci* item指向栈空间的ffrt_deps_t 1708484543d1Sopenharmony_ci 1709484543d1Sopenharmony_ci```{.c} 1710484543d1Sopenharmony_ci#include "ffrt.h" 1711484543d1Sopenharmony_ci 1712484543d1Sopenharmony_ciint main(int narg, char** argv) 1713484543d1Sopenharmony_ci{ 1714484543d1Sopenharmony_ci int x1 = 1; 1715484543d1Sopenharmony_ci int x2 = 2; 1716484543d1Sopenharmony_ci 1717484543d1Sopenharmony_ci const std::vector<ffrt_dependence_t> t_deps = {{ffrt_dependence_data, &x1}, {ffrt_dependence_data, &x2}}; 1718484543d1Sopenharmony_ci ffrt_deps_t deps{static_cast<uint32_t>(t_deps.size()), t_deps.data()}; 1719484543d1Sopenharmony_ci // some code use deps 1720484543d1Sopenharmony_ci return 0; 1721484543d1Sopenharmony_ci} 1722484543d1Sopenharmony_ci``` 1723484543d1Sopenharmony_ci 1724484543d1Sopenharmony_ci* item指向栈空间的ffrt_deps_t 1725484543d1Sopenharmony_ci 1726484543d1Sopenharmony_ci```{.c} 1727484543d1Sopenharmony_ci#include <stdlib.h> 1728484543d1Sopenharmony_ci#include "ffrt.h" 1729484543d1Sopenharmony_ci 1730484543d1Sopenharmony_ciint main(int narg, char** argv) 1731484543d1Sopenharmony_ci{ 1732484543d1Sopenharmony_ci int x1 = 1; 1733484543d1Sopenharmony_ci int x2 = 2; 1734484543d1Sopenharmony_ci 1735484543d1Sopenharmony_ci ffrt_dependence_t* t = new ffrt_dependence_t[2]; 1736484543d1Sopenharmony_ci t[0]= {ffrt_dependence_data, &x1}; 1737484543d1Sopenharmony_ci t[1]= {ffrt_dependence_data, &x2}; 1738484543d1Sopenharmony_ci ffrt_deps_t deps = {2, t}; 1739484543d1Sopenharmony_ci 1740484543d1Sopenharmony_ci // some code use deps 1741484543d1Sopenharmony_ci return 0; 1742484543d1Sopenharmony_ci} 1743484543d1Sopenharmony_ci``` 1744484543d1Sopenharmony_ci 1745484543d1Sopenharmony_ci### ffrt_task_attr_t 1746484543d1Sopenharmony_ci 1747484543d1Sopenharmony_ci<hr/> 1748484543d1Sopenharmony_ci* 定义task 的属性的辅助类,与ffrt_submit 配合使用 1749484543d1Sopenharmony_ci 1750484543d1Sopenharmony_ci#### 声明 1751484543d1Sopenharmony_ci 1752484543d1Sopenharmony_ci```{.c} 1753484543d1Sopenharmony_citypedef enum { 1754484543d1Sopenharmony_ci ffrt_qos_inherent = -1, 1755484543d1Sopenharmony_ci ffrt_qos_background, 1756484543d1Sopenharmony_ci ffrt_qos_utility, 1757484543d1Sopenharmony_ci ffrt_qos_default, 1758484543d1Sopenharmony_ci ffrt_qos_user_initiated, 1759484543d1Sopenharmony_ci} ffrt_qos_t; 1760484543d1Sopenharmony_ci 1761484543d1Sopenharmony_citypedef struct { 1762484543d1Sopenharmony_ci char storage[ffrt_task_attr_storage_size]; 1763484543d1Sopenharmony_ci} ffrt_task_attr_t; 1764484543d1Sopenharmony_citypedef void* ffrt_task_handle_t; 1765484543d1Sopenharmony_ci 1766484543d1Sopenharmony_ciint ffrt_task_attr_init(ffrt_task_attr_t* attr); 1767484543d1Sopenharmony_civoid ffrt_task_attr_destroy(ffrt_task_attr_t* attr); 1768484543d1Sopenharmony_civoid ffrt_task_attr_set_qos(ffrt_task_attr_t* attr, ffrt_qos_t qos); 1769484543d1Sopenharmony_ciffrt_qos_t ffrt_task_attr_get_qos(const ffrt_task_attr_t* attr); 1770484543d1Sopenharmony_civoid ffrt_task_attr_set_name(ffrt_task_attr_t* attr, const char* name); 1771484543d1Sopenharmony_ciconst char* ffrt_task_attr_get_name(const ffrt_task_attr_t* attr); 1772484543d1Sopenharmony_ci``` 1773484543d1Sopenharmony_ci 1774484543d1Sopenharmony_ci#### 参数 1775484543d1Sopenharmony_ci 1776484543d1Sopenharmony_ci`attr` 1777484543d1Sopenharmony_ci 1778484543d1Sopenharmony_ci* 创建的tasks属性的句柄 1779484543d1Sopenharmony_ci 1780484543d1Sopenharmony_ci`qos` 1781484543d1Sopenharmony_ci 1782484543d1Sopenharmony_ci* qos 设定的枚举类型 1783484543d1Sopenharmony_ci* inherent 是一个qos 设定策略,代表即将ffrt_submit 的task 的qos 继承当前task 的qos 1784484543d1Sopenharmony_ci 1785484543d1Sopenharmony_ci#### 返回值 1786484543d1Sopenharmony_ci 1787484543d1Sopenharmony_ci* 不涉及 1788484543d1Sopenharmony_ci 1789484543d1Sopenharmony_ci#### 描述 1790484543d1Sopenharmony_ci* `attr`所传递的内容会在ffrt_submit内部完成取存,ffrt_submit返回后用户即可销毁 1791484543d1Sopenharmony_ci* 约定 1792484543d1Sopenharmony_ci * 在submit 时,如果不通过task_attr 设定qos,那么默认该提交的task的qos 为`ffrt_qos_default` 1793484543d1Sopenharmony_ci * 在submit 时,如果通过task_attr 设定qos 为`ffrt_qos_inherent`,表示将该提交的task 的qos 与当前task 的qos 相同,在FFRT task 外部提交的属性为`ffrt_qos_inherent` 的task,其qos 为`ffrt_qos_default` 1794484543d1Sopenharmony_ci * 其他情况下,该提交的task 的qos 被设定为指定的值 1795484543d1Sopenharmony_ci* ffrt_task_attr_t对象的置空和销毁由用户完成,对同一个ffrt_task_attr_t仅能调用一次`ffrt_task_attr_destroy`,重复对同一个ffrt_task_attr_t调用`ffrt_task_attr_destroy`,其行为是未定义的 1796484543d1Sopenharmony_ci* 在`ffrt_task_attr_destroy`之后再对task_attr进行访问,其行为是未定义的 1797484543d1Sopenharmony_ci 1798484543d1Sopenharmony_ci#### 样例 1799484543d1Sopenharmony_ci 1800484543d1Sopenharmony_ci```{.c} 1801484543d1Sopenharmony_ci#include <stdio.h> 1802484543d1Sopenharmony_ci#include "ffrt.h" 1803484543d1Sopenharmony_ci 1804484543d1Sopenharmony_civoid my_print(void* arg) 1805484543d1Sopenharmony_ci{ 1806484543d1Sopenharmony_ci printf("hello ffrt\n"); 1807484543d1Sopenharmony_ci} 1808484543d1Sopenharmony_ci 1809484543d1Sopenharmony_citypedef struct { 1810484543d1Sopenharmony_ci ffrt_function_header_t header; 1811484543d1Sopenharmony_ci ffrt_function_t func; 1812484543d1Sopenharmony_ci ffrt_function_t after_func; 1813484543d1Sopenharmony_ci void* arg; 1814484543d1Sopenharmony_ci} c_function; 1815484543d1Sopenharmony_ci 1816484543d1Sopenharmony_cistatic void ffrt_exec_function_wrapper(void* t) 1817484543d1Sopenharmony_ci{ 1818484543d1Sopenharmony_ci c_function* f = (c_function*)t; 1819484543d1Sopenharmony_ci if (f->func) { 1820484543d1Sopenharmony_ci f->func(f->arg); 1821484543d1Sopenharmony_ci } 1822484543d1Sopenharmony_ci} 1823484543d1Sopenharmony_ci 1824484543d1Sopenharmony_cistatic void ffrt_destroy_function_wrapper(void* t) 1825484543d1Sopenharmony_ci{ 1826484543d1Sopenharmony_ci c_function* f = (c_function*)t; 1827484543d1Sopenharmony_ci if (f->after_func) { 1828484543d1Sopenharmony_ci f->after_func(f->arg); 1829484543d1Sopenharmony_ci } 1830484543d1Sopenharmony_ci} 1831484543d1Sopenharmony_ci 1832484543d1Sopenharmony_ci#define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1]) 1833484543d1Sopenharmony_cistatic inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func, 1834484543d1Sopenharmony_ci const ffrt_function_t after_func, void* arg) 1835484543d1Sopenharmony_ci{ 1836484543d1Sopenharmony_ci FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size, 1837484543d1Sopenharmony_ci size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size); 1838484543d1Sopenharmony_ci c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); 1839484543d1Sopenharmony_ci f->header.exec = ffrt_exec_function_wrapper; 1840484543d1Sopenharmony_ci f->header.destroy = ffrt_destroy_function_wrapper; 1841484543d1Sopenharmony_ci f->func = func; 1842484543d1Sopenharmony_ci f->after_func = after_func; 1843484543d1Sopenharmony_ci f->arg = arg; 1844484543d1Sopenharmony_ci return (ffrt_function_header_t*)f; 1845484543d1Sopenharmony_ci} 1846484543d1Sopenharmony_ci 1847484543d1Sopenharmony_cistatic inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func, 1848484543d1Sopenharmony_ci void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr) 1849484543d1Sopenharmony_ci{ 1850484543d1Sopenharmony_ci ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr); 1851484543d1Sopenharmony_ci} 1852484543d1Sopenharmony_ci 1853484543d1Sopenharmony_ciint main(int narg, char** argv) 1854484543d1Sopenharmony_ci{ 1855484543d1Sopenharmony_ci ffrt_task_attr_t attr; 1856484543d1Sopenharmony_ci ffrt_task_attr_init(&attr); 1857484543d1Sopenharmony_ci ffrt_task_attr_set_qos(&attr, ffrt_qos_background); 1858484543d1Sopenharmony_ci ffrt_submit_c(my_print, NULL, NULL, NULL, NULL, &attr); 1859484543d1Sopenharmony_ci ffrt_task_attr_destroy(&attr); 1860484543d1Sopenharmony_ci ffrt_wait(); 1861484543d1Sopenharmony_ci return 0; 1862484543d1Sopenharmony_ci} 1863484543d1Sopenharmony_ci``` 1864484543d1Sopenharmony_ci 1865484543d1Sopenharmony_ci* 提交一个qos 级别为background 的任务 1866484543d1Sopenharmony_ci 1867484543d1Sopenharmony_ci 1868484543d1Sopenharmony_ci 1869484543d1Sopenharmony_ci### ffrt_submit_h 1870484543d1Sopenharmony_ci 1871484543d1Sopenharmony_ci<hr/> 1872484543d1Sopenharmony_ci 1873484543d1Sopenharmony_ci* 向调度器提交一个task,与ffrt_submit 的差别在于返回task 的句柄,该句柄可以用于建立task 之间的依赖,或用于在wait 语句中实现同步 1874484543d1Sopenharmony_ci 1875484543d1Sopenharmony_ci#### 声明 1876484543d1Sopenharmony_ci 1877484543d1Sopenharmony_ci```{.cpp} 1878484543d1Sopenharmony_citypedef void* ffrt_task_handle_t; 1879484543d1Sopenharmony_ci 1880484543d1Sopenharmony_ciffrt_task_handle_t ffrt_submit_h(ffrt_function_t func, void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr); 1881484543d1Sopenharmony_civoid ffrt_task_handle_destroy(ffrt_task_handle_t handle); 1882484543d1Sopenharmony_ci``` 1883484543d1Sopenharmony_ci 1884484543d1Sopenharmony_ci#### 参数 1885484543d1Sopenharmony_ci 1886484543d1Sopenharmony_ci`func` 1887484543d1Sopenharmony_ci 1888484543d1Sopenharmony_ci* 同ffrt_submit,详见[ffrt_submit](#ffrt_submit) 定义 1889484543d1Sopenharmony_ci 1890484543d1Sopenharmony_ci`in_deps` 1891484543d1Sopenharmony_ci 1892484543d1Sopenharmony_ci* 同ffrt_submit,详见[ffrt_submit](#ffrt_submit) 定义 1893484543d1Sopenharmony_ci 1894484543d1Sopenharmony_ci`out_deps` 1895484543d1Sopenharmony_ci 1896484543d1Sopenharmony_ci* 同ffrt_submit,详见[ffrt_submit](#ffrt_submit) 定义 1897484543d1Sopenharmony_ci 1898484543d1Sopenharmony_ci`attr` 1899484543d1Sopenharmony_ci 1900484543d1Sopenharmony_ci* 同ffrt_submit,详见[ffrt_submit](#ffrt_submit) 定义 1901484543d1Sopenharmony_ci 1902484543d1Sopenharmony_ci#### 返回值 1903484543d1Sopenharmony_ci 1904484543d1Sopenharmony_ci* task 的句柄,该句柄可以用于建立task 之间的依赖,或用于在wait 语句中实现同步 1905484543d1Sopenharmony_ci 1906484543d1Sopenharmony_ci#### 描述 1907484543d1Sopenharmony_ci 1908484543d1Sopenharmony_ci* C API中的ffrt_task_handle_t的使用与C++ API中的ffrt::task_handle相同 1909484543d1Sopenharmony_ci* **差异在于:C API中的ffrt_task_handle_t需要用户调用`ffrt_task_handle_destroy`显式销毁,而C++ API无需该操作** 1910484543d1Sopenharmony_ci* C API中的task_handle_t对象的置空和销毁由用户完成,对同一个ffrt_task_handle_t仅能调用一次`ffrt_task_handle_destroy`,重复对同一个ffrt_task_handle_t调用`ffrt_task_handle_destroy`,其行为是未定义的 1911484543d1Sopenharmony_ci* 在`ffrt_task_handle_destroy`之后再对ffrt_task_handle_t进行访问,其行为是未定义的 1912484543d1Sopenharmony_ci 1913484543d1Sopenharmony_ci#### 样例 1914484543d1Sopenharmony_ci 1915484543d1Sopenharmony_ci```{.c} 1916484543d1Sopenharmony_ci#include <stdio.h> 1917484543d1Sopenharmony_ci#include "ffrt.h" 1918484543d1Sopenharmony_ci 1919484543d1Sopenharmony_civoid func0(void* arg) 1920484543d1Sopenharmony_ci{ 1921484543d1Sopenharmony_ci printf("hello "); 1922484543d1Sopenharmony_ci} 1923484543d1Sopenharmony_ci 1924484543d1Sopenharmony_civoid func1(void* arg) 1925484543d1Sopenharmony_ci{ 1926484543d1Sopenharmony_ci (*(int*)arg)++; 1927484543d1Sopenharmony_ci} 1928484543d1Sopenharmony_ci 1929484543d1Sopenharmony_civoid func2(void* arg) 1930484543d1Sopenharmony_ci{ 1931484543d1Sopenharmony_ci printf("world, x = %d\n", *(int*)arg); 1932484543d1Sopenharmony_ci} 1933484543d1Sopenharmony_ci 1934484543d1Sopenharmony_civoid func3(void* arg) 1935484543d1Sopenharmony_ci{ 1936484543d1Sopenharmony_ci printf("handle wait"); 1937484543d1Sopenharmony_ci (*(int*)arg)++; 1938484543d1Sopenharmony_ci} 1939484543d1Sopenharmony_ci 1940484543d1Sopenharmony_citypedef struct { 1941484543d1Sopenharmony_ci ffrt_function_header_t header; 1942484543d1Sopenharmony_ci ffrt_function_t func; 1943484543d1Sopenharmony_ci ffrt_function_t after_func; 1944484543d1Sopenharmony_ci void* arg; 1945484543d1Sopenharmony_ci} c_function; 1946484543d1Sopenharmony_ci 1947484543d1Sopenharmony_cistatic void ffrt_exec_function_wrapper(void* t) 1948484543d1Sopenharmony_ci{ 1949484543d1Sopenharmony_ci c_function* f = (c_function*)t; 1950484543d1Sopenharmony_ci if (f->func) { 1951484543d1Sopenharmony_ci f->func(f->arg); 1952484543d1Sopenharmony_ci } 1953484543d1Sopenharmony_ci} 1954484543d1Sopenharmony_ci 1955484543d1Sopenharmony_cistatic void ffrt_destroy_function_wrapper(void* t) 1956484543d1Sopenharmony_ci{ 1957484543d1Sopenharmony_ci c_function* f = (c_function*)t; 1958484543d1Sopenharmony_ci if (f->after_func) { 1959484543d1Sopenharmony_ci f->after_func(f->arg); 1960484543d1Sopenharmony_ci } 1961484543d1Sopenharmony_ci} 1962484543d1Sopenharmony_ci 1963484543d1Sopenharmony_ci#define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1]) 1964484543d1Sopenharmony_cistatic inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func, 1965484543d1Sopenharmony_ci const ffrt_function_t after_func, void* arg) 1966484543d1Sopenharmony_ci{ 1967484543d1Sopenharmony_ci FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size, 1968484543d1Sopenharmony_ci size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size); 1969484543d1Sopenharmony_ci c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); 1970484543d1Sopenharmony_ci f->header.exec = ffrt_exec_function_wrapper; 1971484543d1Sopenharmony_ci f->header.destroy = ffrt_destroy_function_wrapper; 1972484543d1Sopenharmony_ci f->func = func; 1973484543d1Sopenharmony_ci f->after_func = after_func; 1974484543d1Sopenharmony_ci f->arg = arg; 1975484543d1Sopenharmony_ci return (ffrt_function_header_t*)f; 1976484543d1Sopenharmony_ci} 1977484543d1Sopenharmony_ci 1978484543d1Sopenharmony_cistatic inline ffrt_task_handle_t ffrt_submit_h_c(ffrt_function_t func, const ffrt_function_t after_func, 1979484543d1Sopenharmony_ci void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr) 1980484543d1Sopenharmony_ci{ 1981484543d1Sopenharmony_ci return ffrt_submit_h_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr); 1982484543d1Sopenharmony_ci} 1983484543d1Sopenharmony_ci 1984484543d1Sopenharmony_cistatic inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func, 1985484543d1Sopenharmony_ci void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr) 1986484543d1Sopenharmony_ci{ 1987484543d1Sopenharmony_ci ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr); 1988484543d1Sopenharmony_ci} 1989484543d1Sopenharmony_ci 1990484543d1Sopenharmony_ciint main(int narg, char** argv) 1991484543d1Sopenharmony_ci{ 1992484543d1Sopenharmony_ci // handle work with submit 1993484543d1Sopenharmony_ci ffrt_task_handle_t h = ffrt_submit_h_c(func0, NULL, NULL, NULL, NULL, NULL); // not need some data in this task 1994484543d1Sopenharmony_ci int x = 1; 1995484543d1Sopenharmony_ci const std::vector<ffrt_dependence_t> d1_deps = {{ffrt_dependence_data, &x}}; 1996484543d1Sopenharmony_ci ffrt_deps_t d1{static_cast<uint32_t>(d1_deps.size()), d1_deps.data()}; 1997484543d1Sopenharmony_ci const std::vector<ffrt_dependence_t> d2_deps = {{ffrt_dependence_data, &x}, {ffrt_dependence_data, h}}; 1998484543d1Sopenharmony_ci ffrt_deps_t d2{static_cast<uint32_t>(d2_deps.size()), d2_deps.data()}; 1999484543d1Sopenharmony_ci ffrt_submit_c(func1, NULL, &x, NULL, &d1, NULL); 2000484543d1Sopenharmony_ci ffrt_submit_c(func2, NULL, &x, &d2, NULL, NULL); // this task depend x and h 2001484543d1Sopenharmony_ci ffrt_task_handle_destroy(h); 2002484543d1Sopenharmony_ci 2003484543d1Sopenharmony_ci // handle work with wait 2004484543d1Sopenharmony_ci ffrt_task_handle_t h2 = ffrt_submit_h_c(func3, NULL, &x, NULL, NULL, NULL); 2005484543d1Sopenharmony_ci const std::vector<ffrt_dependence_t> d3_deps = {{ffrt_dependence_data, h2}}; 2006484543d1Sopenharmony_ci ffrt_deps_t d3{static_cast<uint32_t>(d3_deps.size()), d3_deps.data()}; 2007484543d1Sopenharmony_ci ffrt_wait_deps(&d3); 2008484543d1Sopenharmony_ci ffrt_task_handle_destroy(h2); 2009484543d1Sopenharmony_ci printf("x = %d", x); 2010484543d1Sopenharmony_ci ffrt_wait(); 2011484543d1Sopenharmony_ci return 0; 2012484543d1Sopenharmony_ci} 2013484543d1Sopenharmony_ci``` 2014484543d1Sopenharmony_ci 2015484543d1Sopenharmony_ci* 预期的输出为 2016484543d1Sopenharmony_ci 2017484543d1Sopenharmony_ci``` 2018484543d1Sopenharmony_cihello world, x = 2 2019484543d1Sopenharmony_cihandle wait 2020484543d1Sopenharmony_cix = 3 2021484543d1Sopenharmony_ci``` 2022484543d1Sopenharmony_ci 2023484543d1Sopenharmony_ci 2024484543d1Sopenharmony_ci 2025484543d1Sopenharmony_ci### ffrt_this_task_get_id 2026484543d1Sopenharmony_ci 2027484543d1Sopenharmony_ci<hr/> 2028484543d1Sopenharmony_ci 2029484543d1Sopenharmony_ci* 返回当前task的id标识,更多使用用于维测(原因是task name可能重名) 2030484543d1Sopenharmony_ci 2031484543d1Sopenharmony_ci#### 声明 2032484543d1Sopenharmony_ci 2033484543d1Sopenharmony_ci```{.c} 2034484543d1Sopenharmony_ciuint64_t ffrt_this_task_get_id(); 2035484543d1Sopenharmony_ci``` 2036484543d1Sopenharmony_ci 2037484543d1Sopenharmony_ci#### 参数 2038484543d1Sopenharmony_ci 2039484543d1Sopenharmony_ci* 不涉及 2040484543d1Sopenharmony_ci 2041484543d1Sopenharmony_ci#### 返回值 2042484543d1Sopenharmony_ci 2043484543d1Sopenharmony_ci* 当前task的id 2044484543d1Sopenharmony_ci 2045484543d1Sopenharmony_ci#### 描述 2046484543d1Sopenharmony_ci 2047484543d1Sopenharmony_ci* 该接口在task内部调用将返回当前task的id标识,在task外部调用将返回0 2048484543d1Sopenharmony_ci* 可以基于该接口在task外部调用返回0的特性来区分函数是运行在FFRT 工作线程上还是非FFRT工作线程上 2049484543d1Sopenharmony_ci* task id为从1开始编码,每提交一个task便增加1,被设计成64bit,即便是每秒百万次提交,也需要292471.2年才会发生翻转 2050484543d1Sopenharmony_ci 2051484543d1Sopenharmony_ci#### 样例 2052484543d1Sopenharmony_ci 2053484543d1Sopenharmony_ci* 忽略 2054484543d1Sopenharmony_ci 2055484543d1Sopenharmony_ci 2056484543d1Sopenharmony_ci 2057484543d1Sopenharmony_ci### ffrt_this_task_update_qos 2058484543d1Sopenharmony_ci 2059484543d1Sopenharmony_ci<hr/> 2060484543d1Sopenharmony_ci 2061484543d1Sopenharmony_ci* 更新当前正在执行的task的优先级 2062484543d1Sopenharmony_ci 2063484543d1Sopenharmony_ci#### 声明 2064484543d1Sopenharmony_ci 2065484543d1Sopenharmony_ci```{.cpp} 2066484543d1Sopenharmony_ciint ffrt_this_task_update_qos(ffrt_qos_t qos); 2067484543d1Sopenharmony_ci``` 2068484543d1Sopenharmony_ci 2069484543d1Sopenharmony_ci#### 参数 2070484543d1Sopenharmony_ci 2071484543d1Sopenharmony_ci* `qos` 新的优先级 2072484543d1Sopenharmony_ci 2073484543d1Sopenharmony_ci#### 返回值 2074484543d1Sopenharmony_ci 2075484543d1Sopenharmony_ci* 0表示成功,非0表示失败 2076484543d1Sopenharmony_ci 2077484543d1Sopenharmony_ci#### 描述 2078484543d1Sopenharmony_ci 2079484543d1Sopenharmony_ci* 该接口对当前task的qos调整会立即生效 2080484543d1Sopenharmony_ci* 如果新设定的qos与当前的qos不一致,则会block当前task的执行,再按照新的qos恢复执行 2081484543d1Sopenharmony_ci* 如果新设定的qos与当前的qos一致,则接口会立即返回0,不做任何处理 2082484543d1Sopenharmony_ci* **如果在非task内部调用该接口,则返回非0值,用户可以选择忽略或其他处理** 2083484543d1Sopenharmony_ci 2084484543d1Sopenharmony_ci#### 样例 2085484543d1Sopenharmony_ci 2086484543d1Sopenharmony_ci* 忽略 2087484543d1Sopenharmony_ci 2088484543d1Sopenharmony_ci## 串行队列 2089484543d1Sopenharmony_ci<hr /> 2090484543d1Sopenharmony_ci 2091484543d1Sopenharmony_ci基本功能与使用约束见 C++ API 中的串行队列部分 2092484543d1Sopenharmony_ci 2093484543d1Sopenharmony_ci### ffrt_queue_t 2094484543d1Sopenharmony_ci<hr/> 2095484543d1Sopenharmony_ci 2096484543d1Sopenharmony_ci#### 描述 2097484543d1Sopenharmony_ciFFRT串行队列 C API,提供提交任务、取消任务、等待任务执行完成等功能 2098484543d1Sopenharmony_ci 2099484543d1Sopenharmony_ci#### 声明 2100484543d1Sopenharmony_ci 2101484543d1Sopenharmony_ci```{.cpp} 2102484543d1Sopenharmony_citypedef enum { ffrt_queue_serial, ffrt_queue_max } ffrt_queue_type_t; 2103484543d1Sopenharmony_citypedef void* ffrt_queue_t; 2104484543d1Sopenharmony_ci 2105484543d1Sopenharmony_ciffrt_queue_t ffrt_queue_create(ffrt_queue_type_t type, const char* name, const ffrt_queue_attr_t* attr); 2106484543d1Sopenharmony_civoid ffrt_queue_destroy(ffrt_queue_t queue); 2107484543d1Sopenharmony_ci 2108484543d1Sopenharmony_civoid ffrt_queue_submit(ffrt_queue_t queue, ffrt_function_header_t* f, const ffrt_task_attr_t* attr); 2109484543d1Sopenharmony_ciffrt_task_handle_t ffrt_queue_submit_h( 2110484543d1Sopenharmony_ci ffrt_queue_t queue, ffrt_function_header_t* f, const ffrt_task_attr_t* attr); 2111484543d1Sopenharmony_ci 2112484543d1Sopenharmony_civoid ffrt_queue_wait(ffrt_task_handle_t handle); 2113484543d1Sopenharmony_ci 2114484543d1Sopenharmony_ciint ffrt_queue_cancel(ffrt_task_handle_t handle); 2115484543d1Sopenharmony_ci``` 2116484543d1Sopenharmony_ci 2117484543d1Sopenharmony_ci#### 方法 2118484543d1Sopenharmony_ci 2119484543d1Sopenharmony_ci##### ffrt_queue_create 2120484543d1Sopenharmony_ci 2121484543d1Sopenharmony_ci```{.cpp} 2122484543d1Sopenharmony_ciffrt_queue_t ffrt_queue_create(ffrt_queue_type_t type, const char* name, const ffrt_queue_attr_t* attr); 2123484543d1Sopenharmony_ci``` 2124484543d1Sopenharmony_ci 2125484543d1Sopenharmony_ci* 描述:创建串行队列 2126484543d1Sopenharmony_ci 2127484543d1Sopenharmony_ci* 参数: 2128484543d1Sopenharmony_ci 2129484543d1Sopenharmony_ci `type`:用于描述创建的队列类型,串行队列对应 `type` 为 `ffrt_queue_serial` 2130484543d1Sopenharmony_ci 2131484543d1Sopenharmony_ci `name`:用于描述创建的队列名称 2132484543d1Sopenharmony_ci 2133484543d1Sopenharmony_ci `attr`:所创建的queue属性,若未设定则会使用默认值 2134484543d1Sopenharmony_ci 2135484543d1Sopenharmony_ci* 返回值:如果成功创建了队列,则返回一个非空的队列句柄;否则返回空指针 2136484543d1Sopenharmony_ci 2137484543d1Sopenharmony_ci##### ffrt_queue_destroy 2138484543d1Sopenharmony_ci 2139484543d1Sopenharmony_ci```{.cpp} 2140484543d1Sopenharmony_civoid ffrt_queue_destroy(ffrt_queue_t queue); 2141484543d1Sopenharmony_ci``` 2142484543d1Sopenharmony_ci 2143484543d1Sopenharmony_ci* 描述:销毁串行队列 2144484543d1Sopenharmony_ci 2145484543d1Sopenharmony_ci* 参数: 2146484543d1Sopenharmony_ci 2147484543d1Sopenharmony_ci `queue`:想要销毁的队列的句柄 2148484543d1Sopenharmony_ci 2149484543d1Sopenharmony_ci* 返回值:不涉及 2150484543d1Sopenharmony_ci 2151484543d1Sopenharmony_ci##### ffrt_queue_submit 2152484543d1Sopenharmony_ci 2153484543d1Sopenharmony_ci```{.cpp} 2154484543d1Sopenharmony_civoid ffrt_queue_submit(ffrt_queue_t queue, ffrt_function_header_t* f, const ffrt_task_attr_t* attr); 2155484543d1Sopenharmony_ci``` 2156484543d1Sopenharmony_ci 2157484543d1Sopenharmony_ci* 描述:提交一个任务到队列中调度执行 2158484543d1Sopenharmony_ci 2159484543d1Sopenharmony_ci* 参数: 2160484543d1Sopenharmony_ci 2161484543d1Sopenharmony_ci `queue`:串行队列的句柄 2162484543d1Sopenharmony_ci 2163484543d1Sopenharmony_ci `f`:任务执行指针 2164484543d1Sopenharmony_ci 2165484543d1Sopenharmony_ci `attr`:所创建的queue属性 2166484543d1Sopenharmony_ci 2167484543d1Sopenharmony_ci* 返回值:不涉及 2168484543d1Sopenharmony_ci 2169484543d1Sopenharmony_ci##### ffrt_queue_submit_h 2170484543d1Sopenharmony_ci 2171484543d1Sopenharmony_ci```{.cpp} 2172484543d1Sopenharmony_ciffrt_task_handle_t ffrt_queue_submit_h( 2173484543d1Sopenharmony_ci ffrt_queue_t queue, ffrt_function_header_t* f, const ffrt_task_attr_t* attr); 2174484543d1Sopenharmony_ci``` 2175484543d1Sopenharmony_ci 2176484543d1Sopenharmony_ci* 描述:提交一个任务到队列中调度执行,并返回任务句柄 2177484543d1Sopenharmony_ci 2178484543d1Sopenharmony_ci* 参数: 2179484543d1Sopenharmony_ci 2180484543d1Sopenharmony_ci `queue`:串行队列的句柄 2181484543d1Sopenharmony_ci 2182484543d1Sopenharmony_ci `f`:任务执行指针 2183484543d1Sopenharmony_ci 2184484543d1Sopenharmony_ci `attr`:所创建的queue属性 2185484543d1Sopenharmony_ci 2186484543d1Sopenharmony_ci* 返回值:如果任务被提交,则返回一个非空的任务句柄;否则返回空指针 2187484543d1Sopenharmony_ci 2188484543d1Sopenharmony_ci##### ffrt_queue_wait 2189484543d1Sopenharmony_ci 2190484543d1Sopenharmony_ci```{.cpp} 2191484543d1Sopenharmony_civoid ffrt_queue_wait(ffrt_task_handle_t handle); 2192484543d1Sopenharmony_ci``` 2193484543d1Sopenharmony_ci 2194484543d1Sopenharmony_ci* 描述:等待串行队列中一个任务执行完成 2195484543d1Sopenharmony_ci 2196484543d1Sopenharmony_ci* 参数: 2197484543d1Sopenharmony_ci 2198484543d1Sopenharmony_ci `handle`:任务的句柄 2199484543d1Sopenharmony_ci 2200484543d1Sopenharmony_ci* 返回值:不涉及 2201484543d1Sopenharmony_ci 2202484543d1Sopenharmony_ci##### ffrt_queue_cancel 2203484543d1Sopenharmony_ci 2204484543d1Sopenharmony_ci```{.cpp} 2205484543d1Sopenharmony_ciint ffrt_queue_cancel(ffrt_task_handle_t handle); 2206484543d1Sopenharmony_ci``` 2207484543d1Sopenharmony_ci 2208484543d1Sopenharmony_ci* 描述:取消队列中一个任务。必须使用submit_h后拿到的task_handle,否则会报异常;任务开始执行后则无法取消,仅能成功取消未开始执行的任务 2209484543d1Sopenharmony_ci 2210484543d1Sopenharmony_ci* 参数: 2211484543d1Sopenharmony_ci 2212484543d1Sopenharmony_ci `handle`:任务的句柄 2213484543d1Sopenharmony_ci 2214484543d1Sopenharmony_ci* 返回值:若成功返回0,否则返回其他非0值 2215484543d1Sopenharmony_ci 2216484543d1Sopenharmony_ci#### 样例 2217484543d1Sopenharmony_ci 2218484543d1Sopenharmony_ci```{.cpp} 2219484543d1Sopenharmony_ci#include <stdio.h> 2220484543d1Sopenharmony_ci#include "ffrt.h" 2221484543d1Sopenharmony_ci 2222484543d1Sopenharmony_ciusing namespace ffrt; 2223484543d1Sopenharmony_ciusing namespace std; 2224484543d1Sopenharmony_ci 2225484543d1Sopenharmony_ciint main(int narg, char** argv) 2226484543d1Sopenharmony_ci{ 2227484543d1Sopenharmony_ci ffrt_queue_attr_t queue_attr; 2228484543d1Sopenharmony_ci // 1、初始化队列属性,必需 2229484543d1Sopenharmony_ci (void)ffrt_queue_attr_init(&queue_attr); 2230484543d1Sopenharmony_ci 2231484543d1Sopenharmony_ci // 2、创建串行队列,并返回队列句柄queue_handle 2232484543d1Sopenharmony_ci ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_serial, "test_queue", &queue_attr); 2233484543d1Sopenharmony_ci 2234484543d1Sopenharmony_ci int result = 0; 2235484543d1Sopenharmony_ci std::function<void()>&& basicFunc = [&result]() { result += 1; }; 2236484543d1Sopenharmony_ci 2237484543d1Sopenharmony_ci // 3、提交串行任务 2238484543d1Sopenharmony_ci ffrt_queue_submit(queue_handle, create_function_wrapper(basicFunc, ffrt_function_kind_queue), nullptr); 2239484543d1Sopenharmony_ci 2240484543d1Sopenharmony_ci // 4、提交串行任务,并返回任务句柄 2241484543d1Sopenharmony_ci ffrt_task_handle_t t1 = ffrt_queue_submit_h(queue_handle, create_function_wrapper(basicFunc, ffrt_function_kind_queue), nullptr); 2242484543d1Sopenharmony_ci // 5、等待指定任务执行完成 2243484543d1Sopenharmony_ci ffrt_queue_wait(t1); 2244484543d1Sopenharmony_ci 2245484543d1Sopenharmony_ci ffrt_task_handle_t t2 = ffrt_queue_submit_h(queue_handle, create_function_wrapper(basicFunc, ffrt_function_kind_queue), nullptr); 2246484543d1Sopenharmony_ci // 6、取消句柄为t2的任务 2247484543d1Sopenharmony_ci int ret = ffrt_queue_cancel(t2); 2248484543d1Sopenharmony_ci 2249484543d1Sopenharmony_ci // 7、销毁提交给串行队列任务的句柄t1和t2,必需 2250484543d1Sopenharmony_ci ffrt_task_handle_destroy(t1); 2251484543d1Sopenharmony_ci ffrt_task_handle_destroy(t2); 2252484543d1Sopenharmony_ci // 8、销毁队列属性,必需 2253484543d1Sopenharmony_ci ffrt_queue_attr_destroy(&queue_attr); 2254484543d1Sopenharmony_ci // 9、销毁队列句柄,必需 2255484543d1Sopenharmony_ci ffrt_queue_destroy(queue_handle); 2256484543d1Sopenharmony_ci} 2257484543d1Sopenharmony_ci``` 2258484543d1Sopenharmony_ci 2259484543d1Sopenharmony_ci### ffrt_queue_attr_t 2260484543d1Sopenharmony_ci<hr/> 2261484543d1Sopenharmony_ci 2262484543d1Sopenharmony_ci#### 描述 2263484543d1Sopenharmony_ciFFRT串行队列 C API,提供设置与获取串行队列优先级、设置与获取串行队列任务执行超时时间、设置与获取串行队列超时回调函数等功能 2264484543d1Sopenharmony_ci 2265484543d1Sopenharmony_ci#### 声明 2266484543d1Sopenharmony_ci 2267484543d1Sopenharmony_ci```{.cpp} 2268484543d1Sopenharmony_citypedef struct { 2269484543d1Sopenharmony_ci uint32_t storage[(ffrt_queue_attr_storage_size + sizeof(uint32_t) - 1) / sizeof(uint32_t)]; 2270484543d1Sopenharmony_ci} ffrt_queue_attr_t; 2271484543d1Sopenharmony_ci 2272484543d1Sopenharmony_ciint ffrt_queue_attr_init(ffrt_queue_attr_t* attr); 2273484543d1Sopenharmony_civoid ffrt_queue_attr_destroy(ffrt_queue_attr_t* attr); 2274484543d1Sopenharmony_ci 2275484543d1Sopenharmony_civoid ffrt_queue_attr_set_qos(ffrt_queue_attr_t* attr, ffrt_qos_t qos); 2276484543d1Sopenharmony_ciffrt_qos_t ffrt_queue_attr_get_qos(const ffrt_queue_attr_t* attr); 2277484543d1Sopenharmony_ci 2278484543d1Sopenharmony_civoid ffrt_queue_attr_set_timeout(ffrt_queue_attr_t* attr, uint64_t timeout_us); 2279484543d1Sopenharmony_ciuint64_t ffrt_queue_attr_get_timeout(const ffrt_queue_attr_t* attr); 2280484543d1Sopenharmony_ci 2281484543d1Sopenharmony_civoid ffrt_queue_attr_set_callback(ffrt_queue_attr_t* attr, ffrt_function_header_t* f); 2282484543d1Sopenharmony_ciffrt_function_header_t* ffrt_queue_attr_get_callback(const ffrt_queue_attr_t* attr); 2283484543d1Sopenharmony_ci``` 2284484543d1Sopenharmony_ci 2285484543d1Sopenharmony_ci#### 方法 2286484543d1Sopenharmony_ci 2287484543d1Sopenharmony_ci##### ffrt_queue_attr_init 2288484543d1Sopenharmony_ci```{.cpp} 2289484543d1Sopenharmony_ciint ffrt_queue_attr_init(ffrt_queue_attr_t* attr); 2290484543d1Sopenharmony_ci``` 2291484543d1Sopenharmony_ci 2292484543d1Sopenharmony_ci* 描述:初始化串行队列的属性 2293484543d1Sopenharmony_ci 2294484543d1Sopenharmony_ci* 参数: 2295484543d1Sopenharmony_ci 2296484543d1Sopenharmony_ci `attr`:已初始化的串行队列属性 2297484543d1Sopenharmony_ci 2298484543d1Sopenharmony_ci* 返回值:若成功返回0,否则返回-1 2299484543d1Sopenharmony_ci 2300484543d1Sopenharmony_ci##### ffrt_queue_attr_destroy 2301484543d1Sopenharmony_ci```{.cpp} 2302484543d1Sopenharmony_civoid ffrt_queue_attr_destroy(ffrt_queue_attr_t* attr); 2303484543d1Sopenharmony_ci``` 2304484543d1Sopenharmony_ci 2305484543d1Sopenharmony_ci* 描述:销毁串行队列的属性 2306484543d1Sopenharmony_ci 2307484543d1Sopenharmony_ci ffrt_queue_attr_t对象的置空和销毁由用户完成,对同一个ffrt_queue_t仅能调用一次 `ffrt_queue_attr_destroy` ,重复对同一个ffrt_queue_t调用 `ffrt_queue_attr_destroy` ,其行为是未定义的 2308484543d1Sopenharmony_ci 2309484543d1Sopenharmony_ci 在`ffrt_queue_attr_destroy`之后再对ffrt_queue_t进行访问,其行为是未定义的 2310484543d1Sopenharmony_ci 2311484543d1Sopenharmony_ci* 参数: 2312484543d1Sopenharmony_ci 2313484543d1Sopenharmony_ci `attr`:所创建的串行队列属性 2314484543d1Sopenharmony_ci 2315484543d1Sopenharmony_ci* 返回值:不涉及 2316484543d1Sopenharmony_ci 2317484543d1Sopenharmony_ci##### ffrt_queue_attr_set_qos 2318484543d1Sopenharmony_ci```{.cpp} 2319484543d1Sopenharmony_civoid ffrt_queue_attr_set_qos(ffrt_queue_attr_t* attr, ffrt_qos_t qos); 2320484543d1Sopenharmony_ci``` 2321484543d1Sopenharmony_ci 2322484543d1Sopenharmony_ci* 描述:设置串行队列qos属性,默认为default等级 2323484543d1Sopenharmony_ci 2324484543d1Sopenharmony_ci* 参数: 2325484543d1Sopenharmony_ci 2326484543d1Sopenharmony_ci `attr`:所创建的串行队列属性 2327484543d1Sopenharmony_ci 2328484543d1Sopenharmony_ci `qos`:串行队列优先级 2329484543d1Sopenharmony_ci 2330484543d1Sopenharmony_ci* 返回值:不涉及 2331484543d1Sopenharmony_ci 2332484543d1Sopenharmony_ci##### ffrt_queue_attr_get_qos 2333484543d1Sopenharmony_ci```{.cpp} 2334484543d1Sopenharmony_ciffrt_qos_t ffrt_queue_attr_get_qos(const ffrt_queue_attr_t* attr); 2335484543d1Sopenharmony_ci``` 2336484543d1Sopenharmony_ci 2337484543d1Sopenharmony_ci* 描述:获取串行队列qos属性 2338484543d1Sopenharmony_ci 2339484543d1Sopenharmony_ci* 参数: 2340484543d1Sopenharmony_ci 2341484543d1Sopenharmony_ci `attr`:所创建的串行队列属性 2342484543d1Sopenharmony_ci 2343484543d1Sopenharmony_ci* 返回值:所设置的串行队列的qos等级,默认为default等级 2344484543d1Sopenharmony_ci 2345484543d1Sopenharmony_ci##### ffrt_queue_attr_set_timeout 2346484543d1Sopenharmony_ci```{.cpp} 2347484543d1Sopenharmony_civoid ffrt_queue_attr_set_timeout(ffrt_queue_attr_t* attr, uint64_t timeout_us); 2348484543d1Sopenharmony_ci``` 2349484543d1Sopenharmony_ci 2350484543d1Sopenharmony_ci* 描述:设置串行队列任务执行超时时间 2351484543d1Sopenharmony_ci 2352484543d1Sopenharmony_ci* 参数: 2353484543d1Sopenharmony_ci 2354484543d1Sopenharmony_ci `attr`:所创建的串行队列属性 2355484543d1Sopenharmony_ci 2356484543d1Sopenharmony_ci `timeout_us`:串行队列任务执行超时时间,单位为us 2357484543d1Sopenharmony_ci 2358484543d1Sopenharmony_ci* 返回值:不涉及 2359484543d1Sopenharmony_ci 2360484543d1Sopenharmony_ci##### ffrt_queue_attr_get_timeout 2361484543d1Sopenharmony_ci```{.cpp} 2362484543d1Sopenharmony_ciuint64_t ffrt_queue_attr_get_timeout(const ffrt_queue_attr_t* attr); 2363484543d1Sopenharmony_ci``` 2364484543d1Sopenharmony_ci 2365484543d1Sopenharmony_ci* 描述:获取所设置的串行队列任务执行超时时间 2366484543d1Sopenharmony_ci 2367484543d1Sopenharmony_ci* 参数: 2368484543d1Sopenharmony_ci 2369484543d1Sopenharmony_ci `attr`:所创建的串行队列属性 2370484543d1Sopenharmony_ci 2371484543d1Sopenharmony_ci* 返回值:串行队列任务执行超时时间,单位为us 2372484543d1Sopenharmony_ci 2373484543d1Sopenharmony_ci##### ffrt_queue_attr_set_callback 2374484543d1Sopenharmony_ci```{.cpp} 2375484543d1Sopenharmony_civoid ffrt_queue_attr_set_callback(ffrt_queue_attr_t* attr, ffrt_function_header_t* f); 2376484543d1Sopenharmony_ci``` 2377484543d1Sopenharmony_ci 2378484543d1Sopenharmony_ci* 描述:设置串行队列超时回调函数 2379484543d1Sopenharmony_ci 2380484543d1Sopenharmony_ci* 参数: 2381484543d1Sopenharmony_ci 2382484543d1Sopenharmony_ci `attr`:所创建的串行队列属性 2383484543d1Sopenharmony_ci 2384484543d1Sopenharmony_ci `f`:串行队列超时回调函数 2385484543d1Sopenharmony_ci 2386484543d1Sopenharmony_ci* 返回值:不涉及 2387484543d1Sopenharmony_ci 2388484543d1Sopenharmony_ci##### ffrt_queue_attr_get_callback 2389484543d1Sopenharmony_ci```{.cpp} 2390484543d1Sopenharmony_ciffrt_function_header_t* ffrt_queue_attr_get_callback(const ffrt_queue_attr_t* attr); 2391484543d1Sopenharmony_ci``` 2392484543d1Sopenharmony_ci 2393484543d1Sopenharmony_ci* 描述:获取串行队列超时回调函数 2394484543d1Sopenharmony_ci 2395484543d1Sopenharmony_ci* 参数: 2396484543d1Sopenharmony_ci 2397484543d1Sopenharmony_ci `attr`:所创建的串行队列属性 2398484543d1Sopenharmony_ci 2399484543d1Sopenharmony_ci* 返回值:串行队列任务超时回调函数 2400484543d1Sopenharmony_ci 2401484543d1Sopenharmony_ci#### 样例 2402484543d1Sopenharmony_ci```{.cpp} 2403484543d1Sopenharmony_ci#include <stdio.h> 2404484543d1Sopenharmony_ci#include "ffrt.h" 2405484543d1Sopenharmony_ci 2406484543d1Sopenharmony_ciusing namespace ffrt; 2407484543d1Sopenharmony_ciusing namespace std; 2408484543d1Sopenharmony_ci 2409484543d1Sopenharmony_ciint main(int narg, char** argv) 2410484543d1Sopenharmony_ci{ 2411484543d1Sopenharmony_ci ffrt_queue_attr_t queue_attr; 2412484543d1Sopenharmony_ci // 1、初始化串行队列属性,必需 2413484543d1Sopenharmony_ci int result = ffrt_queue_attr_init(&queue_attr); 2414484543d1Sopenharmony_ci 2415484543d1Sopenharmony_ci int x = 0; 2416484543d1Sopenharmony_ci std::function<void()>&& basicFunc = [&x]() { x += 1; }; 2417484543d1Sopenharmony_ci 2418484543d1Sopenharmony_ci // 2、可设置队列优先级,默认为default等级 2419484543d1Sopenharmony_ci ffrt_queue_attr_set_qos(&queue_attr, static_cast<int>(ffrt_qos_utility)); 2420484543d1Sopenharmony_ci int qos = ffrt_queue_attr_get_qos(&queue_attr); 2421484543d1Sopenharmony_ci 2422484543d1Sopenharmony_ci // 3、可通过设置timeout打开队列任务超时监测,默认不设置(关闭) 2423484543d1Sopenharmony_ci ffrt_queue_attr_set_timeout(&queue_attr, 10000); 2424484543d1Sopenharmony_ci uint64_t time = ffrt_queue_attr_get_timeout(&queue_attr); 2425484543d1Sopenharmony_ci 2426484543d1Sopenharmony_ci // 4、超时会打印Error日志并执行用户设置的callback(可选) 2427484543d1Sopenharmony_ci ffrt_queue_attr_set_callback(&queue_attr, ffrt::create_function_wrapper(basicFunc, ffrt_function_kind_queue)); 2428484543d1Sopenharmony_ci ffrt_function_header_t* func = ffrt_queue_attr_get_callback(&queue_attr); 2429484543d1Sopenharmony_ci 2430484543d1Sopenharmony_ci // 5、销毁串行队列属性,必需 2431484543d1Sopenharmony_ci ffrt_queue_attr_destroy(&queue_attr); 2432484543d1Sopenharmony_ci} 2433484543d1Sopenharmony_ci``` 2434484543d1Sopenharmony_ci 2435484543d1Sopenharmony_ci### ffrt_loop_t 2436484543d1Sopenharmony_ci<hr/> 2437484543d1Sopenharmony_ci 2438484543d1Sopenharmony_ci* 为满足美团生态对接的要求,扩展了FFRT基本功能。新增了支持定时器、线程间通信、N并发队列、并提供Loop机制(在用户创建的线程内循环执行用户提交的任务)等功能 2439484543d1Sopenharmony_ci 2440484543d1Sopenharmony_ci#### 声明 2441484543d1Sopenharmony_ci 2442484543d1Sopenharmony_ci```{.c} 2443484543d1Sopenharmony_citypedef void* ffrt_loop_t 2444484543d1Sopenharmony_ci 2445484543d1Sopenharmony_ciffrt_loop_t ffrt_loop_create(ffrt_queue_t queue); 2446484543d1Sopenharmony_ciint ffrt_loop_destroy(ffrt_loop_t loop); 2447484543d1Sopenharmony_ciint ffrt_loop_run(ffrt_loop_t loop); 2448484543d1Sopenharmony_civoid ffrt_loop_stop(ffrt_loop_t loop); 2449484543d1Sopenharmony_ciint ffrt_loop_epoll_ctl(ffrt_loop_t loop, int op, int fd, uint32_t events, void *data, ffrt_poller_cb cb); 2450484543d1Sopenharmony_ciffrt_timer_t ffrt_loop_timer_start( 2451484543d1Sopenharmony_ci ffrt_loop_t loop, uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat); 2452484543d1Sopenharmony_ciint ffrt_loop_timer_stop(ffrt_loop_t loop, ffrt_timer_t handle); 2453484543d1Sopenharmony_ci``` 2454484543d1Sopenharmony_ci 2455484543d1Sopenharmony_ci#### 参数 2456484543d1Sopenharmony_ci 2457484543d1Sopenharmony_ci`queue`: 表示一个队列句柄 2458484543d1Sopenharmony_ci 2459484543d1Sopenharmony_ci`loop`: 表示一个loop句柄 2460484543d1Sopenharmony_ci 2461484543d1Sopenharmony_ci`op`: 表示目标文件描述符的操作 2462484543d1Sopenharmony_ci 2463484543d1Sopenharmony_ci`fd`: 表示执行操作的目标文件描述符 2464484543d1Sopenharmony_ci 2465484543d1Sopenharmony_ci`events`: 表示跟目标文件描述符相关联的事件类型 2466484543d1Sopenharmony_ci 2467484543d1Sopenharmony_ci`data`: 表示回调函数中被用户使用的数据 2468484543d1Sopenharmony_ci 2469484543d1Sopenharmony_ci`cb`: 表示一个回调函数,当目标文件描述符被获取时执行 2470484543d1Sopenharmony_ci 2471484543d1Sopenharmony_ci`timeout`: 表示函数调用中阻塞时间的上限,单位为毫秒 2472484543d1Sopenharmony_ci 2473484543d1Sopenharmony_ci`repeat`: 表示是否重复这个定时器 2474484543d1Sopenharmony_ci 2475484543d1Sopenharmony_ci#### 返回值 2476484543d1Sopenharmony_ci* ffrt_loop_create接口:当loop成功创建后返回一个非空的loop句柄,否则返回一个空指针 2477484543d1Sopenharmony_ci* ffrt_loop_destroy接口:当loop成功被销毁返回0,否则返回-1 2478484543d1Sopenharmony_ci* ffrt_loop_run接口:当loop成功运行返回0,否则返回-1 2479484543d1Sopenharmony_ci* ffrt_loop_epoll_ctl接口:如果成功在loop里添加/删除fd,返回0,否则返回-1 2480484543d1Sopenharmony_ci* ffrt_loop_timer_start接口:在loop里开启一个定时器,返回该定时器的句柄 2481484543d1Sopenharmony_ci* ffrt_loop_timer_stop接口:在loop里停止一个目标定时器,停止成功:返回0,如果停止失败:返回-1 2482484543d1Sopenharmony_ci 2483484543d1Sopenharmony_ci#### 描述 2484484543d1Sopenharmony_ci* FFRT提供loop的编程机制,loop支持任务提交,提交的任务直接在用户线程中执行 2485484543d1Sopenharmony_ci* FFRT loop基于FFRT queue构建任务队列,基于FFRT Poller实现事件监听,loop内部自动遍历任务队列执行任务,当没有任务时进入Poller的epoll_wait监听事件,线程进入休眠状态 2486484543d1Sopenharmony_ci* 支持用户通过接口创建loop,返回给用户loop句柄,创建loop时需要传入一个已创建的FFRT queue作为该loop的任务队列 2487484543d1Sopenharmony_ci* loop创建后支持向queue中提交任务,并支持在loop run的过程中向queue中提交任务 2488484543d1Sopenharmony_ci* 提供ffrt_loop_create接口创建loop,用户传入queue,创建时将loop和queue相互绑定 2489484543d1Sopenharmony_ci* **注意:这里对传入的queue要求从未提交过任务,即:不支持queue的任务既在worker上执行又在用户线程上执行** 2490484543d1Sopenharmony_ci* **注意:传入的queue类型仅支持N并发队列,不支持其它类型的队列** 2491484543d1Sopenharmony_ci* 提供ffrt_loop_run接口,运行loop,loop启动后遍历queue中的任务执行 2492484543d1Sopenharmony_ci* 提供ffrt_loop_stop接口,停止运行loop,停止后loop不能再运行 2493484543d1Sopenharmony_ci* 提供ffrt_loop_destroy接口,将loop销毁,同时解除queue和loop间的绑定关系,意味着loop销毁后不能再向该queue提交任务 2494484543d1Sopenharmony_ci* 提供ffrt_loop_epoll_ctl接口,使用户可以监听/删除一个fd,当fd被调用时,执行用户的回调函数 2495484543d1Sopenharmony_ci* 提供ffrt_loop_timer_start接口,在loop中开始一个定时器 2496484543d1Sopenharmony_ci* 提供ffrt_loop_timer_stop接口,在loop中停止一个目标定时器 2497484543d1Sopenharmony_ci 2498484543d1Sopenharmony_ci#### 样例 2499484543d1Sopenharmony_ci```{.c} 2500484543d1Sopenharmony_ci#include <stdio.h> 2501484543d1Sopenharmony_ci#include "ffrt.h" 2502484543d1Sopenharmony_ci 2503484543d1Sopenharmony_ciusing namespace ffrt; 2504484543d1Sopenharmony_ciusing namespace std; 2505484543d1Sopenharmony_ci 2506484543d1Sopenharmony_ciint main(int narg, char** argv) 2507484543d1Sopenharmony_ci{ 2508484543d1Sopenharmony_ci // step1: 创建queue 2509484543d1Sopenharmony_ci ffrt_queue_attr_t queue_attr; 2510484543d1Sopenharmony_ci (void)ffrt_queue_attr_init(&queue_attr); 2511484543d1Sopenharmony_ci ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_concurrent, "test_queue", &queue_attr); 2512484543d1Sopenharmony_ci 2513484543d1Sopenharmony_ci // step2: 创建loop 2514484543d1Sopenharmony_ci auto loop = ffrt_loop_create(queue_handle); 2515484543d1Sopenharmony_ci 2516484543d1Sopenharmony_ci // step3: 此时可以向loop提交任务 2517484543d1Sopenharmony_ci int result1 = 0; 2518484543d1Sopenharmony_ci std::function<void()>&& basicFunc1 = [&result1]() { result1 += 10; }; 2519484543d1Sopenharmony_ci ffrt_task_handle_t task1 = ffrt_queue_submit_h(queue_handle, 2520484543d1Sopenharmony_ci create_function_wrapper(basicFunc1, ffrt_function_kind_queue), nullptr); 2521484543d1Sopenharmony_ci 2522484543d1Sopenharmony_ci // step4: 在进程中执行loop run 2523484543d1Sopenharmony_ci pthread_t thread; 2524484543d1Sopenharmony_ci pthread_create(&thread, 0, ThreadFunc, loop); 2525484543d1Sopenharmony_ci 2526484543d1Sopenharmony_ci static int x = 0; 2527484543d1Sopenharmony_ci int* xf = &x; 2528484543d1Sopenharmony_ci void* data = xf; 2529484543d1Sopenharmony_ci uint64_t timeout1 = 20; 2530484543d1Sopenharmony_ci uint64_t timeout2 = 10; 2531484543d1Sopenharmony_ci uint64_t expected = 0xabacadae; 2532484543d1Sopenharmony_ci int testFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); 2533484543d1Sopenharmony_ci 2534484543d1Sopenharmony_ci struct TestData testData {.fd = testFd, .expected = expected}; 2535484543d1Sopenharmony_ci EXPECT_EQ(0, ffrt_loop_timer_start(loop, timeout1, data, cb, false)); 2536484543d1Sopenharmony_ci EXPECT_EQ(1, ffrt_loop_timer_start(loop, timeout2, data, cb, false)); 2537484543d1Sopenharmony_ci 2538484543d1Sopenharmony_ci ffrt_loop_epoll_ctl(loop, EPOLL_CTL_ADD, testFd, EPOLLIN, (void*)(&testData), testCallBack); 2539484543d1Sopenharmony_ci ssize_t n = write(testFd, &expected, sizeof(uint64_t)); 2540484543d1Sopenharmony_ci EXPECT_EQ(n, sizeof(uint64_t)); 2541484543d1Sopenharmony_ci usleep(25000); 2542484543d1Sopenharmony_ci ffrt_loop_epoll_ctl(loop, EPOLL_CTL_DEL, testFd, 0, nullptr, nullptr); 2543484543d1Sopenharmony_ci 2544484543d1Sopenharmony_ci EXPECT_EQ(2, x); 2545484543d1Sopenharmony_ci 2546484543d1Sopenharmony_ci // step5: 继续向loop上提交任务 2547484543d1Sopenharmony_ci int result2 = 0; 2548484543d1Sopenharmony_ci std::function<void()>&& basicFunc2 = [&result2]() { result2 += 20; }; 2549484543d1Sopenharmony_ci ffrt_task_handle_t task2 = ffrt_queue_submit_h(queue_handle, 2550484543d1Sopenharmony_ci create_function_wrapper(basicFunc2, ffrt_function_kind_queue), nullptr); 2551484543d1Sopenharmony_ci 2552484543d1Sopenharmony_ci ffrt_queue_wait(task1); 2553484543d1Sopenharmony_ci ffrt_queue_wait(task2); 2554484543d1Sopenharmony_ci EXPECT_EQ(result1, 10); 2555484543d1Sopenharmony_ci EXPECT_EQ(result2, 20); 2556484543d1Sopenharmony_ci 2557484543d1Sopenharmony_ci // step6: 停止loop 2558484543d1Sopenharmony_ci ffrt_loop_stop(loop); 2559484543d1Sopenharmony_ci pthread_join(thread, nullptr); 2560484543d1Sopenharmony_ci 2561484543d1Sopenharmony_ci // step7: loop销毁 2562484543d1Sopenharmony_ci ffrt_loop_destroy(loop); 2563484543d1Sopenharmony_ci 2564484543d1Sopenharmony_ci // step8: 队列销毁 2565484543d1Sopenharmony_ci ffrt_queue_attr_destroy(&queue_attr); 2566484543d1Sopenharmony_ci ffrt_queue_destroy(queue_handle); 2567484543d1Sopenharmony_ci} 2568484543d1Sopenharmony_ci 2569484543d1Sopenharmony_ci``` 2570484543d1Sopenharmony_ci 2571484543d1Sopenharmony_ci### ffrt_timer_t 2572484543d1Sopenharmony_ci<hr/> 2573484543d1Sopenharmony_ci 2574484543d1Sopenharmony_ci* FFRT timer基于epoll实现定时功能,epoll是一种I/O事件监听、通知机制。在定期执行PollOnce时会根据所设的timeout时间执行其中的epoll_wait阻塞等待注册的事件发生。epoll_wait的参数timeout是函数调用中阻塞时间的上限,单位是ms,若timeout > 0,则在期间有检测到对象变为ready状态或者捕获到信号然后返回,否则直到超时。Timeout = -1则会一直在阻塞。 2575484543d1Sopenharmony_ci 2576484543d1Sopenharmony_ci#### 声明 2577484543d1Sopenharmony_ci```{.c} 2578484543d1Sopenharmony_ciffrt_timer_t ffrt_timer_start(ffrt_qos_t qos, uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat); 2579484543d1Sopenharmony_ciint ffrt_timer_stop(ffrt_qos_t qos, ffrt_timer_t handle); 2580484543d1Sopenharmony_ci``` 2581484543d1Sopenharmony_ci 2582484543d1Sopenharmony_ci#### 参数 2583484543d1Sopenharmony_ci 2584484543d1Sopenharmony_ci`qos` 2585484543d1Sopenharmony_ci 2586484543d1Sopenharmony_ci* 表示运行定时器work的优先级 2587484543d1Sopenharmony_ci 2588484543d1Sopenharmony_ci`timeout` 2589484543d1Sopenharmony_ci 2590484543d1Sopenharmony_ci* 表示函数调用中阻塞时长的上限,单位为毫秒 2591484543d1Sopenharmony_ci 2592484543d1Sopenharmony_ci`data` 2593484543d1Sopenharmony_ci 2594484543d1Sopenharmony_ci* 表示回调函数中使用的用户数据 2595484543d1Sopenharmony_ci 2596484543d1Sopenharmony_ci`cb` 2597484543d1Sopenharmony_ci 2598484543d1Sopenharmony_ci* 表示在超时之后被执行的用户回调函数 2599484543d1Sopenharmony_ci 2600484543d1Sopenharmony_ci`repeat` 2601484543d1Sopenharmony_ci 2602484543d1Sopenharmony_ci* 表示是否重复这个定时器 2603484543d1Sopenharmony_ci 2604484543d1Sopenharmony_ci`handle` 2605484543d1Sopenharmony_ci 2606484543d1Sopenharmony_ci* 表示目标定时器的句柄 2607484543d1Sopenharmony_ci 2608484543d1Sopenharmony_ci 2609484543d1Sopenharmony_ci#### 返回值 2610484543d1Sopenharmony_ci 2611484543d1Sopenharmony_ci* ffrt_timer_start接口:返回一个定时器句柄 2612484543d1Sopenharmony_ci* ffrt_timer_stop接口:成功停止一个目标定时器,返回0;否则返回-1 2613484543d1Sopenharmony_ci 2614484543d1Sopenharmony_ci 2615484543d1Sopenharmony_ci#### 描述 2616484543d1Sopenharmony_ci 2617484543d1Sopenharmony_ci* 提供接口ffrt_timer_start设定超时的绝对时间,用于设定epoll_wait阻塞时间,若调用PollOnce时已超时,则执行入参所设的回调函数cb 2618484543d1Sopenharmony_ci* 提供接口ffrt_timer_stop用于根据任务handle取消定时任务 2619484543d1Sopenharmony_ci* 当timer超时回调被执行时,ffrt会记录并保存handle的执行状态(执行中、执行完成),该记录会在ffrt_timer_stop被调用后删除。因此建议ffrt_timer_start和ffrt_timer_stop接口成对使用,否则可能造成记录数据的无限膨胀 2620484543d1Sopenharmony_ci 2621484543d1Sopenharmony_ci 2622484543d1Sopenharmony_ci#### 样例 2623484543d1Sopenharmony_ci 2624484543d1Sopenharmony_ci```{.c} 2625484543d1Sopenharmony_ci#include <stdio.h> 2626484543d1Sopenharmony_ci#include "ffrt.h" 2627484543d1Sopenharmony_ci 2628484543d1Sopenharmony_ciusing namespace ffrt 2629484543d1Sopenharmony_ciusing namespace std 2630484543d1Sopenharmony_ci 2631484543d1Sopenharmony_cistruct TestData { 2632484543d1Sopenharmony_ci int fd; 2633484543d1Sopenharmony_ci uint64_t expected; 2634484543d1Sopenharmony_ci}; 2635484543d1Sopenharmony_ci 2636484543d1Sopenharmony_ciint main(int narg, char** argv) 2637484543d1Sopenharmony_ci{ 2638484543d1Sopenharmony_ci static int x = 0; 2639484543d1Sopenharmony_ci int* xf = &x; 2640484543d1Sopenharmony_ci void* data = xf; 2641484543d1Sopenharmony_ci uint64_t timeout = 20; 2642484543d1Sopenharmony_ci uint64_t expected = 0xabacadae; 2643484543d1Sopenharmony_ci int testFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); 2644484543d1Sopenharmony_ci 2645484543d1Sopenharmony_ci struct TestData testData {.fd = testFd, .expected = expected}; 2646484543d1Sopenharmony_ci ffrt::submit([=]() { 2647484543d1Sopenharmony_ci ffrt_qos_t taskQos = ffrt_this_task_get_qos(); 2648484543d1Sopenharmony_ci int handle = ffrt_timer_start(taskQos, timeout, data, cb, false); 2649484543d1Sopenharmony_ci 2650484543d1Sopenharmony_ci ffrt_epoll_ctl(taskQos, EPOLL_CTL_ADD, testFd, EPOLLIN, (void*)(&testData), testCallBack); 2651484543d1Sopenharmony_ci ffrt_usleep(19000); 2652484543d1Sopenharmony_ci ffrt_timer_stop(taskQos, handle); 2653484543d1Sopenharmony_ci ssize_t n = write(testFd, &expected, sizeof(uint64_t)); 2654484543d1Sopenharmony_ci stall_us(200); 2655484543d1Sopenharmony_ci 2656484543d1Sopenharmony_ci ffrt_epoll_ctl(taskQos, EPOLL_CTL_DEL, testFd, 0, nullptr, nullptr); 2657484543d1Sopenharmony_ci }, {}, {}); 2658484543d1Sopenharmony_ci ffrt::wait(); 2659484543d1Sopenharmony_ci} 2660484543d1Sopenharmony_ci 2661484543d1Sopenharmony_ci``` 2662484543d1Sopenharmony_ci 2663484543d1Sopenharmony_ci 2664484543d1Sopenharmony_ci 2665484543d1Sopenharmony_ci 2666484543d1Sopenharmony_ci## 同步原语 2667484543d1Sopenharmony_ci 2668484543d1Sopenharmony_ci### ffrt_mutex_t 2669484543d1Sopenharmony_ci<hr/> 2670484543d1Sopenharmony_ci* FFRT提供的类似pthread mutex 的性能实现 2671484543d1Sopenharmony_ci 2672484543d1Sopenharmony_ci#### 声明 2673484543d1Sopenharmony_ci 2674484543d1Sopenharmony_ci```{.cpp} 2675484543d1Sopenharmony_citypedef enum { 2676484543d1Sopenharmony_ci ffrt_error = -1, 2677484543d1Sopenharmony_ci ffrt_success = 0, 2678484543d1Sopenharmony_ci ffrt_error_nomem = ENOMEM, 2679484543d1Sopenharmony_ci ffrt_error_timedout = ETIMEDOUT, 2680484543d1Sopenharmony_ci ffrt_error_busy = EBUSY, 2681484543d1Sopenharmony_ci ffrt_error_inval = EINVAL 2682484543d1Sopenharmony_ci} ffrt_error_t; 2683484543d1Sopenharmony_ci 2684484543d1Sopenharmony_cistruct ffrt_mutex_t; 2685484543d1Sopenharmony_ci 2686484543d1Sopenharmony_cistruct ffrt_mutexattr_t; 2687484543d1Sopenharmony_ci 2688484543d1Sopenharmony_citypedef enum { 2689484543d1Sopenharmony_ci ffrt_mutex_normal = 0, 2690484543d1Sopenharmony_ci ffrt_mutex_recursive = 2, 2691484543d1Sopenharmony_ci ffrt_mutex_default = ffrt_mutex_normal 2692484543d1Sopenharmony_ci} ffrt_mutex_type; 2693484543d1Sopenharmony_ci 2694484543d1Sopenharmony_ciint ffrt_mutexattr_init(ffrt_mutexattr_t* attr); 2695484543d1Sopenharmony_ciint ffrt_mutexattr_settype(ffrt_mutexattr_t* attr, int type); 2696484543d1Sopenharmony_ciint ffrt_mutexattr_gettype(ffrt_mutexattr_t* attr, int* type); 2697484543d1Sopenharmony_ciint ffrt_mutexattr_destroy(ffrt_mutexattr_t* attr); 2698484543d1Sopenharmony_ciint ffrt_mutex_init(ffrt_mutex_t* mutex, const ffrt_mutexattr_t* attr); 2699484543d1Sopenharmony_ciint ffrt_mutex_lock(ffrt_mutex_t* mutex); 2700484543d1Sopenharmony_ciint ffrt_mutex_unlock(ffrt_mutex_t* mutex); 2701484543d1Sopenharmony_ciint ffrt_mutex_trylock(ffrt_mutex_t* mutex); 2702484543d1Sopenharmony_ciint ffrt_mutex_destroy(ffrt_mutex_t* mutex); 2703484543d1Sopenharmony_ci``` 2704484543d1Sopenharmony_ci 2705484543d1Sopenharmony_ci#### 参数 2706484543d1Sopenharmony_ci`type` 2707484543d1Sopenharmony_ci 2708484543d1Sopenharmony_ci* FFRT锁类型,当前仅支持互斥锁ffrt_mutex_normal和递归锁ffrt_mutex_recursive 2709484543d1Sopenharmony_ci 2710484543d1Sopenharmony_ci`attr` 2711484543d1Sopenharmony_ci 2712484543d1Sopenharmony_ci* FFRT锁属性,attr如果为空指针代表互斥锁mutex 2713484543d1Sopenharmony_ci 2714484543d1Sopenharmony_ci`mutex` 2715484543d1Sopenharmony_ci 2716484543d1Sopenharmony_ci* 指向所操作的锁指针 2717484543d1Sopenharmony_ci 2718484543d1Sopenharmony_ci#### 返回值 2719484543d1Sopenharmony_ci 2720484543d1Sopenharmony_ci* 若成功则为 ffrt_success ,否则发生错误 2721484543d1Sopenharmony_ci 2722484543d1Sopenharmony_ci#### 描述 2723484543d1Sopenharmony_ci* 该接口支持在FFRT task 内部调用,也支持在FFRT task 外部调用 2724484543d1Sopenharmony_ci* 该功能能够避免pthread传统的pthread_mutex_t 在抢不到锁时陷入内核的问题,在使用得当的条件下将会有更好的性能 2725484543d1Sopenharmony_ci* **注意:目前暂不支持定时功能** 2726484543d1Sopenharmony_ci* **注意:C API中的ffrt_mutexattr_t需要用户调用`ffrt_mutexattr_init`和`ffrt_mutexattr_destroy`显示创建和销毁,而C++ API无需该操作** 2727484543d1Sopenharmony_ci* **注意:C API中的ffrt_mutex_t需要用户调用`ffrt_mutex_init`和`ffrt_mutex_destroy`显式创建和销毁,而C++ API无需该操作** 2728484543d1Sopenharmony_ci* **注意:C API中的ffrt_mutex_t对象的置空和销毁由用户完成,对同一个ffrt_mutex_t仅能调用一次`ffrt_mutex_destroy`,重复对同一个ffrt_mutex_t调用`ffrt_mutex_destroy`,其行为是未定义的** 2729484543d1Sopenharmony_ci* **注意:C API中的同一个ffrt_mutexattr_t只能调用一次`ffrt_mutexattr_init`和`ffrt_mutexattr_destroy`,重复调用其行为是未定义的** 2730484543d1Sopenharmony_ci* **注意:用户需要在调用`ffrt_mutex_init`之后和调用`ffrt_mutex_destroy`之前显示调用`ffrt_mutexattr_destroy`** 2731484543d1Sopenharmony_ci* **注意:在`ffrt_mutex_destroy`之后再对ffrt_mutex_t进行访问,其行为是未定义的** 2732484543d1Sopenharmony_ci 2733484543d1Sopenharmony_ci#### 样例 2734484543d1Sopenharmony_ci 2735484543d1Sopenharmony_ci```{.c} 2736484543d1Sopenharmony_ci#include <stdio.h> 2737484543d1Sopenharmony_ci#include "ffrt.h" 2738484543d1Sopenharmony_ci 2739484543d1Sopenharmony_citypedef struct { 2740484543d1Sopenharmony_ci int* sum; 2741484543d1Sopenharmony_ci ffrt_mutex_t* mtx; 2742484543d1Sopenharmony_ci} tuple; 2743484543d1Sopenharmony_ci 2744484543d1Sopenharmony_civoid func(void* arg) 2745484543d1Sopenharmony_ci{ 2746484543d1Sopenharmony_ci tuple* t = (tuple*)arg; 2747484543d1Sopenharmony_ci 2748484543d1Sopenharmony_ci int ret = ffrt_mutex_lock(t->mtx); 2749484543d1Sopenharmony_ci if (ret != ffrt_success) { 2750484543d1Sopenharmony_ci printf("error\n"); 2751484543d1Sopenharmony_ci } 2752484543d1Sopenharmony_ci (*t->sum)++; 2753484543d1Sopenharmony_ci ret = ffrt_mutex_unlock(t->mtx); 2754484543d1Sopenharmony_ci if (ret != ffrt_success) { 2755484543d1Sopenharmony_ci printf("error\n"); 2756484543d1Sopenharmony_ci } 2757484543d1Sopenharmony_ci} 2758484543d1Sopenharmony_ci 2759484543d1Sopenharmony_citypedef struct { 2760484543d1Sopenharmony_ci ffrt_function_header_t header; 2761484543d1Sopenharmony_ci ffrt_function_t func; 2762484543d1Sopenharmony_ci ffrt_function_t after_func; 2763484543d1Sopenharmony_ci void* arg; 2764484543d1Sopenharmony_ci} c_function; 2765484543d1Sopenharmony_ci 2766484543d1Sopenharmony_cistatic void ffrt_exec_function_wrapper(void* t) 2767484543d1Sopenharmony_ci{ 2768484543d1Sopenharmony_ci c_function* f = (c_function*)t; 2769484543d1Sopenharmony_ci if (f->func) { 2770484543d1Sopenharmony_ci f->func(f->arg); 2771484543d1Sopenharmony_ci } 2772484543d1Sopenharmony_ci} 2773484543d1Sopenharmony_ci 2774484543d1Sopenharmony_cistatic void ffrt_destroy_function_wrapper(void* t) 2775484543d1Sopenharmony_ci{ 2776484543d1Sopenharmony_ci c_function* f = (c_function*)t; 2777484543d1Sopenharmony_ci if (f->after_func) { 2778484543d1Sopenharmony_ci f->after_func(f->arg); 2779484543d1Sopenharmony_ci } 2780484543d1Sopenharmony_ci} 2781484543d1Sopenharmony_ci 2782484543d1Sopenharmony_ci#define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1]) 2783484543d1Sopenharmony_cistatic inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func, 2784484543d1Sopenharmony_ci const ffrt_function_t after_func, void* arg) 2785484543d1Sopenharmony_ci{ 2786484543d1Sopenharmony_ci FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size, 2787484543d1Sopenharmony_ci size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size); 2788484543d1Sopenharmony_ci c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); 2789484543d1Sopenharmony_ci f->header.exec = ffrt_exec_function_wrapper; 2790484543d1Sopenharmony_ci f->header.destroy = ffrt_destroy_function_wrapper; 2791484543d1Sopenharmony_ci f->func = func; 2792484543d1Sopenharmony_ci f->after_func = after_func; 2793484543d1Sopenharmony_ci f->arg = arg; 2794484543d1Sopenharmony_ci return (ffrt_function_header_t*)f; 2795484543d1Sopenharmony_ci} 2796484543d1Sopenharmony_ci 2797484543d1Sopenharmony_cistatic inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func, 2798484543d1Sopenharmony_ci void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr) 2799484543d1Sopenharmony_ci{ 2800484543d1Sopenharmony_ci ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr); 2801484543d1Sopenharmony_ci} 2802484543d1Sopenharmony_ci 2803484543d1Sopenharmony_civoid ffrt_mutex_task(void *) 2804484543d1Sopenharmony_ci{ 2805484543d1Sopenharmony_ci int sum = 0; 2806484543d1Sopenharmony_ci ffrt_mutex_t mtx; 2807484543d1Sopenharmony_ci tuple t = {&sum, &mtx}; 2808484543d1Sopenharmony_ci int ret = ffrt_mutex_init(&mtx, NULL); 2809484543d1Sopenharmony_ci if (ret != ffrt_success) { 2810484543d1Sopenharmony_ci printf("error\n"); 2811484543d1Sopenharmony_ci } 2812484543d1Sopenharmony_ci for (int i = 0; i < 10; i++) { 2813484543d1Sopenharmony_ci ffrt_submit_c(func, NULL, &t, NULL, NULL, NULL); 2814484543d1Sopenharmony_ci } 2815484543d1Sopenharmony_ci ffrt_mutex_destroy(&mtx); 2816484543d1Sopenharmony_ci ffrt_wait(); 2817484543d1Sopenharmony_ci printf("sum = %d", sum); 2818484543d1Sopenharmony_ci} 2819484543d1Sopenharmony_ci 2820484543d1Sopenharmony_civoid ffrt_recursive_mutex_task(void *) 2821484543d1Sopenharmony_ci{ 2822484543d1Sopenharmony_ci int sum = 0; 2823484543d1Sopenharmony_ci int ret = 0; 2824484543d1Sopenharmony_ci ffrt_mutexattr_t attr; 2825484543d1Sopenharmony_ci ffrt_mutex_t mtx; 2826484543d1Sopenharmony_ci tuple t = {&sum, &mtx}; 2827484543d1Sopenharmony_ci ret = ffrt_recursive_mutex_init(&mtx, &attr); 2828484543d1Sopenharmony_ci if (ret != ffrt_success) { 2829484543d1Sopenharmony_ci printf("error\n"); 2830484543d1Sopenharmony_ci } 2831484543d1Sopenharmony_ci for (int i = 0; i < 10; i++) { 2832484543d1Sopenharmony_ci ffrt_submit_c(func, NULL, &t, NULL, NULL, NULL); 2833484543d1Sopenharmony_ci } 2834484543d1Sopenharmony_ci ffrt_recursive_mutex_destroy(&mtx); 2835484543d1Sopenharmony_ci ffrt_wait(); 2836484543d1Sopenharmony_ci printf("sum = %d", sum); 2837484543d1Sopenharmony_ci} 2838484543d1Sopenharmony_ci 2839484543d1Sopenharmony_ciint main(int narg, char** argv) 2840484543d1Sopenharmony_ci{ 2841484543d1Sopenharmony_ci int r; 2842484543d1Sopenharmony_ci /* mutex */ 2843484543d1Sopenharmony_ci ffrt_submit_c(ffrt_mutex_task, NULL, NULL, NULL, NULL, NULL); 2844484543d1Sopenharmony_ci ffrt_wait(); 2845484543d1Sopenharmony_ci /* recursive mutex */ 2846484543d1Sopenharmony_ci ffrt_submit_c(ffrt_recursive_mutex_task, NULL, NULL, NULL, NULL, NULL); 2847484543d1Sopenharmony_ci ffrt_wait(); 2848484543d1Sopenharmony_ci return 0; 2849484543d1Sopenharmony_ci} 2850484543d1Sopenharmony_ci``` 2851484543d1Sopenharmony_ci 2852484543d1Sopenharmony_ci预期输出为 2853484543d1Sopenharmony_ci 2854484543d1Sopenharmony_ci``` 2855484543d1Sopenharmony_cisum=10 2856484543d1Sopenharmony_ci``` 2857484543d1Sopenharmony_ci 2858484543d1Sopenharmony_ci* 该例子为功能示例,实际中并不鼓励这样使用 2859484543d1Sopenharmony_ci 2860484543d1Sopenharmony_ci### ffrt_rwlock_t 2861484543d1Sopenharmony_ci<hr/> 2862484543d1Sopenharmony_ci* FFRT提供的类似pthread rwlock 的性能实现 2863484543d1Sopenharmony_ci 2864484543d1Sopenharmony_ci#### 声明 2865484543d1Sopenharmony_ci 2866484543d1Sopenharmony_ci```{.cpp} 2867484543d1Sopenharmony_citypedef enum { 2868484543d1Sopenharmony_ci ffrt_error = -1, 2869484543d1Sopenharmony_ci ffrt_success = 0, 2870484543d1Sopenharmony_ci ffrt_error_nomem = ENOMEM, 2871484543d1Sopenharmony_ci ffrt_error_timedout = ETIMEDOUT, 2872484543d1Sopenharmony_ci ffrt_error_busy = EBUSY, 2873484543d1Sopenharmony_ci ffrt_error_inval = EINVAL 2874484543d1Sopenharmony_ci} ffrt_error_t; 2875484543d1Sopenharmony_ci 2876484543d1Sopenharmony_cistruct ffrt_rwlock_t; 2877484543d1Sopenharmony_ci 2878484543d1Sopenharmony_ciint ffrt_rwlock_init(ffrt_rwlock_t* rwlock, const ffrt_rwlockattr_t* attr); 2879484543d1Sopenharmony_ciint ffrt_rwlock_wrlock(ffrt_rwlock_t* rwlock); 2880484543d1Sopenharmony_ciint ffrt_rwlock_trywrlock(ffrt_rwlock_t* rwlock); 2881484543d1Sopenharmony_ciint ffrt_rwlock_rdlock(ffrt_rwlock_t* rwlock); 2882484543d1Sopenharmony_ciint ffrt_rwlock_tryrdlock(ffrt_rwlock_t* rwlock); 2883484543d1Sopenharmony_ciint ffrt_rwlock_unlock(ffrt_rwlock_t* rwlock); 2884484543d1Sopenharmony_ciint ffrt_rwlock_destroy(ffrt_rwlock_t* rwlock); 2885484543d1Sopenharmony_ci``` 2886484543d1Sopenharmony_ci 2887484543d1Sopenharmony_ci#### 参数 2888484543d1Sopenharmony_ci 2889484543d1Sopenharmony_ci`attr` 2890484543d1Sopenharmony_ci 2891484543d1Sopenharmony_ci* 当前FFRT只支持基础类型的rwlock,因此attr必须为空指针 2892484543d1Sopenharmony_ci 2893484543d1Sopenharmony_ci`rwlock` 2894484543d1Sopenharmony_ci 2895484543d1Sopenharmony_ci* 指向所操作的读写锁的指针 2896484543d1Sopenharmony_ci 2897484543d1Sopenharmony_ci#### 返回值 2898484543d1Sopenharmony_ci 2899484543d1Sopenharmony_ci* 若成功则为 ffrt_success ,否则发生错误 2900484543d1Sopenharmony_ci 2901484543d1Sopenharmony_ci#### 描述 2902484543d1Sopenharmony_ci* 该接口只能在FFRT task 内部调用,在FFRT task 外部调用存在未定义的行为 2903484543d1Sopenharmony_ci* 该功能能够避免pthread传统的pthread_rwlock_t 在抢不到锁时陷入内核的问题,在使用得当的条件下将会有更好的性能 2904484543d1Sopenharmony_ci* **注意:目前暂不支持递归和定时功能** 2905484543d1Sopenharmony_ci* **注意:C API中的ffrt_rwlock_t需要用户调用`ffrt_rwlock_init`和`ffrt_rwlock_destroy`显式创建和销毁,而C++ API无需该操作** 2906484543d1Sopenharmony_ci* **注意:C API中的ffrt_rwlock_t对象的置空和销毁由用户完成,对同一个ffrt_rwlock_t仅能调用一次`ffrt_rwlock_destroy`,重复对同一个ffrt_rwlock_t调用`ffrt_rwlock_destroy`,其行为是未定义的** 2907484543d1Sopenharmony_ci* **注意:在`ffrt_rwlock_destroy`之后再对ffrt_rwlock_t进行访问,其行为是未定义的** 2908484543d1Sopenharmony_ci 2909484543d1Sopenharmony_ci#### 样例 2910484543d1Sopenharmony_ci 2911484543d1Sopenharmony_ci```{.c} 2912484543d1Sopenharmony_ci#include <stdio.h> 2913484543d1Sopenharmony_ci#include "ffrt_inner.h" 2914484543d1Sopenharmony_ci 2915484543d1Sopenharmony_citypedef struct { 2916484543d1Sopenharmony_ci int* sum; 2917484543d1Sopenharmony_ci ffrt_rwlock_t* mtx; 2918484543d1Sopenharmony_ci} tuple; 2919484543d1Sopenharmony_ci 2920484543d1Sopenharmony_civoid func1(void* arg) 2921484543d1Sopenharmony_ci{ 2922484543d1Sopenharmony_ci tuple* t = (tuple*)arg; 2923484543d1Sopenharmony_ci 2924484543d1Sopenharmony_ci int ret = ffrt_rwlock_wrlock(t->mtx); 2925484543d1Sopenharmony_ci if (ret != ffrt_success) { 2926484543d1Sopenharmony_ci printf("error\n"); 2927484543d1Sopenharmony_ci } 2928484543d1Sopenharmony_ci (*t->sum)++; 2929484543d1Sopenharmony_ci ret = ffrt_rwlock_unlock(t->mtx); 2930484543d1Sopenharmony_ci if (ret != ffrt_success) { 2931484543d1Sopenharmony_ci printf("error\n"); 2932484543d1Sopenharmony_ci } 2933484543d1Sopenharmony_ci} 2934484543d1Sopenharmony_ci 2935484543d1Sopenharmony_civoid func2(void* arg) 2936484543d1Sopenharmony_ci{ 2937484543d1Sopenharmony_ci tuple* t = (tuple*)arg; 2938484543d1Sopenharmony_ci 2939484543d1Sopenharmony_ci int ret = ffrt_rwlock_rdlock(t->mtx); 2940484543d1Sopenharmony_ci if (ret != ffrt_success) { 2941484543d1Sopenharmony_ci printf("error\n"); 2942484543d1Sopenharmony_ci } 2943484543d1Sopenharmony_ci printf("sum is %d\n", *t->sum); 2944484543d1Sopenharmony_ci ret = ffrt_rwlock_unlock(t->mtx); 2945484543d1Sopenharmony_ci if (ret != ffrt_success) { 2946484543d1Sopenharmony_ci printf("error\n"); 2947484543d1Sopenharmony_ci } 2948484543d1Sopenharmony_ci} 2949484543d1Sopenharmony_ci 2950484543d1Sopenharmony_citypedef struct { 2951484543d1Sopenharmony_ci ffrt_function_header_t header; 2952484543d1Sopenharmony_ci ffrt_function_t func; 2953484543d1Sopenharmony_ci ffrt_function_t after_func; 2954484543d1Sopenharmony_ci void* arg; 2955484543d1Sopenharmony_ci} c_function; 2956484543d1Sopenharmony_ci 2957484543d1Sopenharmony_cistatic void ffrt_exec_function_wrapper(void* t) 2958484543d1Sopenharmony_ci{ 2959484543d1Sopenharmony_ci c_function* f = (c_function*)t; 2960484543d1Sopenharmony_ci if (f->func) { 2961484543d1Sopenharmony_ci f->func(f->arg); 2962484543d1Sopenharmony_ci } 2963484543d1Sopenharmony_ci} 2964484543d1Sopenharmony_ci 2965484543d1Sopenharmony_cistatic void ffrt_destroy_function_wrapper(void* t) 2966484543d1Sopenharmony_ci{ 2967484543d1Sopenharmony_ci c_function* f = (c_function*)t; 2968484543d1Sopenharmony_ci if (f->after_func) { 2969484543d1Sopenharmony_ci f->after_func(f->arg); 2970484543d1Sopenharmony_ci } 2971484543d1Sopenharmony_ci} 2972484543d1Sopenharmony_ci 2973484543d1Sopenharmony_ci#define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1]) 2974484543d1Sopenharmony_cistatic inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func, 2975484543d1Sopenharmony_ci const ffrt_function_t after_func, void* arg) 2976484543d1Sopenharmony_ci{ 2977484543d1Sopenharmony_ci FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size, 2978484543d1Sopenharmony_ci size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size); 2979484543d1Sopenharmony_ci c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); 2980484543d1Sopenharmony_ci f->header.exec = ffrt_exec_function_wrapper; 2981484543d1Sopenharmony_ci f->header.destroy = ffrt_destroy_function_wrapper; 2982484543d1Sopenharmony_ci f->func = func; 2983484543d1Sopenharmony_ci f->after_func = after_func; 2984484543d1Sopenharmony_ci f->arg = arg; 2985484543d1Sopenharmony_ci return (ffrt_function_header_t*)f; 2986484543d1Sopenharmony_ci} 2987484543d1Sopenharmony_ci 2988484543d1Sopenharmony_cistatic inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func, 2989484543d1Sopenharmony_ci void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr) 2990484543d1Sopenharmony_ci{ 2991484543d1Sopenharmony_ci ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr); 2992484543d1Sopenharmony_ci} 2993484543d1Sopenharmony_ci 2994484543d1Sopenharmony_civoid ffrt_rwlock_task(void* arg) 2995484543d1Sopenharmony_ci{ 2996484543d1Sopenharmony_ci int sum = 0; 2997484543d1Sopenharmony_ci ffrt_rwlock_t mtx; 2998484543d1Sopenharmony_ci tuple t = {&sum, &mtx}; 2999484543d1Sopenharmony_ci int ret = ffrt_rwlock_init(&mtx, NULL); 3000484543d1Sopenharmony_ci if (ret != ffrt_success) { 3001484543d1Sopenharmony_ci printf("error\n"); 3002484543d1Sopenharmony_ci } 3003484543d1Sopenharmony_ci for (int i = 0; i < 10; i++) { 3004484543d1Sopenharmony_ci ffrt_submit_c(func1, NULL, &t, NULL, NULL, NULL); 3005484543d1Sopenharmony_ci for (int j = 0; j < 5; j++) { 3006484543d1Sopenharmony_ci ffrt_submit_c(func2, NULL, &t, NULL, NULL, NULL); 3007484543d1Sopenharmony_ci } 3008484543d1Sopenharmony_ci } 3009484543d1Sopenharmony_ci ffrt_rwlock_destroy(&mtx); 3010484543d1Sopenharmony_ci ffrt_wait(); 3011484543d1Sopenharmony_ci printf("sum = %d", sum); 3012484543d1Sopenharmony_ci} 3013484543d1Sopenharmony_ci 3014484543d1Sopenharmony_ciint main(int narg, char** argv) 3015484543d1Sopenharmony_ci{ 3016484543d1Sopenharmony_ci int r; 3017484543d1Sopenharmony_ci ffrt_submit_c(ffrt_rwlock_task, NULL, NULL, NULL, NULL, NULL); 3018484543d1Sopenharmony_ci ffrt_wait(); 3019484543d1Sopenharmony_ci return 0; 3020484543d1Sopenharmony_ci} 3021484543d1Sopenharmony_ci``` 3022484543d1Sopenharmony_ci 3023484543d1Sopenharmony_ci预期输出为 3024484543d1Sopenharmony_ci 3025484543d1Sopenharmony_ci``` 3026484543d1Sopenharmony_cisum is 1 3027484543d1Sopenharmony_cisum is 2 3028484543d1Sopenharmony_cisum is 3 3029484543d1Sopenharmony_cisum is 4 3030484543d1Sopenharmony_cisum is 5 3031484543d1Sopenharmony_cisum is 6 3032484543d1Sopenharmony_cisum is 7 3033484543d1Sopenharmony_cisum is 8 3034484543d1Sopenharmony_cisum is 9 3035484543d1Sopenharmony_cisum is 10 3036484543d1Sopenharmony_ci每种各5次 3037484543d1Sopenharmony_ci 3038484543d1Sopenharmony_ci``` 3039484543d1Sopenharmony_ci 3040484543d1Sopenharmony_ci* 该例子为功能示例,实际中并不鼓励这样使用 3041484543d1Sopenharmony_ci 3042484543d1Sopenharmony_ci 3043484543d1Sopenharmony_ci### ffrt_cond_t 3044484543d1Sopenharmony_ci<hr/> 3045484543d1Sopenharmony_ci 3046484543d1Sopenharmony_ci* FFRT提供的类似pthread 信号量的性能实现 3047484543d1Sopenharmony_ci 3048484543d1Sopenharmony_ci#### 声明 3049484543d1Sopenharmony_ci 3050484543d1Sopenharmony_ci```{.c} 3051484543d1Sopenharmony_citypedef enum { 3052484543d1Sopenharmony_ci ffrt_error = -1, 3053484543d1Sopenharmony_ci ffrt_success = 0, 3054484543d1Sopenharmony_ci ffrt_error_nomem = ENOMEM, 3055484543d1Sopenharmony_ci ffrt_error_timedout = ETIMEDOUT, 3056484543d1Sopenharmony_ci ffrt_error_busy = EBUSY, 3057484543d1Sopenharmony_ci ffrt_error_inval = EINVAL 3058484543d1Sopenharmony_ci} ffrt_error_t; 3059484543d1Sopenharmony_ci 3060484543d1Sopenharmony_citypedef struct { 3061484543d1Sopenharmony_ci uint32_t storage[(ffrt_cond_storage_size + sizeof(uint32_t) - 1) / sizeof(uint32_t)]; 3062484543d1Sopenharmony_ci} ffrt_cond_t; 3063484543d1Sopenharmony_ci 3064484543d1Sopenharmony_ciint ffrt_cond_init(ffrt_cond_t* cond, const ffrt_condattr_t* attr); 3065484543d1Sopenharmony_ciint ffrt_cond_signal(ffrt_cond_t* cond); 3066484543d1Sopenharmony_ciint ffrt_cond_broadcast(ffrt_cond_t* cond); 3067484543d1Sopenharmony_ciint ffrt_cond_wait(ffrt_cond_t*cond, ffrt_mutex_t* mutex); 3068484543d1Sopenharmony_ciint ffrt_cond_timedwait(ffrt_cond_t* cond, ffrt_mutex_t* mutex, const struct timespec* time_point); 3069484543d1Sopenharmony_ciint ffrt_cond_destroy(ffrt_cond_t* cond); 3070484543d1Sopenharmony_ci``` 3071484543d1Sopenharmony_ci 3072484543d1Sopenharmony_ci#### 参数 3073484543d1Sopenharmony_ci 3074484543d1Sopenharmony_ci`cond` 3075484543d1Sopenharmony_ci 3076484543d1Sopenharmony_ci* 指向所操作的信号量的指针 3077484543d1Sopenharmony_ci 3078484543d1Sopenharmony_ci`attr` 3079484543d1Sopenharmony_ci 3080484543d1Sopenharmony_ci* 属性设定,空指针表示使用默认属性 3081484543d1Sopenharmony_ci 3082484543d1Sopenharmony_ci`mutex` 3083484543d1Sopenharmony_ci 3084484543d1Sopenharmony_ci* 指向要在阻塞期间解锁的互斥锁的指针 3085484543d1Sopenharmony_ci 3086484543d1Sopenharmony_ci`time_point` 3087484543d1Sopenharmony_ci 3088484543d1Sopenharmony_ci* 指向指定等待时限时间的对象的指针 3089484543d1Sopenharmony_ci 3090484543d1Sopenharmony_ci 3091484543d1Sopenharmony_ci#### 返回值 3092484543d1Sopenharmony_ci 3093484543d1Sopenharmony_ci* 若成功则为 ffrt_success,若在锁定互斥前抵达时限则为 ffrt_error_timedout 3094484543d1Sopenharmony_ci 3095484543d1Sopenharmony_ci#### 描述 3096484543d1Sopenharmony_ci* 该接口支持在FFRT task 内部调用,也支持在FFRT task 外部调用 3097484543d1Sopenharmony_ci* 该功能能够避免传统的pthread_cond_t在条件不满足时陷入内核的问题,在使用得当的条件下将会有更好的性能 3098484543d1Sopenharmony_ci* **注意:C API中的ffrt_cond_t需要用户调用`ffrt_cond_init`和`ffrt_cond_destroy`显式创建和销毁,而C++ API中依赖构造和析构自动完成** 3099484543d1Sopenharmony_ci* **注意:C API中的ffrt_cond_t对象的置空和销毁由用户完成,对同一个ffrt_cond_t仅能调用一次`ffrt_cond_destroy`,重复对同一个ffrt_cond_t调用`ffrt_cond_destroy`,其行为是未定义的** 3100484543d1Sopenharmony_ci* **注意:在`ffrt_cond_destroy`之后再对ffrt_cond_t进行访问,其行为是未定义的** 3101484543d1Sopenharmony_ci 3102484543d1Sopenharmony_ci#### 样例 3103484543d1Sopenharmony_ci 3104484543d1Sopenharmony_ci```{.c} 3105484543d1Sopenharmony_ci#include <stdio.h> 3106484543d1Sopenharmony_ci#include "ffrt.h" 3107484543d1Sopenharmony_ci 3108484543d1Sopenharmony_citypedef struct { 3109484543d1Sopenharmony_ci ffrt_cond_t* cond; 3110484543d1Sopenharmony_ci int* a; 3111484543d1Sopenharmony_ci ffrt_mutex_t* lock_; 3112484543d1Sopenharmony_ci} tuple; 3113484543d1Sopenharmony_ci 3114484543d1Sopenharmony_civoid func1(void* arg) 3115484543d1Sopenharmony_ci{ 3116484543d1Sopenharmony_ci tuple* t = (tuple*)arg; 3117484543d1Sopenharmony_ci int ret = ffrt_mutex_lock(t->lock_); 3118484543d1Sopenharmony_ci if (ret != ffrt_success) { 3119484543d1Sopenharmony_ci printf("error\n"); 3120484543d1Sopenharmony_ci } 3121484543d1Sopenharmony_ci while (*t->a != 1) { 3122484543d1Sopenharmony_ci ret = ffrt_cond_wait(t->cond, t->lock_); 3123484543d1Sopenharmony_ci if (ret != ffrt_success) { 3124484543d1Sopenharmony_ci printf("error\n"); 3125484543d1Sopenharmony_ci } 3126484543d1Sopenharmony_ci } 3127484543d1Sopenharmony_ci ret = ffrt_mutex_unlock(t->lock_); 3128484543d1Sopenharmony_ci if (ret != ffrt_success) { 3129484543d1Sopenharmony_ci printf("error\n"); 3130484543d1Sopenharmony_ci } 3131484543d1Sopenharmony_ci printf("a = %d", *(t->a)); 3132484543d1Sopenharmony_ci} 3133484543d1Sopenharmony_ci 3134484543d1Sopenharmony_civoid func2(void* arg) 3135484543d1Sopenharmony_ci{ 3136484543d1Sopenharmony_ci tuple* t = (tuple*)arg; 3137484543d1Sopenharmony_ci int ret = ffrt_mutex_lock(t->lock_); 3138484543d1Sopenharmony_ci if (ret != ffrt_success) { 3139484543d1Sopenharmony_ci printf("error\n"); 3140484543d1Sopenharmony_ci } 3141484543d1Sopenharmony_ci *(t->a) = 1; 3142484543d1Sopenharmony_ci ret = ffrt_cond_signal(t->cond); 3143484543d1Sopenharmony_ci if (ret != ffrt_success) { 3144484543d1Sopenharmony_ci printf("error\n"); 3145484543d1Sopenharmony_ci } 3146484543d1Sopenharmony_ci ret = ffrt_mutex_unlock(t->lock_); 3147484543d1Sopenharmony_ci if (ret != ffrt_success) { 3148484543d1Sopenharmony_ci printf("error\n"); 3149484543d1Sopenharmony_ci } 3150484543d1Sopenharmony_ci} 3151484543d1Sopenharmony_ci 3152484543d1Sopenharmony_citypedef struct { 3153484543d1Sopenharmony_ci ffrt_function_header_t header; 3154484543d1Sopenharmony_ci ffrt_function_t func; 3155484543d1Sopenharmony_ci ffrt_function_t after_func; 3156484543d1Sopenharmony_ci void* arg; 3157484543d1Sopenharmony_ci} c_function; 3158484543d1Sopenharmony_ci 3159484543d1Sopenharmony_cistatic void ffrt_exec_function_wrapper(void* t) 3160484543d1Sopenharmony_ci{ 3161484543d1Sopenharmony_ci c_function* f = (c_function*)t; 3162484543d1Sopenharmony_ci if (f->func) { 3163484543d1Sopenharmony_ci f->func(f->arg); 3164484543d1Sopenharmony_ci } 3165484543d1Sopenharmony_ci} 3166484543d1Sopenharmony_ci 3167484543d1Sopenharmony_cistatic void ffrt_destroy_function_wrapper(void* t) 3168484543d1Sopenharmony_ci{ 3169484543d1Sopenharmony_ci c_function* f = (c_function*)t; 3170484543d1Sopenharmony_ci if (f->after_func) { 3171484543d1Sopenharmony_ci f->after_func(f->arg); 3172484543d1Sopenharmony_ci } 3173484543d1Sopenharmony_ci} 3174484543d1Sopenharmony_ci 3175484543d1Sopenharmony_ci#define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1]) 3176484543d1Sopenharmony_cistatic inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func, 3177484543d1Sopenharmony_ci const ffrt_function_t after_func, void* arg) 3178484543d1Sopenharmony_ci{ 3179484543d1Sopenharmony_ci FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size, 3180484543d1Sopenharmony_ci size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size); 3181484543d1Sopenharmony_ci c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); 3182484543d1Sopenharmony_ci f->header.exec = ffrt_exec_function_wrapper; 3183484543d1Sopenharmony_ci f->header.destroy = ffrt_destroy_function_wrapper; 3184484543d1Sopenharmony_ci f->func = func; 3185484543d1Sopenharmony_ci f->after_func = after_func; 3186484543d1Sopenharmony_ci f->arg = arg; 3187484543d1Sopenharmony_ci return (ffrt_function_header_t*)f; 3188484543d1Sopenharmony_ci} 3189484543d1Sopenharmony_ci 3190484543d1Sopenharmony_cistatic inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func, 3191484543d1Sopenharmony_ci void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr) 3192484543d1Sopenharmony_ci{ 3193484543d1Sopenharmony_ci ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr); 3194484543d1Sopenharmony_ci} 3195484543d1Sopenharmony_ci 3196484543d1Sopenharmony_civoid ffrt_cv_task(void*) 3197484543d1Sopenharmony_ci{ 3198484543d1Sopenharmony_ci ffrt_cond_t cond; 3199484543d1Sopenharmony_ci int ret = ffrt_cond_init(&cond, NULL); 3200484543d1Sopenharmony_ci if (ret != ffrt_success) { 3201484543d1Sopenharmony_ci printf("error\n"); 3202484543d1Sopenharmony_ci } 3203484543d1Sopenharmony_ci int a = 0; 3204484543d1Sopenharmony_ci ffrt_mutex_t lock_; 3205484543d1Sopenharmony_ci tuple t = {&cond, &a, &lock_}; 3206484543d1Sopenharmony_ci ret = ffrt_mutex_init(&lock_, NULL); 3207484543d1Sopenharmony_ci if (ret != ffrt_success) { 3208484543d1Sopenharmony_ci printf("error\n"); 3209484543d1Sopenharmony_ci } 3210484543d1Sopenharmony_ci ffrt_submit_c(func1, NULL, &t, NULL, NULL, NULL); 3211484543d1Sopenharmony_ci ffrt_submit_c(func2, NULL, &t, NULL, NULL, NULL); 3212484543d1Sopenharmony_ci ffrt_wait(); 3213484543d1Sopenharmony_ci ffrt_cond_destroy(&cond); 3214484543d1Sopenharmony_ci ffrt_mutex_destroy(&lock_); 3215484543d1Sopenharmony_ci} 3216484543d1Sopenharmony_ci 3217484543d1Sopenharmony_ciint main(int narg, char** argv) 3218484543d1Sopenharmony_ci{ 3219484543d1Sopenharmony_ci ffrt_submit_c(ffrt_cv_task, NULL, NULL, NULL, NULL, NULL); 3220484543d1Sopenharmony_ci ffrt_wait(); 3221484543d1Sopenharmony_ci return 0; 3222484543d1Sopenharmony_ci} 3223484543d1Sopenharmony_ci``` 3224484543d1Sopenharmony_ci 3225484543d1Sopenharmony_ci预期输出为: 3226484543d1Sopenharmony_ci 3227484543d1Sopenharmony_ci``` 3228484543d1Sopenharmony_cia=1 3229484543d1Sopenharmony_ci``` 3230484543d1Sopenharmony_ci 3231484543d1Sopenharmony_ci* 该例子为功能示例,实际中并不鼓励这样使用 3232484543d1Sopenharmony_ci 3233484543d1Sopenharmony_ci## 杂项 3234484543d1Sopenharmony_ci 3235484543d1Sopenharmony_ci### ffrt_usleep 3236484543d1Sopenharmony_ci 3237484543d1Sopenharmony_ci<hr/> 3238484543d1Sopenharmony_ci 3239484543d1Sopenharmony_ci* FFRT提供的类似C11 sleep和linux usleep的性能实现 3240484543d1Sopenharmony_ci 3241484543d1Sopenharmony_ci#### 声明 3242484543d1Sopenharmony_ci 3243484543d1Sopenharmony_ci```{.c} 3244484543d1Sopenharmony_ciint ffrt_usleep(uint64_t usec); 3245484543d1Sopenharmony_ci``` 3246484543d1Sopenharmony_ci 3247484543d1Sopenharmony_ci#### 参数 3248484543d1Sopenharmony_ci 3249484543d1Sopenharmony_ci`usec` 3250484543d1Sopenharmony_ci 3251484543d1Sopenharmony_ci* 睡眠的us数 3252484543d1Sopenharmony_ci 3253484543d1Sopenharmony_ci#### 返回值 3254484543d1Sopenharmony_ci 3255484543d1Sopenharmony_ci* 不涉及 3256484543d1Sopenharmony_ci 3257484543d1Sopenharmony_ci#### 描述 3258484543d1Sopenharmony_ci* 该接口只能在FFRT task 内部调用,在FFRT task 外部调用存在未定义的行为 3259484543d1Sopenharmony_ci* 该功能能够避免传统的sleep 睡眠时陷入内核的问题,在使用得当的条件下将会有更好的性能 3260484543d1Sopenharmony_ci 3261484543d1Sopenharmony_ci#### 样例 3262484543d1Sopenharmony_ci 3263484543d1Sopenharmony_ci```{.c} 3264484543d1Sopenharmony_ci#include <stdio.h> 3265484543d1Sopenharmony_ci#include "ffrt.h" 3266484543d1Sopenharmony_ci 3267484543d1Sopenharmony_civoid func(void* arg) 3268484543d1Sopenharmony_ci{ 3269484543d1Sopenharmony_ci time_t current_time = time(NULL); 3270484543d1Sopenharmony_ci printf("Time: %s", ctime(¤t_time)); 3271484543d1Sopenharmony_ci ffrt_usleep(2000000); // 睡眠 2 秒 3272484543d1Sopenharmony_ci current_time = time(NULL); 3273484543d1Sopenharmony_ci printf("Time: %s", ctime(¤t_time)); 3274484543d1Sopenharmony_ci} 3275484543d1Sopenharmony_ci 3276484543d1Sopenharmony_citypedef struct { 3277484543d1Sopenharmony_ci ffrt_function_header_t header; 3278484543d1Sopenharmony_ci ffrt_function_t func; 3279484543d1Sopenharmony_ci ffrt_function_t after_func; 3280484543d1Sopenharmony_ci void* arg; 3281484543d1Sopenharmony_ci} c_function; 3282484543d1Sopenharmony_ci 3283484543d1Sopenharmony_cistatic void ffrt_exec_function_wrapper(void* t) 3284484543d1Sopenharmony_ci{ 3285484543d1Sopenharmony_ci c_function* f = (c_function*)t; 3286484543d1Sopenharmony_ci if (f->func) { 3287484543d1Sopenharmony_ci f->func(f->arg); 3288484543d1Sopenharmony_ci } 3289484543d1Sopenharmony_ci} 3290484543d1Sopenharmony_ci 3291484543d1Sopenharmony_cistatic void ffrt_destroy_function_wrapper(void* t) 3292484543d1Sopenharmony_ci{ 3293484543d1Sopenharmony_ci c_function* f = (c_function*)t; 3294484543d1Sopenharmony_ci if (f->after_func) { 3295484543d1Sopenharmony_ci f->after_func(f->arg); 3296484543d1Sopenharmony_ci } 3297484543d1Sopenharmony_ci} 3298484543d1Sopenharmony_ci 3299484543d1Sopenharmony_ci#define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1]) 3300484543d1Sopenharmony_cistatic inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func, 3301484543d1Sopenharmony_ci const ffrt_function_t after_func, void* arg) 3302484543d1Sopenharmony_ci{ 3303484543d1Sopenharmony_ci FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size, 3304484543d1Sopenharmony_ci size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size); 3305484543d1Sopenharmony_ci c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); 3306484543d1Sopenharmony_ci f->header.exec = ffrt_exec_function_wrapper; 3307484543d1Sopenharmony_ci f->header.destroy = ffrt_destroy_function_wrapper; 3308484543d1Sopenharmony_ci f->func = func; 3309484543d1Sopenharmony_ci f->after_func = after_func; 3310484543d1Sopenharmony_ci f->arg = arg; 3311484543d1Sopenharmony_ci return (ffrt_function_header_t*)f; 3312484543d1Sopenharmony_ci} 3313484543d1Sopenharmony_ci 3314484543d1Sopenharmony_cistatic inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func, 3315484543d1Sopenharmony_ci void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr) 3316484543d1Sopenharmony_ci{ 3317484543d1Sopenharmony_ci ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr); 3318484543d1Sopenharmony_ci} 3319484543d1Sopenharmony_ci 3320484543d1Sopenharmony_ciint main(int narg, char** argv) 3321484543d1Sopenharmony_ci{ 3322484543d1Sopenharmony_ci ffrt_submit_c(func, NULL, NULL, NULL, NULL, NULL); 3323484543d1Sopenharmony_ci ffrt_wait(); 3324484543d1Sopenharmony_ci return 0; 3325484543d1Sopenharmony_ci} 3326484543d1Sopenharmony_ci``` 3327484543d1Sopenharmony_ci 3328484543d1Sopenharmony_ci预期输出为 3329484543d1Sopenharmony_ci 3330484543d1Sopenharmony_ci``` 3331484543d1Sopenharmony_ciTime: Tue Aug 13 11:34:40 2024 3332484543d1Sopenharmony_ciTime: Tue Aug 13 11:34:42 2024 3333484543d1Sopenharmony_ci``` 3334484543d1Sopenharmony_ci 3335484543d1Sopenharmony_ci### ffrt_yield 3336484543d1Sopenharmony_ci<hr/> 3337484543d1Sopenharmony_ci 3338484543d1Sopenharmony_ci* 当前task 主动让出CPU 执行资源,让其他可以被执行的task 先执行,如果没有其他可被执行的task,yield 无效 3339484543d1Sopenharmony_ci 3340484543d1Sopenharmony_ci#### 声明 3341484543d1Sopenharmony_ci 3342484543d1Sopenharmony_ci```{.cpp} 3343484543d1Sopenharmony_civoid ffrt_yield(); 3344484543d1Sopenharmony_ci``` 3345484543d1Sopenharmony_ci 3346484543d1Sopenharmony_ci#### 参数 3347484543d1Sopenharmony_ci 3348484543d1Sopenharmony_ci* 不涉及 3349484543d1Sopenharmony_ci 3350484543d1Sopenharmony_ci#### 返回值 3351484543d1Sopenharmony_ci 3352484543d1Sopenharmony_ci* 不涉及 3353484543d1Sopenharmony_ci 3354484543d1Sopenharmony_ci#### 描述 3355484543d1Sopenharmony_ci* 该接口只能在FFRT task 内部调用,在FFRT task 外部调用存在未定义的行为 3356484543d1Sopenharmony_ci* 此函数的确切行为取决于实现,特别是使用中的FFRT 调度程序的机制和系统状态 3357484543d1Sopenharmony_ci 3358484543d1Sopenharmony_ci#### 样例 3359484543d1Sopenharmony_ci 3360484543d1Sopenharmony_ci* 省略 3361484543d1Sopenharmony_ci 3362484543d1Sopenharmony_ci## 维测 3363484543d1Sopenharmony_ci 3364484543d1Sopenharmony_ci### 长耗时任务监测 3365484543d1Sopenharmony_ci 3366484543d1Sopenharmony_ci#### 描述 3367484543d1Sopenharmony_ci* 长耗时任务打印机制 3368484543d1Sopenharmony_ci 当任务执行时间超过一秒时,会触发一次堆栈打印,后续该任务堆栈打印频率调整为一分钟。连续打印十次后,打印频率调整为十分钟。再触发十次打印后,打印频率固定为三十分钟。 3369484543d1Sopenharmony_ci* 该机制的堆栈打印调用的是DFX的 `GetBacktraceStringByTid` 接口,该接口会向阻塞线程发送抓栈信号,触发中断并抓取调用栈返回。 3370484543d1Sopenharmony_ci 3371484543d1Sopenharmony_ci#### 样例 3372484543d1Sopenharmony_ci在对应进程日志中搜索 `RecordSymbolAndBacktrace` 关键字,对应的日志示例如下: 3373484543d1Sopenharmony_ci 3374484543d1Sopenharmony_ci``` 3375484543d1Sopenharmony_ciW C01719/ffrt: 60500:RecordSymbolAndBacktrace:159 Tid[16579] function occupies worker for more than [1]s. 3376484543d1Sopenharmony_ciW C01719/ffrt: 60501:RecordSymbolAndBacktrace:164 Backtrace: 3377484543d1Sopenharmony_ciW C01719/ffrt: #00 pc 00000000000075f0 /system/lib64/module/file/libhash.z.so 3378484543d1Sopenharmony_ciW C01719/ffrt: #01 pc 0000000000008758 /system/lib64/module/file/libhash.z.so 3379484543d1Sopenharmony_ciW C01719/ffrt: #02 pc 0000000000012b98 /system/lib64/module/file/libhash.z.so 3380484543d1Sopenharmony_ciW C01719/ffrt: #03 pc 000000000002aaa0 /system/lib64/platformsdk/libfilemgmt_libn.z.so 3381484543d1Sopenharmony_ciW C01719/ffrt: #04 pc 0000000000054b2c /system/lib64/platformsdk/libace_napi.z.so 3382484543d1Sopenharmony_ciW C01719/ffrt: #05 pc 00000000000133a8 /system/lib64/platformsdk/libuv.so 3383484543d1Sopenharmony_ciW C01719/ffrt: #06 pc 00000000000461a0 /system/lib64/chipset-sdk/libffrt.so 3384484543d1Sopenharmony_ciW C01719/ffrt: #07 pc 0000000000046d44 /system/lib64/chipset-sdk/libffrt.so 3385484543d1Sopenharmony_ciW C01719/ffrt: #08 pc 0000000000046a6c /system/lib64/chipset-sdk/libffrt.so 3386484543d1Sopenharmony_ciW C01719/ffrt: #09 pc 00000000000467b0 /system/lib64/chipset-sdk/libffrt.so 3387484543d1Sopenharmony_ci``` 3388484543d1Sopenharmony_ci该维测会打印出worker上执行时间超过阈值的任务堆栈、worker线程号、执行时间,请自行根据堆栈找对应组件确认阻塞原因。 3389484543d1Sopenharmony_ci 3390484543d1Sopenharmony_ci 3391484543d1Sopenharmony_ci#### 注意事项 3392484543d1Sopenharmony_ci如果代码中存在 `sleep` 等会被中断唤醒的阻塞,用户需主动接收该阻塞的返回值,并重新调用。 3393484543d1Sopenharmony_ci示例如下: 3394484543d1Sopenharmony_ci``` 3395484543d1Sopenharmony_ciunsigned int leftTime = sleep(10); 3396484543d1Sopenharmony_ciwhile (leftTime != 0) { 3397484543d1Sopenharmony_ci leftTime = sleep(leftTime); 3398484543d1Sopenharmony_ci} 3399484543d1Sopenharmony_ci``` 3400484543d1Sopenharmony_ci 3401484543d1Sopenharmony_ci# 部署 3402484543d1Sopenharmony_ci 3403484543d1Sopenharmony_ci## 部署方式 3404484543d1Sopenharmony_ci<img src="images/image-20230120153923679.png" alt="image-20230120153923679" style="zoom:67%;" /> 3405484543d1Sopenharmony_ci 3406484543d1Sopenharmony_ci* FFRT的部署依赖FFRT动态库libffrt.so和一组header头文件 3407484543d1Sopenharmony_ci 3408484543d1Sopenharmony_ci* FFRT的头文件为`ffrt.h`,内部包含了C++ API,C API和C base API 3409484543d1Sopenharmony_ci * ffrt.h 定义为: 3410484543d1Sopenharmony_ci ```{.cpp} 3411484543d1Sopenharmony_ci #ifndef FFRT_API_FFRT_H 3412484543d1Sopenharmony_ci #define FFRT_API_FFRT_H 3413484543d1Sopenharmony_ci #ifdef __cplusplus 3414484543d1Sopenharmony_ci #include "cpp/task.h" 3415484543d1Sopenharmony_ci #include "cpp/deadline.h" 3416484543d1Sopenharmony_ci #include "cpp/sys_event.h" 3417484543d1Sopenharmony_ci #include "cpp/mutex.h" 3418484543d1Sopenharmony_ci #include "cpp/condition_variable.h" 3419484543d1Sopenharmony_ci #include "cpp/sleep.h" 3420484543d1Sopenharmony_ci #include "cpp/thread.h" 3421484543d1Sopenharmony_ci #include "cpp/config.h" 3422484543d1Sopenharmony_ci #include "cpp/future.h" 3423484543d1Sopenharmony_ci #else 3424484543d1Sopenharmony_ci #include "c/task.h" 3425484543d1Sopenharmony_ci #include "c/deadline.h" 3426484543d1Sopenharmony_ci #include "c/sys_event.h" 3427484543d1Sopenharmony_ci #include "c/mutex.h" 3428484543d1Sopenharmony_ci #include "c/condition_variable.h" 3429484543d1Sopenharmony_ci #include "c/sleep.h" 3430484543d1Sopenharmony_ci #include "c/thread.h" 3431484543d1Sopenharmony_ci #include "c/config.h" 3432484543d1Sopenharmony_ci #endif 3433484543d1Sopenharmony_ci #endif 3434484543d1Sopenharmony_ci ``` 3435484543d1Sopenharmony_ci * C base API定义示例: 3436484543d1Sopenharmony_ci ```{.cpp} 3437484543d1Sopenharmony_ci void ffrt_submit_base(ffrt_function_header_t* func, ...); 3438484543d1Sopenharmony_ci int ffrt_mutex_init(...); 3439484543d1Sopenharmony_ci ``` 3440484543d1Sopenharmony_ci * C API定义示例: 3441484543d1Sopenharmony_ci ```{.cpp} 3442484543d1Sopenharmony_ci static inline void ffrt_submit(ffrt_function_t func, void* arg, ...) 3443484543d1Sopenharmony_ci { 3444484543d1Sopenharmony_ci ffrt_submit_base(ffrt_create_function_wrapper(func, arg), ...); 3445484543d1Sopenharmony_ci } 3446484543d1Sopenharmony_ci ``` 3447484543d1Sopenharmony_ci * C++ API定义示例: 3448484543d1Sopenharmony_ci ```{.cpp} 3449484543d1Sopenharmony_ci namespace ffrt { 3450484543d1Sopenharmony_ci static inline void submit(std::function& func, ...) 3451484543d1Sopenharmony_ci { 3452484543d1Sopenharmony_ci ffrt_submit_base(ffrt_create_function_wrapper(func), ...); 3453484543d1Sopenharmony_ci } 3454484543d1Sopenharmony_ci struct mutex { 3455484543d1Sopenharmony_ci mutex() { 3456484543d1Sopenharmony_ci ffrt_mutex_init(...); 3457484543d1Sopenharmony_ci ... 3458484543d1Sopenharmony_ci }; 3459484543d1Sopenharmony_ci } 3460484543d1Sopenharmony_ci ``` 3461484543d1Sopenharmony_ci 3462484543d1Sopenharmony_ci* **出于易用性方面的考虑,除非必要,强烈建议你使用C++ API,调用C API将会使你的代码非常臃肿或者更容易产生资源未释放问题** 3463484543d1Sopenharmony_ci 3464484543d1Sopenharmony_ci| 需求列表 | 3465484543d1Sopenharmony_ci| ------------------------------------------------------------ | 3466484543d1Sopenharmony_ci| 需求1:ABI兼容性,在NDK场景中由于用户的编译环境与FFRT的编译环境不同,使用C++接口可能存在ABI兼容性问题,要有解决方案 | 3467484543d1Sopenharmony_ci| 需求2:用户的编译环境为纯C编译环境,不想因为引入FFRT而引入C++元素的场景,要有解决方案 | 3468484543d1Sopenharmony_ci| 需求3:易用性,尽可能让接口简单易用,用户少出错 | 3469484543d1Sopenharmony_ci 3470484543d1Sopenharmony_ci* 对于需求1,通过在用户调用的C++接口和FFRT的实现之间增加一个C base API层,并基于头文件方式将API中的C++的元素编译到用户的so,从而解决ABI兼容的问题 3471484543d1Sopenharmony_ci* 对于需求2,可以通过C Base API解决 3472484543d1Sopenharmony_ci* 对于需求3,建议用户尽可能使用C++ API,以避免C API固有的资源未初始化/释放、参数冗长等问题,对于不得不使用C API的场景,FFRT仍然支持用户使用C API和C base API 3473484543d1Sopenharmony_ci 3474484543d1Sopenharmony_ci 3475484543d1Sopenharmony_ci 3476484543d1Sopenharmony_ci<br/> 3477484543d1Sopenharmony_ci<br/> 3478484543d1Sopenharmony_ci 3479484543d1Sopenharmony_ci<hr/> 3480484543d1Sopenharmony_ci# 实战指南 3481484543d1Sopenharmony_ci 3482484543d1Sopenharmony_ci## 步骤1: 分析应用 3483484543d1Sopenharmony_ci 3484484543d1Sopenharmony_ci使用 FFRT 并行编程的第一步便是您需要了解你的应用。 3485484543d1Sopenharmony_ci 3486484543d1Sopenharmony_ci【建议1】:使用 Task 梳理应用的流程。 3487484543d1Sopenharmony_ci 3488484543d1Sopenharmony_ci使用 Task 梳理应用的流程,并且尽可能使用数据来表达 Task 之间的依赖。当然如果两个 Task 之间如无数据依赖,仅存在控制依赖,您也可以创建一个虚拟的(或者逻辑上的)数据依赖。 3489484543d1Sopenharmony_ci 3490484543d1Sopenharmony_ci<img src="images/image-20220926152831526.png" style="zoom:70%" /> 3491484543d1Sopenharmony_ci 3492484543d1Sopenharmony_ci<center>AIRAW 的数据流图</center> 3493484543d1Sopenharmony_ci 3494484543d1Sopenharmony_ci基于数据流图,可以很容易判定出哪些 Task 是可以并发的,比如,Slice0 的 NPU Task 和 Slice1 的 GPU Pre Task 是可以并发的,因为它们没有任何依赖。 3495484543d1Sopenharmony_ci 3496484543d1Sopenharmony_ci反过来,如果并发的效果不理想,也可以通过调整数据流图来优化并发。例如,假如上图中GPU Pre Task 执行时间有很大波动,但平均耗时略小于 NPU Task,会出现某些时刻 GPU Pre Task 拖慢整个执行时间。此时,如果将 GPU Pre Task 的输出 Buffer 改成3个(或者更多)的 Buffer ,可以增加 GPU Pre Task 和 NPU Task 的并发机会,将降低波动对总执行时间的影响。 3497484543d1Sopenharmony_ci 3498484543d1Sopenharmony_ci 3499484543d1Sopenharmony_ci 3500484543d1Sopenharmony_ci【建议2】:这里不用太担心 Task 大或小的问题,因为 FFRT 允许你在 Task 内部继续拆分 SubTask,可以逐步细化。 3501484543d1Sopenharmony_ci 3502484543d1Sopenharmony_ci下图中,第一次画数据流图时,可以不将 FaceDirection 和 UpdateExistFaceImageInfo 两个 Task 展开,可以逐步细化。 3503484543d1Sopenharmony_ci 3504484543d1Sopenharmony_ci<img src="images/image-20220926153003884.png" style="zoom:70%" /> 3505484543d1Sopenharmony_ci 3506484543d1Sopenharmony_ci<center>某拍照业务的数据流图</center> 3507484543d1Sopenharmony_ci 3508484543d1Sopenharmony_ci【建议3】:上述流程图或者数据流图不要求是静态图(即 Task 数量和 Task 依赖关系是固定的) 3509484543d1Sopenharmony_ci 3510484543d1Sopenharmony_ciFFRT 允许动态提交 Task ,在编程界面上不体现图的概念,FFRT 内部会根据Task 之间的依赖关系动态调整数据流图的节点。 3511484543d1Sopenharmony_ci 3512484543d1Sopenharmony_ci 3513484543d1Sopenharmony_ci【建议4】:尽可能对应用做热点分析 3514484543d1Sopenharmony_ci 3515484543d1Sopenharmony_ci如果是对存量代码的 FFRT 化改造,那么,使用 System Trace 这类工具能帮助您聚焦在性能热点上,比如下图可以很容易知道当前的性能Bound,在分析数据流图时,可以重点关注这些热点任务。 3516484543d1Sopenharmony_ci 3517484543d1Sopenharmony_ci<img src="images/image-20220926153030993.png" style="zoom:70%" /> 3518484543d1Sopenharmony_ci 3519484543d1Sopenharmony_ci<center>某业务的System Trace</center> 3520484543d1Sopenharmony_ci 3521484543d1Sopenharmony_ci## 步骤2: 并行化应用 3522484543d1Sopenharmony_ci 3523484543d1Sopenharmony_ci【建议1】:不要直接使用线程,使用 FFRT 提交Task。 3524484543d1Sopenharmony_ci 3525484543d1Sopenharmony_ci如果应用中有明显的数据依赖关系,那么 FFRT 将会非常适合;最差的情况是应用没有数据依赖或难以并行(如果真的存在),您仍然可以把 FFRT 当做一个高效的进程级线程池、或者协程库去使用它,但非常不建议你继续创建线程。 3526484543d1Sopenharmony_ci 3527484543d1Sopenharmony_ci 3528484543d1Sopenharmony_ci 3529484543d1Sopenharmony_ci【建议2】:Task 最好被建模为纯函数。 3530484543d1Sopenharmony_ci 3531484543d1Sopenharmony_ci纯函数是指其执行没有副作用,例如更新全局数据结构。每个任务都依赖于其输入/输出签名来连接到其他任务。 3532484543d1Sopenharmony_ci 3533484543d1Sopenharmony_ci请注意,即使 Task 不是"纯"的,FFRT 仍然适用。只要任务使用的数据依赖或者锁足以保证正确执行,FFRT 就能正常工作。 3534484543d1Sopenharmony_ci 3535484543d1Sopenharmony_ci 3536484543d1Sopenharmony_ci 3537484543d1Sopenharmony_ci【建议3】:尽可能尝试通过 inDeps/outDeps 表达依赖,而不是使用 ffrt::wait()。 3538484543d1Sopenharmony_ci 3539484543d1Sopenharmony_ci这是因为 FFRT 跟踪和处理 inDeps/outDeps 比调用显式 ffrt::wait() 函数更自然、更便宜。 3540484543d1Sopenharmony_ci 3541484543d1Sopenharmony_ci 3542484543d1Sopenharmony_ci 3543484543d1Sopenharmony_ci【建议4】:注意 Task 粒度 3544484543d1Sopenharmony_ci 3545484543d1Sopenharmony_ci以适当的粒度提交任务至关重要:目前每个任务的调度开销约为 10 us。如果 Task 的粒度非常小,那么开销的百分比将会很高。FFRT 会继续基于软硬件的方式优化调度开销。 3546484543d1Sopenharmony_ci 3547484543d1Sopenharmony_ci 3548484543d1Sopenharmony_ci 3549484543d1Sopenharmony_ci【建议5】:尽可能使用 FFRT 原语 3550484543d1Sopenharmony_ci 3551484543d1Sopenharmony_ci如果需要mutex、sleep、异步 I/O,请使用 FFRT 原语,而不是使用OS 提供的版本。因为这些 FFRT 提供的实现在与 FFRT 配合时开销将会更小。 3552484543d1Sopenharmony_ci 3553484543d1Sopenharmony_ci 3554484543d1Sopenharmony_ci 3555484543d1Sopenharmony_ci【建议6】:在需要时,使用 ffrt::wait() 确保栈变量的生命周期。 3556484543d1Sopenharmony_ci 3557484543d1Sopenharmony_ci如果子任务使用驻留在父任务栈上的数据,则父任务应避免在子任务执行完成前返回。在父任务的末尾添加 ffrt::wait() 可以解决这个问题。 3558484543d1Sopenharmony_ci 3559484543d1Sopenharmony_ci 3560484543d1Sopenharmony_ci 3561484543d1Sopenharmony_ci## 步骤3: 优化应用 3562484543d1Sopenharmony_ci 3563484543d1Sopenharmony_ci【建议1】:基于System Trace,分析并行是否符合预期 3564484543d1Sopenharmony_ci 3565484543d1Sopenharmony_ciFFRT 已经内置 SysTrace 支持,默认以txx.xx表示,非常有利于分析 Task 粒度和并发度。未来,在性能分析和维测方面将继续增强。 3566484543d1Sopenharmony_ci 3567484543d1Sopenharmony_ci<img src="images/image-20220926153209875.png" style="zoom:70%" /> 3568484543d1Sopenharmony_ci 3569484543d1Sopenharmony_ci【建议2】:对于耗时的 Task,尝试提交 SubTask,提升应用的并行度 3570484543d1Sopenharmony_ci 3571484543d1Sopenharmony_ci 3572484543d1Sopenharmony_ci【建议3】:在合适的场景,使用 Deadline 调度,实现能效和性能的平衡 3573484543d1Sopenharmony_ci 3574484543d1Sopenharmony_ci方案正在验证中,待更新。 3575484543d1Sopenharmony_ci 3576484543d1Sopenharmony_ci 3577484543d1Sopenharmony_ci 3578484543d1Sopenharmony_ci## 样例: CameraHal QuickThumb 3579484543d1Sopenharmony_ci 3580484543d1Sopenharmony_ci### 步骤1: 分析应用 3581484543d1Sopenharmony_ci 3582484543d1Sopenharmony_ci<img src="images/image-20220926153255824.png" style="zoom:70%" /> 3583484543d1Sopenharmony_ci 3584484543d1Sopenharmony_ci1) QuickThumb 是 CameraHal 中实现的对一张图片进行缩小的功能,整体运行时间约30 us; 3585484543d1Sopenharmony_ci 3586484543d1Sopenharmony_ci2) 在实现上分为两层循环,外层的一次循环输出1行,内层的1次循环输出该行的m列; 3587484543d1Sopenharmony_ci 3588484543d1Sopenharmony_ci3) 在划分 Task 时,一种简单的做法是1行的处理就是1个Task。 3589484543d1Sopenharmony_ci 3590484543d1Sopenharmony_ci### 步骤2: 并行化应用 3591484543d1Sopenharmony_ci<img src="images/image-20220926153509205.png" style="zoom:100%" /> 3592484543d1Sopenharmony_ci 3593484543d1Sopenharmony_ci 1) 根据纯函数的定义,该 Task 的输入输出的数据是非常之多的,因此,这个场景下使用更宽泛的纯函数的定义,只需要考虑在 Task 内部会被写,但是却被定义在 Task 外部的变量即可; 3594484543d1Sopenharmony_ci 3595484543d1Sopenharmony_ci2) 按照上面的原则,将 py/puv 的定义移到 Task 内部可避免多个 Task 同时写 py/puv 的问题; 3596484543d1Sopenharmony_ci 3597484543d1Sopenharmony_ci3) s32r 的处理可以有两种方式,都能得到正确的功能:a. 保持定义在Task 外部,但作为Task 的输出依赖;b. 将s32r定义在Task 内部,作为Task的私有变量。显然,b 方案能够获得更好的性能 3598484543d1Sopenharmony_ci 3599484543d1Sopenharmony_ci 3600484543d1Sopenharmony_ci 3601484543d1Sopenharmony_ci### 步骤3: 优化应用 3602484543d1Sopenharmony_ci 3603484543d1Sopenharmony_ci通过System Trace,会发现上述改造方案的Task 粒度较小,大约单个Task 耗时在5us左右,因此,扩大Task的粒度为32行处理,得到最终的并行结果,下图为使用4小核和3中核的结果。 3604484543d1Sopenharmony_ci 3605484543d1Sopenharmony_ci<img src="images/image-20220926153603572.png" style="zoom:100%" /> 3606484543d1Sopenharmony_ci 3607484543d1Sopenharmony_ci 3608484543d1Sopenharmony_ci 3609484543d1Sopenharmony_ci## 样例: Camera AIRAW 3610484543d1Sopenharmony_ci 3611484543d1Sopenharmony_ci### 步骤1: 分析应用 3612484543d1Sopenharmony_ci<img src="images/image-20220926153611121.png" style="zoom:70%" /> 3613484543d1Sopenharmony_ci 3614484543d1Sopenharmony_ciAIRAW 的处理包括了3个处理步骤,在数据面上,可以按slice 进行切分,在不考虑pre_outbuf和npu_outbuf 在slice间复用的情况下,数据流图如上图所示。 3615484543d1Sopenharmony_ci 3616484543d1Sopenharmony_ci<img src="images/image-20220926152831526.png" style="zoom:70%" /> 3617484543d1Sopenharmony_ci 3618484543d1Sopenharmony_ci为了节省运行过程中的内存占用,但不影响整体性能,可以只保留2个pre_outbuf和2个npu_outbuf。 3619484543d1Sopenharmony_ci 3620484543d1Sopenharmony_ci`为此付出的代价是:Buffer 的复用产生了slice3 的GPU Pre Task 依赖slice1 的NPU Task 完成,俗称反压,又称生产者依赖关系。但是,如果您使用 FFRT 来实现,将会是非常自然而高效的` 3621484543d1Sopenharmony_ci 3622484543d1Sopenharmony_ci### 步骤2: 并行化应用 3623484543d1Sopenharmony_ci 3624484543d1Sopenharmony_ci```{.cpp} 3625484543d1Sopenharmony_ciconstexpr uint32_t SLICE_NUM = 24; 3626484543d1Sopenharmony_ciconstexpr uint32_t BUFFER_NUM = 2; 3627484543d1Sopenharmony_ci 3628484543d1Sopenharmony_ciint input[SLICE_NUM]; // input is split into SLICE_NUM slices 3629484543d1Sopenharmony_ciint pre_outbuf[BUFFER_NUM]; // gpu pre task output buffers 3630484543d1Sopenharmony_ciint npu_outbuf[BUFFER_NUM]; // npu output buffers 3631484543d1Sopenharmony_ciint output[SLICE_NUM]; // output is split into SLICE_NUM slices 3632484543d1Sopenharmony_ci 3633484543d1Sopenharmony_cifor (uint32_t i = 0; i < SLICE_NUM; i++) { 3634484543d1Sopenharmony_ci uint32_t buf_id = i % BUFFER_NUM; 3635484543d1Sopenharmony_ci ffrt::submit(gpuPreTask, {input + i}, {pre_outbuf + buf_id}); 3636484543d1Sopenharmony_ci ffrt::submit(npuTask, {pre_outbuf + buf_id}, {npu_outbuf + buf_id}); 3637484543d1Sopenharmony_ci ffrt::submit(gpuPostTask, {npu_outbuf + buf_id}, {output + i}); 3638484543d1Sopenharmony_ci} 3639484543d1Sopenharmony_ci 3640484543d1Sopenharmony_ciffrt::wait(); 3641484543d1Sopenharmony_ci``` 3642484543d1Sopenharmony_ci 3643484543d1Sopenharmony_ci### 步骤3: 优化应用 3644484543d1Sopenharmony_ci 3645484543d1Sopenharmony_ci<img src="images/image-20220926153825527.png" style="zoom:100%" /> 3646484543d1Sopenharmony_ci 3647484543d1Sopenharmony_ci基于以上实现,从上面的Trace中我们看到,NPU 的硬件时间被完全用满,系统端到端性能达到最优,而付出的开发代价将会比GCD 或多线程小的多。 3648484543d1Sopenharmony_ci 3649484543d1Sopenharmony_ci 3650484543d1Sopenharmony_ci 3651484543d1Sopenharmony_ci## 样例: Camera FaceStory 3652484543d1Sopenharmony_ci 3653484543d1Sopenharmony_ci### 步骤1: 分析应用 3654484543d1Sopenharmony_ci 3655484543d1Sopenharmony_ci<img src="images/image-20220926153003884.png" style="zoom:70%" /> 3656484543d1Sopenharmony_ci 3657484543d1Sopenharmony_ci 3658484543d1Sopenharmony_ci 3659484543d1Sopenharmony_ci### 步骤2: 并行化应用 3660484543d1Sopenharmony_ci 3661484543d1Sopenharmony_ci<img src="images/image-20220926153906692.png" style="zoom:100%" /> 3662484543d1Sopenharmony_ci 3663484543d1Sopenharmony_ci代码改造样例 3664484543d1Sopenharmony_ci 3665484543d1Sopenharmony_ci1) 该场景输出存量代码迁移,只需将原先串行的代码以Task的方式提交即可; 3666484543d1Sopenharmony_ci 3667484543d1Sopenharmony_ci2) 过程中需要考虑Data Race和数据生命周期; 3668484543d1Sopenharmony_ci 3669484543d1Sopenharmony_ci3) 先提交大的Task,根据需要逐步拆分SubTask。 3670484543d1Sopenharmony_ci 3671484543d1Sopenharmony_ci 3672484543d1Sopenharmony_ci 3673484543d1Sopenharmony_ci### 步骤3: 优化应用 3674484543d1Sopenharmony_ci 3675484543d1Sopenharmony_ci<img src="images/image-20220926153030993.png" style="zoom:100%" /> 3676484543d1Sopenharmony_ci 3677484543d1Sopenharmony_ci<center>原始System Trace</center> 3678484543d1Sopenharmony_ci 3679484543d1Sopenharmony_ci<img src="images/image-20220926153925963.png" style="zoom:100%" /> 3680484543d1Sopenharmony_ci 3681484543d1Sopenharmony_ci 3682484543d1Sopenharmony_ci 3683484543d1Sopenharmony_ci 3684484543d1Sopenharmony_ci<center>改造后System Trace</center> 3685484543d1Sopenharmony_ci 3686484543d1Sopenharmony_ci并行化的收益来自于: 3687484543d1Sopenharmony_ci 3688484543d1Sopenharmony_ci1) 多分支或循环并发,实现CPU前后处理和NPU的并发 3689484543d1Sopenharmony_ci 3690484543d1Sopenharmony_ci2) 子任务拆分,进一步提升并行度 3691484543d1Sopenharmony_ci 3692484543d1Sopenharmony_ci3) 基于数据流图优化CPU L2 Cache Flush频次 3693484543d1Sopenharmony_ci 3694484543d1Sopenharmony_ci4) NPU Worker Thread实时优先级调整,后续FFRT中考虑独立出XPU调度Worker来保证实时性 3695484543d1Sopenharmony_ci 3696484543d1Sopenharmony_ci5) 在未来,模型加载使用FFRT submit,模型加载内部也可以使用submit来继续拆分,能够优化整个业务的启动耗时。 3697484543d1Sopenharmony_ci 3698484543d1Sopenharmony_ci<br/> 3699484543d1Sopenharmony_ci<br/> 3700484543d1Sopenharmony_ci<hr/> 3701484543d1Sopenharmony_ci 3702484543d1Sopenharmony_ci 3703484543d1Sopenharmony_ci 3704484543d1Sopenharmony_ci# 使用建议 3705484543d1Sopenharmony_ci 3706484543d1Sopenharmony_ci## 建议1: 函数化 3707484543d1Sopenharmony_ci 3708484543d1Sopenharmony_ci**基本思想:计算过程函数化** 3709484543d1Sopenharmony_ci 3710484543d1Sopenharmony_ci* 程序过程各步骤以函数封装表达,函数满足类纯函数特性 3711484543d1Sopenharmony_ci* 无全局数据访问 3712484543d1Sopenharmony_ci* 无内部状态保留 3713484543d1Sopenharmony_ci* 通过ffrt::submit()接口以异步任务方式提交函数执行 3714484543d1Sopenharmony_ci* 将函数访问的数据对象以及访问方式在ffrt::submit()接口中的in_deps/out_deps参数表达 3715484543d1Sopenharmony_ci* 程序员通过inDeps/outDeps参数表达任务间依赖关系以保证程序执行的正确性 3716484543d1Sopenharmony_ci 3717484543d1Sopenharmony_ci> 做到纯函数的好处在于:1. 能够最大化挖掘并行度,2.避免DataRace和锁的问题 3718484543d1Sopenharmony_ci 3719484543d1Sopenharmony_ci 3720484543d1Sopenharmony_ci 3721484543d1Sopenharmony_ci**在实际中,可以根据场景放松纯函数的约束,但前提是:** 3722484543d1Sopenharmony_ci 3723484543d1Sopenharmony_ci* 确定添加的in_deps/out_deps可确保程序正确执行 3724484543d1Sopenharmony_ci* 通过FFRT提供的锁机制保护对全局变量的访问 3725484543d1Sopenharmony_ci 3726484543d1Sopenharmony_ci 3727484543d1Sopenharmony_ci 3728484543d1Sopenharmony_ci## 建议2: 注意任务粒度 3729484543d1Sopenharmony_ci 3730484543d1Sopenharmony_ci* FFRT管理和调度异步任务执行有调度开销,任务粒度(执行时间)需匹配调度开销 3731484543d1Sopenharmony_ci* 大量小粒度任务造成FFRT调度开销占比增加,性能下降,解决方法: 3732484543d1Sopenharmony_ci * 将多个小粒度任务聚合为大粒度任务一次发送给FFRT异步执行 3733484543d1Sopenharmony_ci * 同步方式执行小粒度任务,不发送给FFRT异步执行。需注意和异步任务之间的数据同步问题,在需要同步的地方插入ffrt::wait() 3734484543d1Sopenharmony_ci * 下面的例子中,fib_ffrt2会比fib_ffrt1拥有更好的性能 3735484543d1Sopenharmony_ci 3736484543d1Sopenharmony_ci ```{.cpp} 3737484543d1Sopenharmony_ci #include "ffrt.h" 3738484543d1Sopenharmony_ci void fib_ffrt1(int x, int& y) 3739484543d1Sopenharmony_ci { 3740484543d1Sopenharmony_ci if (x <= 1) { 3741484543d1Sopenharmony_ci y = x; 3742484543d1Sopenharmony_ci } else { 3743484543d1Sopenharmony_ci int y1, y2; 3744484543d1Sopenharmony_ci ffrt::submit([&] {fib_ffrt1(x - 1, y1);}, {&x}, {&y1} ); 3745484543d1Sopenharmony_ci ffrt::submit([&] {fib_ffrt1(x - 2, y2);}, {&x}, {&y2} ); 3746484543d1Sopenharmony_ci ffrt::submit([&] {y = y1 + y2;}, {&y1, &y2}, {} ); 3747484543d1Sopenharmony_ci ffrt::wait(); 3748484543d1Sopenharmony_ci } 3749484543d1Sopenharmony_ci } 3750484543d1Sopenharmony_ci 3751484543d1Sopenharmony_ci void fib_ffrt2(int x, int& y) 3752484543d1Sopenharmony_ci { 3753484543d1Sopenharmony_ci if (x <= 1) { 3754484543d1Sopenharmony_ci y = x; 3755484543d1Sopenharmony_ci } else { 3756484543d1Sopenharmony_ci int y1, y2; 3757484543d1Sopenharmony_ci ffrt::submit([&] {fib_ffrt2(x - 1, y1);}, {&x}, {&y1} ); 3758484543d1Sopenharmony_ci ffrt::submit([&] {fib_ffrt2(x - 2, y2);}, {&x}, {&y2} ); 3759484543d1Sopenharmony_ci ffrt::wait({&y1, &y2}); 3760484543d1Sopenharmony_ci y = y1 + y2; 3761484543d1Sopenharmony_ci } 3762484543d1Sopenharmony_ci } 3763484543d1Sopenharmony_ci ``` 3764484543d1Sopenharmony_ci 3765484543d1Sopenharmony_ci 3766484543d1Sopenharmony_ci 3767484543d1Sopenharmony_ci## 建议3: 数据生命周期 3768484543d1Sopenharmony_ci 3769484543d1Sopenharmony_ci* FFRT的任务提交和执行是异步的,因此需要确保任务执行时,对任务中涉及的数据的访问是有效的 3770484543d1Sopenharmony_ci* 常见问题:子任务使用父任务栈数据,当父任务先于子任务执行完成时释放栈数据,子任务产生数据访问错误 3771484543d1Sopenharmony_ci* 解决方法1:父任务中增加ffrt::wait()等待子任务完成 3772484543d1Sopenharmony_ci 3773484543d1Sopenharmony_ci```{.cpp} 3774484543d1Sopenharmony_ci#include "ffrt.h" 3775484543d1Sopenharmony_civoid fib_ffrt(int x, int& y) 3776484543d1Sopenharmony_ci{ 3777484543d1Sopenharmony_ci if (x <= 1) { 3778484543d1Sopenharmony_ci y = x; 3779484543d1Sopenharmony_ci } else { 3780484543d1Sopenharmony_ci int y1, y2; 3781484543d1Sopenharmony_ci ffrt::submit([&] {fib_ffrt(x - 1, y1);}, {&x}, {&y1} ); 3782484543d1Sopenharmony_ci ffrt::submit([&] {fib_ffrt(x - 2, y2);}, {&x}, {&y2} ); 3783484543d1Sopenharmony_ci ffrt::submit([&] {y = y1 + y2;}, {&y1, &y2}, {} ); 3784484543d1Sopenharmony_ci ffrt::wait(); // 用于保证y1 y2的生命周期 3785484543d1Sopenharmony_ci } 3786484543d1Sopenharmony_ci} 3787484543d1Sopenharmony_ci``` 3788484543d1Sopenharmony_ci 3789484543d1Sopenharmony_ci* 解决方法2:将数据由栈移到堆,手动管理生命周期 3790484543d1Sopenharmony_ci 3791484543d1Sopenharmony_ci```{.cpp} 3792484543d1Sopenharmony_ci#include "ffrt.h" 3793484543d1Sopenharmony_civoid fib_ffrt(int x, int* y) 3794484543d1Sopenharmony_ci{ 3795484543d1Sopenharmony_ci if (x <= 1) { 3796484543d1Sopenharmony_ci *y = x; 3797484543d1Sopenharmony_ci } else { 3798484543d1Sopenharmony_ci int *y1 = (int*)malloc(sizeof(int)); 3799484543d1Sopenharmony_ci int *y2 = (int*)malloc(sizeof(int)); 3800484543d1Sopenharmony_ci 3801484543d1Sopenharmony_ci ffrt::submit([=] {fib_ffrt(x - 1, y1);}, {}, {y1} ); 3802484543d1Sopenharmony_ci ffrt::submit([=] {fib_ffrt(x - 2, y2);}, {}, {y2} ); 3803484543d1Sopenharmony_ci ffrt::submit([=] {*y = *y1 + *y2; }, {y1, y2}, {} ); 3804484543d1Sopenharmony_ci ffrt::wait(); 3805484543d1Sopenharmony_ci } 3806484543d1Sopenharmony_ci} 3807484543d1Sopenharmony_ci``` 3808484543d1Sopenharmony_ci 3809484543d1Sopenharmony_ci 3810484543d1Sopenharmony_ci 3811484543d1Sopenharmony_ci## 建议4: 使用FFRT提供的替代API 3812484543d1Sopenharmony_ci 3813484543d1Sopenharmony_ci* 禁止在FFRT任务中使用系统线程库API创建线程,使用submit提交任务 3814484543d1Sopenharmony_ci* 使用FFRT提供的锁,条件变量,睡眠,IO等API代替系统线程库API 3815484543d1Sopenharmony_ci * 使用系统线程库API可能造成工作线程阻塞,引起额外性能开销 3816484543d1Sopenharmony_ci 3817484543d1Sopenharmony_ci 3818484543d1Sopenharmony_ci 3819484543d1Sopenharmony_ci## 建议5: Deadline机制 3820484543d1Sopenharmony_ci 3821484543d1Sopenharmony_ci* **必须用于具备周期/重复执行特征的处理流程** 3822484543d1Sopenharmony_ci* 在有明确时间约束和性能关键的处理流程中使用,避免滥用 3823484543d1Sopenharmony_ci* 在相对大颗粒度的处理流程中使用,例如具有16.6ms时间约束的帧处理流程 3824484543d1Sopenharmony_ci 3825484543d1Sopenharmony_ci 3826484543d1Sopenharmony_ci 3827484543d1Sopenharmony_ci## 建议6: 从线程模型迁移 3828484543d1Sopenharmony_ci 3829484543d1Sopenharmony_ci* 创建线程替代为创建FFRT任务 3830484543d1Sopenharmony_ci * 线程从逻辑上类似无in_deps的任务 3831484543d1Sopenharmony_ci* 识别线程间的依赖关系,并将其表达在任务的依赖关系in_deps/out_deps上 3832484543d1Sopenharmony_ci* 线程内计算过程分解为异步任务调用 3833484543d1Sopenharmony_ci* 通过任务依赖关系和锁机制避免并发任务数据竞争问题 3834484543d1Sopenharmony_ci 3835484543d1Sopenharmony_ci 3836484543d1Sopenharmony_ci 3837484543d1Sopenharmony_ci# 已知限制 3838484543d1Sopenharmony_ci 3839484543d1Sopenharmony_ci## thread local使用约束 3840484543d1Sopenharmony_ci* FFRT Task中使用thread local存在风险,说明如下: 3841484543d1Sopenharmony_ci* thread local变量包括C/C++语言提供的thread_local定义的变量,使用pthread_key_create创建的变量 3842484543d1Sopenharmony_ci* FFRT支持Task调度,Task调度到哪个线程是随机的,使用thread local是有风险的,这一点和所有支持Task并发调度的框架一样 3843484543d1Sopenharmony_ci* FFRT的Task默认以协程的方式运行,Task执行过程中可能发生协程退出,恢复执行时,执行该任务的线程可能发生变更 3844484543d1Sopenharmony_ci 3845484543d1Sopenharmony_ci## thread绑定类使用约束 3846484543d1Sopenharmony_ci* FFRT支持Task调度,Task调度到哪个线程是随机的,thread_idx/线程优先级/线程亲和性等与thread绑定的行为禁止在task中使用 3847484543d1Sopenharmony_ci 3848484543d1Sopenharmony_ci## recursive mutex使用约束 3849484543d1Sopenharmony_ci* FFRT Task中使用标准库的recursive mutex可能发生死锁,需要更换为FFRT提供的recursive mutex,说明如下: 3850484543d1Sopenharmony_ci* recursive mutex在lock()成功时记录调用者"执行栈"作为锁的owner,在后续lock()时会判断调用者是否为当前执行栈,如果是则返回成功,以支持在同一个执行栈中嵌套获取锁。在标准库的实现中,"执行栈"以线程标识表示。 3851484543d1Sopenharmony_ci* 在FFRT Task中使用标准库的recursive mutex,如果在外层和内层lock()之间,发生Task(协程)退出,Task恢复执行时在不同于首次调用lock()的FFRT Worker上,则判断当前线程不是owner,lock()失败,FFRT Worker挂起,后面的unlock()不会被执行,从而出现死锁。 3852484543d1Sopenharmony_ci 3853484543d1Sopenharmony_ci## FFRT对使用fork()场景的支持说明 3854484543d1Sopenharmony_ci 3855484543d1Sopenharmony_ci* 在未使用FFRT的进程中,创建子进程,支持在该子进程中使用FFRT(调用submit,timer,epoll等任务类操作)。 3856484543d1Sopenharmony_ci* 在已经使用FFRT的进程中,以fork()(无exec())方式创建子进程,不支持在该子进程中使用FFRT。 3857484543d1Sopenharmony_ci* 在已经使用FFRT的进程中,以fork()+exec()方式创建子进程,支持在子进程中使用FFRT。 3858484543d1Sopenharmony_ci 3859484543d1Sopenharmony_ci## 以动态库方式部署FFRT 3860484543d1Sopenharmony_ci 3861484543d1Sopenharmony_ci* 只能以动态库方式部署FFRT,静态库部署可能有多实例问题,例如:当多个被同一进程加载的so都以静态库的方式使用FFRT时,FFRT会被实例化成多份,其行为是未知的,这也不是FFRT设计的初衷 3862484543d1Sopenharmony_ci 3863484543d1Sopenharmony_ci## C API中初始化ffrt对象后,对象的置空与销毁由用户负责 3864484543d1Sopenharmony_ci 3865484543d1Sopenharmony_ci* 为保证较高的性能,ffrt的C API中内部不包含对对象的销毁状态的标记,用户需要合理地进行资源的释放,重复调用各个对象的destroy操作,其结果是未定义的 3866484543d1Sopenharmony_ci* 错误示例1,重复调用destroy可能造成不可预知的数据损坏 3867484543d1Sopenharmony_ci 3868484543d1Sopenharmony_ci```{.cpp} 3869484543d1Sopenharmony_ci#include "ffrt.h" 3870484543d1Sopenharmony_civoid abnormal_case_1() 3871484543d1Sopenharmony_ci{ 3872484543d1Sopenharmony_ci ffrt_task_handle_t h = ffrt_submit_h([](){printf("Test task running...\n");}, NULL, NULL, NULL, NULL, NULL); 3873484543d1Sopenharmony_ci ... 3874484543d1Sopenharmony_ci ffrt_task_handle_destroy(h); 3875484543d1Sopenharmony_ci ffrt_task_handle_destroy(h); // double free 3876484543d1Sopenharmony_ci} 3877484543d1Sopenharmony_ci``` 3878484543d1Sopenharmony_ci 3879484543d1Sopenharmony_ci* 错误示例2,未调用destroy会造成内存泄漏 3880484543d1Sopenharmony_ci 3881484543d1Sopenharmony_ci```{.cpp} 3882484543d1Sopenharmony_ci#include "ffrt.h" 3883484543d1Sopenharmony_civoid abnormal_case_2() 3884484543d1Sopenharmony_ci{ 3885484543d1Sopenharmony_ci ffrt_task_handle_t h = ffrt_submit_h([](){printf("Test task running...\n");}, NULL, NULL, NULL, NULL, NULL); 3886484543d1Sopenharmony_ci ... 3887484543d1Sopenharmony_ci // memory leak 3888484543d1Sopenharmony_ci} 3889484543d1Sopenharmony_ci``` 3890484543d1Sopenharmony_ci 3891484543d1Sopenharmony_ci* 建议示例,仅调用一次destroy,如有必要可进行置空 3892484543d1Sopenharmony_ci 3893484543d1Sopenharmony_ci```{.cpp} 3894484543d1Sopenharmony_ci#include "ffrt.h" 3895484543d1Sopenharmony_civoid normal_case() 3896484543d1Sopenharmony_ci{ 3897484543d1Sopenharmony_ci ffrt_task_handle_t h = ffrt_submit_h([](){printf("Test task running...\n");}, NULL, NULL, NULL, NULL, NULL); 3898484543d1Sopenharmony_ci ... 3899484543d1Sopenharmony_ci ffrt_task_handle_destroy(h); 3900484543d1Sopenharmony_ci h = nullptr; // if necessary 3901484543d1Sopenharmony_ci} 3902484543d1Sopenharmony_ci``` 3903484543d1Sopenharmony_ci 3904484543d1Sopenharmony_ci## 输入输出依赖数量的限制 3905484543d1Sopenharmony_ci 3906484543d1Sopenharmony_ci* 使用submit接口进行任务提交时,每个任务的输入依赖和输出依赖的数量之和不能超过8个。 3907484543d1Sopenharmony_ci* 使用submit_h接口进行任务提交时,每个任务的输入依赖和输出依赖的数量之和不能超过7个。 3908484543d1Sopenharmony_ci* 参数既作为输入依赖又作为输出依赖的时候,统计依赖数量时只统计一次,如输入依赖是{&x},输出依赖也是{&x},实际依赖的数量是1。 3909