1# Function Flow Runtime 开发指导
2
3## 场景介绍
4
5Function Flow编程模型是一种基于任务和数据驱动的并发编程模型,允许开发者通过任务及其依赖关系描述的方式进行应用开发。FFRT(Function Flow运行时)是支持Function Flow编程模型的软件运行时库,用于调度执行开发者基于Function Flow编程模型开发的应用。通过Function Flow编程模型和FFRT,开发者可专注于应用功能开发,由FFRT在运行时根据任务依赖状态和可用执行资源自动并发调度和执行任务。
6
7本文用于指导开发者基于Function Flow编程模型和FFRT实现并行编程。
8
9## 接口说明
10
11| 接口名                                                       | 描述                                                         |
12| ------------------------------------------------------------ | ------------------------------------------------------------ |
13| ffrt_condattr_init (ffrt_condattr_t* attr) | 初始化条件变量属性。 |
14| ffrt_condattr_destroy(ffrt_condattr_t* attr)  | 销毁条件变量属性。 |
15| ffrt_condattr_setclock(ffrt_condattr_t* attr, ffrt_clockid_t clock) | 设置条件变量的时钟属性。 |
16| ffrt_condattr_getclock(const ffrt_condattr_t* attr, ffrt_clockid_t* clock)        | 获取条件变量的时钟属性。              |
17| ffrt_cond_init(ffrt_cond_t* cond, const ffrt_condattr_t* attr)   | 初始化条件变量。      |
18| ffrt_cond_signal(ffrt_cond_t* cond)         | 唤醒阻塞在条件变量上的一个任务。 |
19| ffrt_cond_broadcast(ffrt_cond_t* cond) | 唤醒阻塞在条件变量上的所有任务。 |
20| ffrt_cond_wait(ffrt_cond_t* cond, ffrt_mutex_t* mutex)            | 条件变量等待函数,条件变量不满足时阻塞当前任务。 |
21| ffrt_cond_timedwait(ffrt_cond_t* cond, ffrt_mutex_t* mutex, const struct timespec* time_point)            | 条件变量超时等待函数,条件变量不满足时阻塞当前任务,超时等待返回。 |
22| ffrt_cond_destroy(ffrt_cond_t* cond)            | 销毁条件变量。 |
23| ffrt_mutex_init(ffrt_mutex_t* mutex, const ffrt_mutexattr_t* attr) | 初始化mutex。 |
24| ffrt_mutex_lock(ffrt_mutex_t* mutex)   | 获取mutex。 |
25| ffrt_mutex_unlock(ffrt_mutex_t* mutex)  | 释放mutex。 |
26| ffrt_mutex_trylock(ffrt_mutex_t* mutex)   | 尝试获取mutex。 |
27| ffrt_mutex_destroy(ffrt_mutex_t* mutex)   | 销毁mutex。 |
28| ffrt_queue_attr_init(ffrt_queue_attr_t* attr)    | 初始化串行队列属性。 |
29| ffrt_queue_attr_destroy(ffrt_queue_attr_t* attr)    | 销毁串行队列属性。 |
30| ffrt_queue_attr_set_qos(ffrt_queue_attr_t* attr, ffrt_qos_t qos)    | 设置串行队列qos属性。 |
31| ffrt_queue_attr_get_qos(const ffrt_queue_attr_t* attr)      | 获取串行队列qos属性。 |
32| ffrt_queue_create(ffrt_queue_type_t type, const char* name, const ffrt_queue_attr_t* attr)   | 创建队列。 |
33| ffrt_queue_destroy(ffrt_queue_t queue)   | 销毁队列。 |
34| ffrt_queue_submit(ffrt_queue_t queue, ffrt_function_header_t* f, const ffrt_task_attr_t* attr)   | 提交一个任务到队列中调度执行。 |
35| ffrt_queue_submit_h(ffrt_queue_t queue, ffrt_function_header_t* f, const ffrt_task_attr_t* attr)  | 提交一个任务到队列中调度执行,并返回任务句柄。 |
36| ffrt_queue_wait(ffrt_task_handle_t handle)    | 等待队列中一个任务执行完成。 |
37| ffrt_queue_cancel(ffrt_task_handle_t handle)     | 取消队列中一个任务。 |
38| ffrt_queue_attr_set_max_concurrency(ffrt_queue_attr_t* attr, const int max_concurrency)    | 设置并行队列最大并发度。 |
39| ffrt_queue_attr_get_max_concurrency(ffrt_queue_attr_t* attr)     | 获取并行队列最大并发度。 |
40| ffrt_get_main_queue()     | 获取主线程队列。 |
41| ffrt_get_current_queue()     | 获取Worker线程队列。 |
42| ffrt_usleep(uint64_t usec)   | 延迟usec微秒。 |
43| ffrt_yield(void)     | 当前任务主动放权,让其他任务有机会调度执行。 |
44| ffrt_task_attr_init(ffrt_task_attr_t* attr)     | 初始化任务属性。 |
45| ffrt_task_attr_set_name(ffrt_task_attr_t* attr, const char* name)   | 设置任务名字。 |
46| ffrt_task_attr_get_name(const ffrt_task_attr_t* attr)   | 获取任务名字。 |
47| ffrt_task_attr_destroy(ffrt_task_attr_t* attr)    | 销毁任务属性。 |
48| ffrt_task_attr_set_qos(ffrt_task_attr_t* attr, ffrt_qos_t qos)    | 设置任务qos。 |
49| ffrt_task_attr_get_qos(const ffrt_task_attr_t* attr)      | 获取任务qos。 |
50| ffrt_task_attr_set_delay(ffrt_task_attr_t* attr, uint64_t delay_us)    | 设置任务延迟时间。 |
51| ffrt_task_attr_get_delay(const ffrt_task_attr_t* attr)      | 获取任务延迟时间。 |
52| ffrt_task_attr_set_queue_priority(ffrt_task_attr_t* attr, ffrt_queue_priority_t priority)     | 设置并行队列任务优先级。 |
53| ffrt_task_attr_get_queue_priority(const ffrt_task_attr_t* attr)      | 获取并行队列任务优先级。 |
54| ffrt_this_task_get_qos()      | 获取任务qos。 |
55| ffrt_this_task_update_qos(ffrt_qos_t qos)    | 更新任务qos。 |
56| ffrt_this_task_get_id(void)    | 获取任务id。 |
57| ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_t kind)     | 申请函数执行结构的内存。 |
58| ffrt_submit_base(ffrt_function_header_t* f, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr)   | 提交任务调度执行。 |
59| ffrt_submit_h_base(ffrt_function_header_t* f, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr)    | 提交任务调度执行并返回任务句柄。 |
60| ffrt_task_handle_destroy(ffrt_task_handle_t handle)    | 销毁任务句柄。 |
61| ffrt_skip(ffrt_task_handle_t handle)     | 跳过指定任务。 |
62| ffrt_wait_deps(const ffrt_deps_t* deps)    | 等待依赖的任务完成,当前任务开始执行。 |
63| ffrt_loop_create(ffrt_queue_t queue)    | 创建loop对象。 |
64| ffrt_loop_destroy(ffrt_loop_t loop)    | 销毁loop对象。 |
65| ffrt_loop_run(ffrt_loop_t loop)    | 启动loop循环。 |
66| ffrt_loop_stop(ffrt_loop_t loop)    | 停止loop循环。 |
67| ffrt_loop_epoll_ctl(ffrt_loop_t loop, int op, int fd, uint32_t events, void* data, ffrt_poller_cb cb)    | 管理LOOP上的监听事件。 |
68| ffrt_loop_timer_start(ffrt_loop_t loop, uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat)    | 在LOOP上启动一个定时器。 |
69| ffrt_loop_timer_stop(ffrt_loop_t loop, ffrt_timer_t handle)   | 在LOOP上停止定时器。 |
70| ffrt_timer_start(ffrt_qos_t qos, uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat)   | 启动timer定时器。 |
71| ffrt_timer_stop(ffrt_qos_t qos, ffrt_timer_t handle);   | 停止timer定时器。 |
72
73## 函数介绍
74
75
76### 任务管理
77
78#### ffrt_submit_base
79
80* 该接口为ffrt动态库的导出接口,基于此可以封装出C API ffrt_submit,满足二进制兼容。
81
82##### 声明
83
84```{.c}
85const int ffrt_auto_managed_function_storage_size = 64 + sizeof(ffrt_function_header_t);
86typedef enum {
87    ffrt_function_kind_general,
88    ffrt_function_kind_queue
89} ffrt_function_kind_t;
90
91void* ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_t kind);
92
93typedef void(*ffrt_function_t)(void*);
94typedef struct {
95    ffrt_function_t exec;
96    ffrt_function_t destroy;
97    uint64_t reserve[2];
98} ffrt_function_header_t;
99
100void 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);
101```
102
103##### 参数
104
105`kind`
106
107* function子类型,用于优化内部数据结构,默认使用ffrt_function_kind_general类型。
108
109`func`
110
111* CPU Function的指针,该指针执行的数据结构,按照`ffrt_function_header_t`定义的描述了该CPU Task如何执行和销毁的函数指针,FFRT通过这两个函数指针完成Task的执行和销毁。
112
113`in_deps`
114
115* 该参数是可选的。
116* 该参数用于描述该任务的输入依赖,FFRT 通过数据的虚拟地址作为数据的Signature 来建立依赖。
117
118`out_deps`
119
120* 该参数是可选的。
121* 该参数用于描述该任务的输出依赖。
122* `注意`:该依赖值本质上是一个数值,ffrt没办法区分该值是合理的还是不合理的,会假定输入的值是合理的进行处理;但不建议采用NULL,1, 2 等值来建立依赖关系,建议采用实际的内存地址,因为前者使用不当会建立起不必要的依赖,影响并发。
123
124`attr`
125
126* 该参数是可选的。
127* 该参数用于描述Task 的属性,比如qos 等,详见 [ffrt_task_attr_t](#ffrt_task_attr_t)章节。
128
129##### 返回值
130
131* 不涉及。
132
133##### 描述
134* 建议用户对ffrt_submit_base进行封装后调用,具体可参考样例。
135* **ffrt_submit_base作为底层能力,使用时需要满足以下限制:**
136  * ffrt_submit_base入参中的func指针只能通过ffrt_alloc_auto_managed_function_storage_base申请,且二者的调用需一一对应。
137  * ffrt_alloc_auto_managed_function_storage_base申请的内存为ffrt_auto_managed_function_storage_size字节,其生命周期归ffrt管理,在该task结束时,由FFRT自动释放,用户无需释放。
138* ffrt_function_header_t 中定义了两个函数指针:
139  * exec:用于描述该Task如何被执行,当FFRT需要执行该Task时由FFRT调用。
140  * destroy:用于描述该Task如何被销毁,当FFRT需要销毁该Task时由FFRT调用。
141
142##### 样例
143
144
145```{.c}
146template<class T>
147struct function {
148    template<class CT>
149    function(ffrt_function_header_t h, CT&& c) : header(h), closure(std::forward<CT>(c)) {}
150    ffrt_function_header_t header;
151    T closure;
152};
153
154template<class T>
155void exec_function_wrapper(void* t)
156{
157    auto f = (function<std::decay_t<T>>*)t;
158    f->closure();
159}
160
161template<class T>
162void destroy_function_wrapper(void* t)
163{
164    auto f = (function<std::decay_t<T>>*)t;
165    f->closure = nullptr;
166}
167
168template<class T>
169inline ffrt_function_header_t* create_function_wrapper(T&& func)
170{
171    using function_type = function<std::decay_t<T>>;
172    static_assert(sizeof(function_type) <= ffrt_auto_managed_function_storage_size,
173        "size of function must be less than ffrt_auto_managed_function_storage_size");
174
175    auto p = ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general);
176    auto f = new (p) function_type(
177        {exec_function_wrapper<T>, destroy_function_wrapper<T>},
178        std::forward<T>(func));
179    return (ffrt_function_header_t*)f;
180}
181
182static inline void submit(std::function<void()>&& func)
183{
184    return ffrt_submit_base(create_function_wrapper(std::move(func)), NULL, NULL, NULL);
185}
186```
187
188#### ffrt_wait
189
190<hr/>
191* 同步等待,与ffrt_submit_base 配合使用。
192* 等待指定的数据被生产完成,或等待当前任务的所有子任务完成,在不满足条件之前,当前的执行上下文被suspend,在满足条件后恢复执行。
193
194##### 声明
195
196```{.c}
197void ffrt_wait_deps(ffrt_deps_t* deps);
198void ffrt_wait();
199```
200
201##### 参数
202
203`deps`
204
205* 需要等待被生产完成的数据的虚拟地址,这些地址可能作为某些任务在submit 时的out_deps,该依赖的生成见ffrt_deps_t章节,空指针表示无依赖。
206
207##### 返回值
208
209* 不涉及。
210
211##### 描述
212* ffrt_wait_deps(deps) 用于等待deps指代的数据被生产完成才能执行后面的代码。
213* ffrt_wait() 用于等待当前上下文提交的所有子任务(`注意:不包括孙任务和下级子任务`)都完成才能执行后面的代码。
214* 该接口支持在FFRT task 内部调用,也支持在FFRT task 外部调用。
215* 在FFRT task 外部调用的wait 是OS 能够感知的等待,相对于FFRT task 内部调用的wait 是更加昂贵的,因此我们希望尽可能让更多的wait 发生在FFRT task 内部 ,而不是FFRT task 外部。
216
217##### 样例
218
219**recursive fibonacci**
220
221串行版的fibonacci 可以实现为:
222
223```{.c}
224#include <stdio.h>
225
226void fib(int x, int* y) {
227    if (x <= 1) {
228        *y = x;
229    } else {
230        int y1, y2;
231        fib(x - 1, &y1);
232        fib(x - 2, &y2);
233        *y = y1 + y2;
234    }
235}
236int main(int narg, char** argv)
237{
238    int r;
239    fib(10, &r);
240    printf("fibonacci 10: %d\n", r);
241    return 0;
242}
243```
244
245若要使用 FFRT 实现并行(注,对于单纯的fibonacci,单个 Task 的计算量极小,不具有并行加速的意义,但这种调用pattern 对并行编程模型的灵活性考验是非常高的),其中1种可行的实现为:
246
247```{.c}
248#include <stdio.h>
249#include "ffrt.h"  //包含所有ffrt涉及的头文件
250
251typedef struct {
252    int x;
253    int* y;
254} fib_ffrt_s;
255
256typedef struct {
257    ffrt_function_header_t header;
258    ffrt_function_t func;
259    ffrt_function_t after_func;
260    void* arg;
261} c_function;
262
263static void ffrt_exec_function_wrapper(void* t)
264{
265    c_function* f = (c_function*)t;
266    if (f->func) {
267        f->func(f->arg);
268    }
269}
270
271static void ffrt_destroy_function_wrapper(void* t)
272{
273    c_function* f = (c_function*)t;
274    if (f->after_func) {
275        f->after_func(f->arg);
276    }
277}
278
279#define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1])
280static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func,
281    const ffrt_function_t after_func, void* arg)
282{
283    FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size,
284        size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size);
285    c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general);
286    f->header.exec = ffrt_exec_function_wrapper;
287    f->header.destroy = ffrt_destroy_function_wrapper;
288    f->func = func;
289    f->after_func = after_func;
290    f->arg = arg;
291    return (ffrt_function_header_t*)f;
292}
293
294static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func,
295    void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr)
296{
297    ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr);
298}
299
300void fib_ffrt(void* arg)
301{
302    fib_ffrt_s* p = (fib_ffrt_s*)arg;
303    int x = p->x;
304    int* y = p->y;
305
306    if (x <= 1) {
307        *y = x;
308    } else {
309        int y1, y2;
310        fib_ffrt_s s1 = {x - 1, &y1};
311        fib_ffrt_s s2 = {x - 2, &y2};
312        const std::vector<ffrt_dependence_t> dx_deps = {{ffrt_dependence_data, &x}};
313        ffrt_deps_t dx{static_cast<uint32_t>(dx_deps.size()), dx_deps.data()};
314        const std::vector<ffrt_dependence_t> dy1_deps = {{ffrt_dependence_data, &y1}};
315        ffrt_deps_t dy1{static_cast<uint32_t>(dy1_deps.size()), dy1_deps.data()};
316        const std::vector<ffrt_dependence_t> dy2_deps = {{ffrt_dependence_data, &y2}};
317        ffrt_deps_t dy2{static_cast<uint32_t>(dy2_deps.size()), dy2_deps.data()};
318        const std::vector<ffrt_dependence_t> dy12_deps = {{ffrt_dependence_data, &y1}, {ffrt_dependence_data, &y2}};
319        ffrt_deps_t dy12{static_cast<uint32_t>(dy12_deps.size()), dy12_deps.data()};
320        ffrt_submit_c(fib_ffrt, NULL, &s1, &dx, &dy1, NULL);
321        ffrt_submit_c(fib_ffrt, NULL, &s2, &dx, &dy2, NULL);
322        ffrt_wait_deps(&dy12);
323        *y = y1 + y2;
324    }
325}
326
327int main(int narg, char** argv)
328{
329    int r;
330    fib_ffrt_s s = {10, &r};
331    const std::vector<ffrt_dependence_t> dr_deps = {{ffrt_dependence_data, &r}};
332    ffrt_deps_t dr{static_cast<uint32_t>(dr_deps.size()), dr_deps.data()};
333    ffrt_submit_c(fib_ffrt, NULL, &s, NULL, &dr, NULL);
334    ffrt_wait_deps(&dr);
335    printf("fibonacci 10: %d\n", r);
336    return 0;
337}
338```
339
340`解析`:
341
3421)   将fibonacci (x-1)和fibonacci (x-2) 作为2个Task 提交给FFRT,在两个Task 完成之后将结果累加;
343
3442)   虽然单个Task 只能拆分成2个SubTask 但是子Task 可以继续拆分,因此,整个计算图的并行度是非常高的,Task 之间在FFRT 内部形成了一颗调用树;
345
346<img src="figures/ffrtfigure2.png" style="zoom:100%" />
347
348> 以上实现,因为需要用户显式管理数据生命周期和函数入参打包两个因素,所以使得代码实现异常复杂。
349
350
351
352#### ffrt_deps_t
353
354* C API中对依赖数组的抽象,逻辑上等同于C++ API中的`std::vector<void*>`
355
356##### 声明
357
358```{.c}
359typedef enum {
360    ffrt_dependence_data,
361    ffrt_dependence_task,
362} ffrt_dependence_type_t;
363
364typedef struct {
365    ffrt_dependence_type_t type;
366    const void* ptr;
367} ffrt_dependence_t;
368
369typedef struct {
370    uint32_t len;
371    const ffrt_dependence_t* items;
372} ffrt_deps_t;
373```
374
375##### 参数
376
377`len`
378
379* 所依赖的Signature的个数,取值大于等于0。
380
381`item`
382
383* len个Signature的起始地址指针。
384
385`type`
386
387* 当前依赖为数据依赖还是任务依赖。
388
389`ptr`
390
391* 所依赖对应Signature内容的实际地址。
392
393##### 返回值
394
395* 不涉及。
396
397##### 描述
398
399* item为len个Signature的起始指针,该指针可以指向堆空间,也可以指向栈空间,但是要求分配的空间大于等于len * sizeof(ffrt_dependence_t)。
400
401##### 样例
402
403* 创建数据依赖或者任务依赖:
404
405```{.c}
406// 创建数据依赖的ffrt_deps_t
407int x = 0;
408const std::vector<ffrt_dependence_t> in_deps = {{ffrt_dependence_data, &x}};
409ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.data()};
410
411// 提交某个返回handle任务
412ffrt_task_handle_t task = ffrt_submit_h_base(
413        ffrt_create_function_wrapper(OnePlusForTest, NULL, &a), NULL, NULL, &attr);
414// 创建任务依赖的ffrt_deps_t
415const std::vector<ffrt_dependence_t> wait_deps = {{ffrt_dependence_task, task}};
416ffrt_deps_t wait{static_cast<uint32_t>(wait_deps.size()), wait_deps.data()};
417```
418
419#### ffrt_task_attr_t
420
421<hr/>
422* 定义task 的属性的辅助类,与ffrt_submit_base 配合使用。
423
424##### 声明
425
426```{.c}
427typedef enum {
428    ffrt_qos_inherent = -1,
429    ffrt_qos_background,
430    ffrt_qos_utility,
431    ffrt_qos_default,
432    ffrt_qos_user_initiated,
433} ffrt_qos_default_t;
434
435typedef int ffrt_qos_t;
436
437typedef struct {
438    uint32_t storage[(ffrt_task_attr_storage_size + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
439} ffrt_task_attr_t;
440typedef void* ffrt_task_handle_t;
441
442int ffrt_task_attr_init(ffrt_task_attr_t* attr);
443void ffrt_task_attr_destroy(ffrt_task_attr_t* attr);
444void ffrt_task_attr_set_qos(ffrt_task_attr_t* attr, ffrt_qos_t qos);
445ffrt_qos_t ffrt_task_attr_get_qos(const ffrt_task_attr_t* attr);
446void ffrt_task_attr_set_name(ffrt_task_attr_t* attr, const char* name);
447const char* ffrt_task_attr_get_name(const ffrt_task_attr_t* attr);
448void ffrt_task_attr_set_delay(ffrt_task_attr_t* attr, uint64_t delay_us);
449uint64_t ffrt_task_attr_get_delay(const ffrt_task_attr_t* attr);
450```
451
452##### 参数
453
454`attr`
455
456* 创建的tasks属性的句柄。
457
458`qos`
459
460* qos 设定的枚举类型。
461* inherent 是一个qos 设定策略,代表即将ffrt_submit 的task 的qos 继承当前task 的qos。
462
463`delay_us`
464
465* 任务延迟执行的时间,单位为us。
466
467##### 返回值
468
469* 不涉及。
470
471##### 描述
472* `attr`所传递的内容会在ffrt_submit内部完成取存,ffrt_submit返回后用户即可销毁。
473* 约定:
474  * 在submit 时,如果不通过task_attr 设定qos,那么默认该提交的task的qos 为`ffrt_qos_default`。
475  * 在submit 时,如果通过task_attr 设定qos 为`ffrt_qos_inherent`,表示将该提交的task 的qos 与当前task 的qos 相同,在FFRT task 外部提交的属性为`ffrt_qos_inherent` 的task,其qos 为`ffrt_qos_default`。
476  * 其他情况下,该提交的task 的qos 被设定为指定的值。
477* ffrt_task_attr_t对象的置空和销毁由用户完成,对同一个ffrt_task_attr_t仅能调用一次`ffrt_task_attr_destroy`,重复对同一个ffrt_task_attr_t调用`ffrt_task_attr_destroy`,其行为是未定义的。
478* 在`ffrt_task_attr_destroy`之后再对task_attr进行访问,其行为是未定义的。
479
480##### 样例
481
482* 提交一个qos 级别为background 的任务:
483
484```{.c}
485#include <stdio.h>
486#include "ffrt.h"
487
488void my_print(void* arg)
489{
490    printf("hello ffrt\n");
491}
492
493typedef struct {
494    ffrt_function_header_t header;
495    ffrt_function_t func;
496    ffrt_function_t after_func;
497    void* arg;
498} c_function;
499
500static void ffrt_exec_function_wrapper(void* t)
501{
502    c_function* f = (c_function*)t;
503    if (f->func) {
504        f->func(f->arg);
505    }
506}
507
508static void ffrt_destroy_function_wrapper(void* t)
509{
510    c_function* f = (c_function*)t;
511    if (f->after_func) {
512        f->after_func(f->arg);
513    }
514}
515
516#define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1])
517static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func,
518    const ffrt_function_t after_func, void* arg)
519{
520    FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size,
521        size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size);
522    c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general);
523    f->header.exec = ffrt_exec_function_wrapper;
524    f->header.destroy = ffrt_destroy_function_wrapper;
525    f->func = func;
526    f->after_func = after_func;
527    f->arg = arg;
528    return (ffrt_function_header_t*)f;
529}
530
531static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func,
532    void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr)
533{
534    ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr);
535}
536
537int main(int narg, char** argv)
538{
539    ffrt_task_attr_t attr;
540    ffrt_task_attr_init(&attr);
541    ffrt_task_attr_set_qos(&attr, ffrt_qos_background);
542    ffrt_task_attr_set_delay(&attr, 10000);
543    ffrt_submit_c(my_print, NULL, NULL, NULL, NULL, &attr);
544    ffrt_task_attr_destroy(&attr);
545    ffrt_wait();
546    return 0;
547}
548```
549
550#### ffrt_submit_h_base
551
552<hr/>
553
554* 向调度器提交一个task,与ffrt_submit_base 的差别在于返回task 的句柄,该句柄可以用于建立task 之间的依赖,或用于在wait 语句中实现同步。
555
556##### 声明
557
558```{.c}
559typedef void* ffrt_task_handle_t;
560
561ffrt_task_handle_t ffrt_submit_h_base(ffrt_function_t func, void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr);
562void ffrt_task_handle_destroy(ffrt_task_handle_t handle);
563```
564
565##### 参数
566
567`func`
568
569* CPU Function的指针,该指针执行的数据结构,按照`ffrt_function_header_t`定义的描述了该CPU Task如何执行和销毁的函数指针,FFRT通过这两个函数指针完成Task的执行和销毁。
570
571`in_deps`
572
573* 该参数是可选的。
574* 该参数用于描述该任务的输入依赖,FFRT 通过数据的虚拟地址作为数据的Signature 来建立依赖。
575
576`out_deps`
577
578* 该参数是可选的。
579* 该参数用于描述该任务的输出依赖。
580* `注意`:该依赖值本质上是一个数值,ffrt没办法区分该值是合理还是不合理的,会假定输入的值是合理的进行处理;但不建议采用NULL,1, 2 等值来建立依赖关系,建议采用实际的内存地址,因为前者使用不当会建立起不必要的依赖,影响并发。
581
582`attr`
583
584* 该参数是可选的。
585* 该参数用于描述Task 的属性,比如qos 等,详见 [ffrt_task_attr_t](#ffrt_task_attr_t)章节。
586
587##### 返回值
588
589* task 的句柄,该句柄可以用于建立task 之间的依赖,或用于在wait 语句中实现同步。
590
591##### 描述
592
593* **C API中的ffrt_task_handle_t需要用户调用`ffrt_task_handle_destroy`显式销毁。**
594* C API中的task_handle_t对象的置空和销毁由用户完成,对同一个ffrt_task_handle_t仅能调用一次`ffrt_task_handle_destroy`,重复对同一个ffrt_task_handle_t调用`ffrt_task_handle_destroy`,其行为是未定义的。
595* 在`ffrt_task_handle_destroy`之后再对ffrt_task_handle_t进行访问,其行为是未定义的。
596
597##### 样例
598
599```{.c}
600#include <stdio.h>
601#include "ffrt.h"
602
603void func0(void* arg)
604{
605    printf("hello ");
606}
607
608void func1(void* arg)
609{
610    (*(int*)arg)++;
611}
612
613void func2(void* arg)
614{
615    printf("world, x = %d\n", *(int*)arg);
616}
617
618void func3(void* arg)
619{
620    printf("handle wait");
621    (*(int*)arg)++;
622}
623
624typedef struct {
625    ffrt_function_header_t header;
626    ffrt_function_t func;
627    ffrt_function_t after_func;
628    void* arg;
629} c_function;
630
631static void ffrt_exec_function_wrapper(void* t)
632{
633    c_function* f = (c_function*)t;
634    if (f->func) {
635        f->func(f->arg);
636    }
637}
638
639static void ffrt_destroy_function_wrapper(void* t)
640{
641    c_function* f = (c_function*)t;
642    if (f->after_func) {
643        f->after_func(f->arg);
644    }
645}
646
647#define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1])
648static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func,
649    const ffrt_function_t after_func, void* arg)
650{
651    FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size,
652        size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size);
653    c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general);
654    f->header.exec = ffrt_exec_function_wrapper;
655    f->header.destroy = ffrt_destroy_function_wrapper;
656    f->func = func;
657    f->after_func = after_func;
658    f->arg = arg;
659    return (ffrt_function_header_t*)f;
660}
661
662static inline ffrt_task_handle_t ffrt_submit_h_c(ffrt_function_t func, const ffrt_function_t after_func,
663    void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr)
664{
665    return ffrt_submit_h_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr);
666}
667
668static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func,
669    void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr)
670{
671    ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr);
672}
673
674
675int main(int narg, char** argv)
676{
677    // handle work with submit
678    ffrt_task_handle_t h = ffrt_submit_h_c(func0, NULL, NULL, NULL, NULL, NULL); // not need some data in this task
679    int x = 1;
680    const std::vector<ffrt_dependence_t> in_deps = {{ffrt_dependence_data, &x}};
681    ffrt_deps_t d2{static_cast<uint32_t>(in_deps.size()), in_deps.data()};
682
683    const std::vector<ffrt_dependence_t> out_deps = {{ffrt_dependence_data, &x}};
684    ffrt_deps_t d1{static_cast<uint32_t>(out_deps.size()), out_deps.data()};
685
686    ffrt_submit_c(func1, NULL, &x, NULL, &d1, NULL);
687    ffrt_submit_c(func2, NULL, &x, &d2, NULL, NULL); // this task depend x and h
688    ffrt_task_handle_destroy(h);
689
690    // handle work with wait
691    ffrt_task_handle_t h2 = ffrt_submit_h_c(func3, NULL, &x, NULL, NULL, NULL);
692
693    const std::vector<ffrt_dependence_t> wait_deps = {{ffrt_dependence_task, h2}};
694    ffrt_deps_t d3{static_cast<uint32_t>(wait_deps.size()), wait_deps.data()};
695    ffrt_wait_deps(&d3);
696    ffrt_task_handle_destroy(h2);
697    printf("x = %d", x);
698    ffrt_wait();
699    return 0;
700}
701```
702
703* 预期的输出为:
704
705```
706hello
707handle wait
708x = 2
709world, x = 3
710```
711
712
713
714#### ffrt_this_task_get_id
715
716<hr/>
717
718* 返回当前task的id标识,更多使用用于维测(原因是task name可能重名)。
719
720##### 声明
721
722```{.c}
723uint64_t ffrt_this_task_get_id();
724```
725
726##### 参数
727
728* 不涉及。
729
730##### 返回值
731
732* 当前task的id。
733
734##### 描述
735
736* 该接口在task内部调用将返回当前task的id标识,在task外部调用将返回0。
737* 可以基于该接口在task外部调用返回0的特性来区分函数是运行在FFRT 工作线程上还是非FFRT工作线程上。
738* task id为从1开始编码,每提交一个task便增加1,被设计成64bit,即便是每秒百万次提交,也需要292471.2年才会发生翻转。
739
740##### 样例
741
742* 忽略。
743
744#### ffrt_this_task_update_qos
745
746<hr/>
747
748* 更新当前正在执行的task的qos等级。
749
750##### 声明
751
752```{.c}
753int ffrt_this_task_update_qos(ffrt_qos_t qos);
754```
755
756##### 参数
757
758* `qos` 新的qos等级。
759
760##### 返回值
761
762* 0表示成功,非0表示失败。
763
764##### 描述
765
766* 该接口对当前task的qos调整会立即生效。
767* 如果新设定的qos与当前的qos不一致,则会block当前task的执行,再按照新的qos恢复执行。
768* 如果新设定的qos与当前的qos一致,则接口会立即返回0,不做任何处理。
769* **如果在非task内部调用该接口,则返回非0值,用户可以选择忽略或其他处理。**
770
771##### 样例
772
773* 忽略。
774
775#### ffrt_this_task_get_qos
776
777<hr/>
778
779* 获取当前正在执行的task的qos等级。
780
781##### 声明
782
783```{.c}
784ffrt_qos_t ffrt_this_task_get_qos();
785```
786
787##### 参数
788
789* NA
790
791##### 返回值
792
793* `qos` 任务qos等级。
794
795##### 描述
796
797* 获取当前正在执行的task的qos等级。
798
799##### 样例
800
801```{.c}
802#include "ffrt.h"
803
804int main(int narg, char** argv)
805{
806    static int x = 0;
807    int* xf = &x;
808    void* data = xf;
809    uint64_t timeout1 = 20;
810
811    ffrt::submit([=]() {
812    ffrt_qos_t taskQos = ffrt_this_task_get_qos();
813    ffrt_timer_cb cb;
814    ffrt_timer_start(taskQos, timeout1, data, cb, false);
815    ffrt_usleep(200);
816    }, {}, {});
817    ffrt::wait();
818    return 0;
819}
820
821```
822
823### 串行队列
824<hr />
825* 串行队列基于FFRT协程调度模型,实现了消息队列功能。串行任务执行在FFRT Workers上,用户无需维护一个专用的线程,拥有更轻量级的调度开销。
826
827#### ffrt_queue_attr_t
828
829##### 声明
830```{.c}
831typedef struct {
832    uint32_t storage[(ffrt_queue_attr_storage_size + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
833} ffrt_queue_attr_t;
834
835int ffrt_queue_attr_init(ffrt_queue_attr_t* attr);
836void ffrt_queue_attr_destroy(ffrt_queue_attr_t* attr);
837```
838
839##### 参数
840
841`attr`
842* 该参数是指向未初始化的ffrt_queue_attr_t。
843
844##### 返回值
845* 若成功返回0,否则返回-1。
846
847##### 描述
848* ffrt_queue_attr_t用于创建ffrt_queue_t且不单独使用,因此必须在创建队列前先创建好队列属性。
849* ffrt_queue_attr_t对象的置空和销毁由用户完成,对同一个ffrt_queue_attr_t仅能调用一次`ffrt_queue_attr_destroy`,重复对同一个ffrt_queue_attr_t调用`ffrt_queue_attr_destroy`,其行为是未定义的。
850* 在`ffrt_queue_attr_destroy`之后再对ffrt_queue_attr_t进行访问,其行为是未定义的。
851
852##### 样例
853参考ffrt_queue_t章节的样例。
854
855#### ffrt_queue_t
856
857##### 声明
858```{.c}
859typedef enum { ffrt_queue_serial, ffrt_queue_concurrent, ffrt_queue_max } ffrt_queue_type_t;
860typedef void* ffrt_queue_t;
861
862ffrt_queue_t ffrt_queue_create(ffrt_queue_type_t type, const char* name, const ffrt_queue_attr_t* attr)
863void ffrt_queue_destroy(ffrt_queue_t queue)
864```
865
866##### 参数
867
868`type`
869* 该参数用于描述创建的队列类型。
870
871`name`
872* 该参数用于描述创建队列的名字。
873
874`attr`
875* 该参数用于描述queue的属性,详见ffrt_queue_attr_t章节。
876
877##### 返回值
878* 若成功则返回新创建的队列,否则返回空指针。
879
880##### 描述
881* 提交至该队列的任务将按照顺序执行,如果某个提交的任务中发生阻塞,则无法保证该任务的执行顺序。
882* ffrt_queue_t对象的置空和销毁由用户完成,对同一个ffrt_queue_t仅能调用一次`ffrt_queue_destroy`,重复对同一个ffrt_queue_t调用`ffrt_queue_destroy`,其行为是未定义的。
883* 在`ffrt_queue_destroy`之后再对ffrt_queue_t进行访问,其行为是未定义的。
884
885##### 样例
886```
887#include <stdio.h>
888#include "ffrt.h"
889
890using namespace std;
891
892template<class T>
893struct Function {
894    ffrt_function_header_t header;
895    T closure;
896};
897
898template<class T>
899void ExecFunctionWrapper(void* t)
900{
901    auto f = reinterpret_cast<Function<std::decay_t<T>>*>(t);
902    f->closure();
903}
904
905template<class T>
906void DestroyFunctionWrapper(void* t)
907{
908    auto f = reinterpret_cast<Function<std::decay_t<T>>*>(t);
909    f = nullptr;
910}
911
912template<class T>
913static inline ffrt_function_header_t* create_function_wrapper(T&& func,
914    ffrt_function_kind_t kind = ffrt_function_kind_general)
915{
916    using function_type = Function<std::decay_t<T>>;
917    auto p = ffrt_alloc_auto_managed_function_storage_base(kind);
918    auto f = new (p)function_type;
919    f->header.exec = ExecFunctionWrapper<T>;
920    f->header.destroy = DestroyFunctionWrapper<T>;
921    f->closure = std::forward<T>(func);
922    return reinterpret_cast<ffrt_function_header_t*>(f);
923}
924
925int main(int narg, char** argv)
926{
927    ffrt_queue_attr_t queue_attr;
928    (void)ffrt_queue_attr_init(&queue_attr);
929    ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_serial, "test_queue", &queue_attr);
930    std::function<void()>&& queueFunc = [] () {printf("Task done.\n");};
931    ffrt_function_header_t* queueFunc_t = create_function_wrapper((queueFunc), ffrt_function_kind_queue);
932    ffrt_queue_submit(queue_handle, queueFunc_t, nullptr);
933
934    ffrt_queue_attr_destroy(&queue_attr);
935    ffrt_queue_destroy(queue_handle);
936}
937```
938
939#### ffrt_get_main_queue
940<hr/>
941获取主线程任务队列。
942
943##### 声明
944```{.c}
945ffrt_queue_t ffrt_get_main_queue();
946```
947
948##### 参数
949
950NA
951
952##### 返回值
953
954主线程队列。
955
956##### 描述
957获取主线程队列,用于FFRT线程与主线程通信。
958
959##### 样例
960```{.c}
961本用例需要在鸿蒙系统中执行
962#include "ffrt.h"
963
964inline void OnePlusForTest(void* data)
965{
966    *(int*)data += 1;
967}
968
969int main(int narg, char** argv)
970{
971    ffrt::queue *serialQueue = new ffrt::queue("ffrt_normal_queue", {});
972    ffrt_queue_t mainQueue = ffrt_get_main_queue();
973    ffrt_task_attr_t attr;
974    ffrt_task_attr_init(&attr);
975    ffrt_task_attr_set_qos(&attr, ffrt_qos_user_initiated);
976    int result = 0;
977    std::function<void()>&& basicFunc = [&result]() {
978        OnePlusForTest(static_cast<void*>(&result));
979        OnePlusForTest(static_cast<void*>(&result));
980        ffrt_usleep(3000);
981    };
982
983    ffrt::task_handle handle = serialQueue->submit_h(
984        [&] {
985            result = result + 1;
986            ffrt_queue_submit(mainQueue, ffrt::create_function_wrapper(basicFunc, ffrt_function_kind_queue),
987                            &attr);
988        },
989        ffrt::task_attr().qos(3).name("ffrt main_queue."));
990
991    serialQueue->wait(handle);
992    return 0;
993}
994```
995
996
997#### ffrt_get_current_queue
998
999获取ArkTS Worker线程任务队列。
1000
1001##### 声明
1002```{.c}
1003ffrt_queue_t ffrt_get_current_queue();
1004```
1005
1006##### 参数
1007
1008NA
1009
1010##### 返回值
1011
1012ArkTS Worker线程任务队列。
1013
1014##### 描述
1015获取ArkTS Worker线程队列,用于FFRT线程与ArkTS Worker线程通信。
1016
1017##### 样例
1018```{.c}
1019//本用例需要在鸿蒙系统中执行
1020#include "ffrt.h"
1021
1022inline void OnePlusForTest(void* data)
1023{
1024    *(int*)data += 1;
1025}
1026
1027int main(int narg, char** argv)
1028{
1029    ffrt::queue *serialQueue = new ffrt::queue("ffrt_normal_queue", {});
1030    ffrt_queue_t currentQueue = ffrt_get_current_queue();
1031    ffrt_task_attr_t attr;
1032    ffrt_task_attr_init(&attr);
1033    ffrt_task_attr_set_qos(&attr, ffrt_qos_user_initiated);
1034    int result = 0;
1035    std::function<void()>&& basicFunc = [&result]() {
1036        OnePlusForTest(static_cast<void*>(&result));
1037        OnePlusForTest(static_cast<void*>(&result));
1038        ffrt_usleep(3000);
1039    };
1040
1041    ffrt::task_handle handle = serialQueue->submit_h(
1042        [&] {
1043            result = result + 1;
1044            ffrt_queue_submit(currentQueue, ffrt::create_function_wrapper(basicFunc, ffrt_function_kind_queue),
1045                            &attr);
1046        },
1047        ffrt::task_attr().qos(3).name("ffrt current_queue."));
1048
1049    serialQueue->wait(handle);
1050    return 0;
1051}
1052```
1053
1054
1055### 并行队列
1056<hr />
1057FFRT支持并行队列,并支持设置并行队列的并发度和任务优先级。
1058
1059#### ffrt_queue_attr_set_max_concurrency
1060<hr/>
1061FFRT并行队列设置最大并发度。
1062
1063##### 声明
1064```{.c}
1065void ffrt_queue_attr_set_max_concurrency(ffrt_queue_attr_t* attr, const int max_concurrency);
1066```
1067
1068##### 参数
1069
1070`attr`
1071
1072* 该参数用于描述queue的属性,详见ffrt_queue_attr_t章节。
1073
1074`max_concurrency`
1075
1076* 最大并发度,当用户设置小于等于0时,并发度是1。
1077
1078##### 返回值
1079
1080NA
1081
1082##### 描述
1083FFRT并行队列设置最大并发度,需要注意的是,当设置很大的并发度时,如100,受限于硬件能力,最终的并发度不会达到100。
1084
1085##### 样例
1086```{.c}
1087#include "ffrt.h"
1088
1089int main(int narg, char** argv)
1090{
1091    ffrt_queue_attr_t queue_attr;
1092    (void)ffrt_queue_attr_init(&queue_attr);
1093    uint64_t concurrency = 4;
1094    ffrt_queue_attr_set_max_concurrency(&queue_attr, concurrency);
1095    concurrency = ffrt_queue_attr_get_max_concurrency(&queue_attr);
1096    ffrt_queue_attr_destroy(&queue_attr);
1097    printf("concurrency=%lu\n", concurrency);
1098    return 0;
1099}
1100```
1101
1102预期输出为:
1103
1104```
1105concurrency=4
1106```
1107
1108#### ffrt_queue_attr_get_max_concurrency
1109<hr/>
1110获取FFRT并行队列设置的最大并发度。
1111
1112##### 声明
1113```{.c}
1114int ffrt_queue_attr_get_max_concurrency(const ffrt_queue_attr_t* attr);
1115```
1116
1117##### 参数
1118
1119`attr`
1120
1121* 该参数用于描述queue的属性,详见ffrt_queue_attr_t章节。
1122
1123##### 返回值
1124
1125用户设置的最大并发度。
1126
1127##### 描述
1128获取FFRT并行队列设置的最大并发度。
1129
1130##### 样例
1131```{.c}
1132#include "ffrt.h"
1133
1134int main(int narg, char** argv)
1135{
1136    ffrt_queue_attr_t queue_attr;
1137    (void)ffrt_queue_attr_init(&queue_attr);
1138    uint64_t concurrency = 4;
1139    ffrt_queue_attr_set_max_concurrency(&queue_attr, concurrency);
1140    concurrency = ffrt_queue_attr_get_max_concurrency(&queue_attr);
1141    ffrt_queue_attr_destroy(&queue_attr);
1142    printf("concurrency=%lu\n", concurrency);
1143    return 0;
1144}
1145```
1146
1147预期输出为:
1148
1149```
1150concurrency=4
1151```
1152
1153#### ffrt_task_attr_set_queue_priority
1154<hr/>
1155设置并行队列任务优先级。
1156
1157##### 声明
1158```{.c}
1159/* 任务优先级 */
1160typedef enum {
1161ffrt_queue_priority_immediate = 0,
1162ffrt_queue_priority_high,
1163ffrt_queue_priority_low,
1164ffrt_queue_priority_idle,
1165} ffrt_queue_priority_t;
1166
1167void ffrt_task_attr_set_queue_priority(ffrt_task_attr_t* attr, ffrt_queue_priority_t priority);
1168```
1169
1170##### 参数
1171
1172`attr`
1173
1174* 该参数用于描述task的属性,详见ffrt_task_attr_t章节。
1175
1176`priority`
1177
1178* 任务优先级,支持四种优先级,定义参考ffrt_queue_priority_t。
1179
1180##### 返回值
1181
1182NA
1183
1184##### 描述
1185设置并行队列任务优先级。
1186
1187##### 样例
1188```{.c}
1189#include "ffrt.h"
1190
1191int main(int narg, char** argv)
1192{
1193    ffrt_task_attr_t task_attr;
1194    (void)ffrt_task_attr_init(&task_attr);
1195    ffrt_queue_priority_t priority = ffrt_queue_priority_idle;
1196    ffrt_task_attr_set_queue_priority(&task_attr, priority);
1197    priority = ffrt_task_attr_get_queue_priority(&task_attr);
1198    ffrt_task_attr_destroy(&task_attr);
1199    printf("priority=%d\n", priority);
1200    return 0;
1201}
1202```
1203
1204预期输出为:
1205
1206```
1207priority=3
1208```
1209
1210#### ffrt_task_attr_get_queue_priority
1211<hr/>
1212获取开发者设置的并行队列任务优先级。
1213
1214##### 声明
1215```{.c}
1216ffrt_queue_priority_t ffrt_task_attr_get_queue_priority(const ffrt_task_attr_t* attr);
1217```
1218
1219##### 参数
1220
1221`attr`
1222
1223* 该参数用于描述queue的属性,详见ffrt_queue_attr_t章节。
1224
1225##### 返回值
1226
1227任务优先级。
1228
1229##### 描述
1230获取开发者设置的并行队列任务优先级。
1231
1232##### 样例
1233```{.c}
1234#include "ffrt.h"
1235
1236int main(int narg, char** argv)
1237{
1238    ffrt_task_attr_t task_attr;
1239    (void)ffrt_task_attr_init(&task_attr);
1240    ffrt_queue_priority_t priority = ffrt_queue_priority_idle;
1241    ffrt_task_attr_set_queue_priority(&task_attr, priority);
1242    priority = ffrt_task_attr_get_queue_priority(&task_attr);
1243    ffrt_task_attr_destroy(&task_attr);
1244    printf("priority=%d\n", priority);
1245    return 0;
1246}
1247```
1248
1249预期输出为:
1250
1251```
1252priority=3
1253```
1254
1255### 同步原语
1256
1257#### ffrt_mutex_t
1258<hr/>
1259* FFRT提供的类似pthread mutex 的性能实现。
1260
1261##### 声明
1262
1263```{.c}
1264typedef enum {
1265    ffrt_error = -1,
1266    ffrt_success = 0,
1267    ffrt_error_nomem = ENOMEM,
1268    ffrt_error_timedout = ETIMEDOUT,
1269    ffrt_error_busy = EBUSY,
1270    ffrt_error_inval = EINVAL
1271} ffrt_error_t;
1272
1273struct ffrt_mutex_t;
1274
1275int ffrt_mutex_init(ffrt_mutex_t* mutex, const ffrt_mutexattr_t* attr);
1276int ffrt_mutex_lock(ffrt_mutex_t* mutex);
1277int ffrt_mutex_unlock(ffrt_mutex_t* mutex);
1278int ffrt_mutex_trylock(ffrt_mutex_t* mutex);
1279int ffrt_mutex_destroy(ffrt_mutex_t* mutex);
1280```
1281
1282##### 参数
1283
1284`attr`
1285
1286* 当前FFRT只支持基础类型的mutex,因此attr必须为空指针。
1287
1288`mutex`
1289
1290* 指向所操作的互斥锁的指针。
1291
1292##### 返回值
1293
1294* 若成功则为 ffrt_success ,否则发生错误。
1295
1296##### 描述
1297* 该接口只能在FFRT task 内部调用,在FFRT task 外部调用存在未定义的行为。
1298* 该功能能够避免pthread传统的pthread_mutex_t 在抢不到锁时陷入内核的问题,在使用得当的条件下将会有更好的性能。
1299* **注意:目前暂不支持递归和定时功能。**
1300* **注意:C API中的ffrt_mutex_t需要用户调用`ffrt_mutex_init`和`ffrt_mutex_destroy`显式创建和销毁。**
1301* **注意:C API中的ffrt_mutex_t对象的置空和销毁由用户完成,对同一个ffrt_mutex_t仅能调用一次`ffrt_mutex_destroy`,重复对同一个ffrt_mutex_t调用`ffrt_mutex_destroy`,其行为是未定义的。**
1302* **注意:在`ffrt_mutex_destroy`之后再对ffrt_mutex_t进行访问,其行为是未定义的。**
1303
1304##### 样例
1305
1306```{.c}
1307#include <stdio.h>
1308#include "ffrt.h"
1309
1310typedef struct {
1311    int* sum;
1312    ffrt_mutex_t* mtx;
1313} tuple;
1314
1315void func(void* arg)
1316{
1317    tuple* t = (tuple*)arg;
1318
1319    int ret = ffrt_mutex_lock(t->mtx);
1320    if (ret != ffrt_success) {
1321        printf("error\n");
1322    }
1323    (*t->sum)++;
1324    ret = ffrt_mutex_unlock(t->mtx);
1325    if (ret != ffrt_success) {
1326        printf("error\n");
1327    }
1328}
1329
1330typedef struct {
1331    ffrt_function_header_t header;
1332    ffrt_function_t func;
1333    ffrt_function_t after_func;
1334    void* arg;
1335} c_function;
1336
1337static void ffrt_exec_function_wrapper(void* t)
1338{
1339    c_function* f = (c_function*)t;
1340    if (f->func) {
1341        f->func(f->arg);
1342    }
1343}
1344
1345static void ffrt_destroy_function_wrapper(void* t)
1346{
1347    c_function* f = (c_function*)t;
1348    if (f->after_func) {
1349        f->after_func(f->arg);
1350    }
1351}
1352
1353#define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1])
1354static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func,
1355    const ffrt_function_t after_func, void* arg)
1356{
1357    FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size,
1358        size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size);
1359    c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general);
1360    f->header.exec = ffrt_exec_function_wrapper;
1361    f->header.destroy = ffrt_destroy_function_wrapper;
1362    f->func = func;
1363    f->after_func = after_func;
1364    f->arg = arg;
1365    return (ffrt_function_header_t*)f;
1366}
1367
1368static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func,
1369    void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr)
1370{
1371    ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr);
1372}
1373
1374void ffrt_mutex_task(void *)
1375{
1376    int sum = 0;
1377    ffrt_mutex_t mtx;
1378    tuple t = {&sum, &mtx};
1379    int ret = ffrt_mutex_init(&mtx, NULL);
1380    if (ret != ffrt_success) {
1381        printf("error\n");
1382    }
1383    for (int i = 0; i < 10; i++) {
1384        ffrt_submit_c(func, NULL, &t, NULL, NULL, NULL);
1385    }
1386    ffrt_mutex_destroy(&mtx);
1387    ffrt_wait();
1388    printf("sum = %d\n", sum);
1389}
1390
1391int main(int narg, char** argv)
1392{
1393    int r;
1394    ffrt_submit_c(ffrt_mutex_task, NULL, NULL, NULL, NULL, NULL);
1395    ffrt_wait();
1396    return 0;
1397}
1398```
1399
1400预期输出为:
1401
1402```
1403sum=10
1404```
1405
1406* 该例子为功能示例,实际中并不鼓励这样使用。
1407
1408
1409#### ffrt_cond_t
1410<hr/>
1411
1412* FFRT提供的类似pthread 信号量的性能实现。
1413
1414##### 声明
1415
1416```{.c}
1417typedef enum {
1418    ffrt_error = -1,
1419    ffrt_success = 0,
1420    ffrt_error_nomem = ENOMEM,
1421    ffrt_error_timedout = ETIMEDOUT,
1422    ffrt_error_busy = EBUSY,
1423    ffrt_error_inval = EINVAL
1424} ffrt_error_t;
1425
1426struct ffrt_cond_t;
1427
1428int ffrt_cond_init(ffrt_cond_t* cond, const ffrt_condattr_t* attr);
1429int ffrt_cond_signal(ffrt_cond_t* cond);
1430int ffrt_cond_broadcast(ffrt_cond_t* cond);
1431int ffrt_cond_wait(ffrt_cond_t*cond, ffrt_mutex_t* mutex);
1432int ffrt_cond_timedwait(ffrt_cond_t* cond, ffrt_mutex_t* mutex, const struct timespec* time_point);
1433int ffrt_cond_destroy(ffrt_cond_t* cond);
1434```
1435
1436##### 参数
1437
1438`cond`
1439
1440* 指向所操作的信号量的指针。
1441
1442`attr`
1443
1444* 属性设定,空指针表示使用默认属性。
1445
1446`mutex`
1447
1448* 指向要在阻塞期间解锁的互斥锁的指针。
1449
1450`time_point`
1451
1452* 指向指定等待时限时间的对象的指针。
1453
1454
1455##### 返回值
1456
1457* 若成功则为 ffrt_success,若在锁定互斥前抵达时限则为 ffrt_error_timedout。
1458
1459##### 描述
1460* 该接口只能在FFRT task 内部调用,在FFRT task 外部调用存在未定义的行为。
1461* 该功能能够避免传统的pthread_cond_t在条件不满足时陷入内核的问题,在使用得当的条件下将会有更好的性能。
1462* **注意:C API中的ffrt_cond_t需要用户调用`ffrt_cond_init`和`ffrt_cond_destroy`显式创建和销毁。**
1463* **注意:C API中的ffrt_cond_t对象的置空和销毁由用户完成,对同一个ffrt_cond_t仅能调用一次`ffrt_cond_destroy`,重复对同一个ffrt_cond_t调用`ffrt_cond_destroy`,其行为是未定义的。**
1464* **注意:在`ffrt_cond_destroy`之后再对ffrt_cond_t进行访问,其行为是未定义的。**
1465
1466##### 样例
1467
1468```{.c}
1469#include <stdio.h>
1470#include "ffrt.h"
1471
1472typedef struct {
1473    ffrt_cond_t* cond;
1474    int* a;
1475    ffrt_mutex_t* lock_;
1476} tuple;
1477
1478void func1(void* arg)
1479{
1480    tuple* t = (tuple*)arg;
1481    int ret = ffrt_mutex_lock(t->lock_);
1482    if (ret != ffrt_success) {
1483        printf("error\n");
1484    }
1485    while (*t->a != 1) {
1486        ret = ffrt_cond_wait(t->cond, t->lock_);
1487        if (ret != ffrt_success) {
1488            printf("error\n");
1489        }
1490    }
1491    ret = ffrt_mutex_unlock(t->lock_);
1492    if (ret != ffrt_success) {
1493        printf("error\n");
1494    }
1495    printf("a = %d\n", *(t->a));
1496}
1497
1498void func2(void* arg)
1499{
1500    tuple* t = (tuple*)arg;
1501    int ret = ffrt_mutex_lock(t->lock_);
1502    if (ret != ffrt_success) {
1503        printf("error\n");
1504    }
1505    *(t->a) = 1;
1506    ret = ffrt_cond_signal(t->cond);
1507    if (ret != ffrt_success) {
1508        printf("error\n");
1509    }
1510    ret = ffrt_mutex_unlock(t->lock_);
1511    if (ret != ffrt_success) {
1512        printf("error\n");
1513    }
1514}
1515
1516typedef struct {
1517    ffrt_function_header_t header;
1518    ffrt_function_t func;
1519    ffrt_function_t after_func;
1520    void* arg;
1521} c_function;
1522
1523static void ffrt_exec_function_wrapper(void* t)
1524{
1525    c_function* f = (c_function*)t;
1526    if (f->func) {
1527        f->func(f->arg);
1528    }
1529}
1530
1531static void ffrt_destroy_function_wrapper(void* t)
1532{
1533    c_function* f = (c_function*)t;
1534    if (f->after_func) {
1535        f->after_func(f->arg);
1536    }
1537}
1538
1539#define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1])
1540static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func,
1541    const ffrt_function_t after_func, void* arg)
1542{
1543    FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size,
1544        size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size);
1545    c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general);
1546    f->header.exec = ffrt_exec_function_wrapper;
1547    f->header.destroy = ffrt_destroy_function_wrapper;
1548    f->func = func;
1549    f->after_func = after_func;
1550    f->arg = arg;
1551    return (ffrt_function_header_t*)f;
1552}
1553
1554static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func,
1555    void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr)
1556{
1557    ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr);
1558}
1559
1560void ffrt_cv_task(void *)
1561{
1562    ffrt_cond_t cond;
1563    int ret = ffrt_cond_init(&cond, NULL);
1564    if (ret != ffrt_success) {
1565        printf("error\n");
1566    }
1567    int a = 0;
1568    ffrt_mutex_t lock_;
1569    tuple t = {&cond, &a, &lock_};
1570    ret = ffrt_mutex_init(&lock_, NULL);
1571    if (ret != ffrt_success) {
1572        printf("error\n");
1573    }
1574    ffrt_submit_c(func1, NULL, &t, NULL, NULL, NULL);
1575    ffrt_submit_c(func2, NULL, &t, NULL, NULL, NULL);
1576    ffrt_wait();
1577    ffrt_cond_destroy(&cond);
1578    ffrt_mutex_destroy(&lock_);
1579}
1580
1581int main(int narg, char** argv)
1582{
1583    ffrt_submit_c(ffrt_cv_task, NULL, NULL, NULL, NULL, NULL);
1584    ffrt_wait();
1585    return 0;
1586}
1587```
1588
1589预期输出为:
1590
1591```
1592a=1
1593```
1594
1595* 该例子为功能示例,实际中并不鼓励这样使用。
1596
1597#### ffrt_usleep
1598
1599<hr/>
1600* FFRT提供的类似C11 sleep和linux usleep的性能实现。
1601
1602##### 声明
1603
1604```{.c}
1605int ffrt_usleep(uint64_t usec);
1606```
1607
1608##### 参数
1609
1610`usec`
1611
1612* 睡眠的us数。
1613
1614##### 返回值
1615
1616* 不涉及。
1617
1618##### 描述
1619* 该接口只能在FFRT task 内部调用,在FFRT task 外部调用存在未定义的行为。
1620* 该功能能够避免传统的sleep 睡眠时陷入内核的问题,在使用得当的条件下将会有更好的性能。
1621
1622##### 样例
1623
1624```{.c}
1625#include <time.h>
1626#include <stdio.h>
1627#include "ffrt.h"
1628
1629void func(void* arg)
1630{
1631    time_t current_time = time(NULL);
1632    printf("Time: %s", ctime(&current_time));
1633    ffrt_usleep(2000000); // 睡眠 2 秒
1634    current_time = time(NULL);
1635    printf("Time: %s", ctime(&current_time));
1636}
1637
1638typedef struct {
1639    ffrt_function_header_t header;
1640    ffrt_function_t func;
1641    ffrt_function_t after_func;
1642    void* arg;
1643} c_function;
1644
1645static void ffrt_exec_function_wrapper(void* t)
1646{
1647    c_function* f = (c_function*)t;
1648    if (f->func) {
1649        f->func(f->arg);
1650    }
1651}
1652
1653static void ffrt_destroy_function_wrapper(void* t)
1654{
1655    c_function* f = (c_function*)t;
1656    if (f->after_func) {
1657        f->after_func(f->arg);
1658    }
1659}
1660
1661#define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1])
1662static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func,
1663    const ffrt_function_t after_func, void* arg)
1664{
1665    FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size,
1666        size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size);
1667    c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general);
1668    f->header.exec = ffrt_exec_function_wrapper;
1669    f->header.destroy = ffrt_destroy_function_wrapper;
1670    f->func = func;
1671    f->after_func = after_func;
1672    f->arg = arg;
1673    return (ffrt_function_header_t*)f;
1674}
1675
1676static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func,
1677    void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr)
1678{
1679    ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr);
1680}
1681
1682int main(int narg, char** argv)
1683{
1684    ffrt_submit_c(func, NULL, NULL, NULL, NULL, NULL);
1685    ffrt_wait();
1686    return 0;
1687}
1688```
1689
1690一种输出情况为:
1691
1692```
1693Time: Tue Aug 13 15:45:30 2024
1694Time: Tue Aug 13 15:45:32 2024
1695```
1696
1697#### ffrt_yield
1698<hr/>
1699* 当前task 主动让出CPU 执行资源,让其他可以被执行的task 先执行,如果没有其他可被执行的task,yield 无效。
1700
1701##### 声明
1702
1703```{.c}
1704void ffrt_yield();
1705```
1706
1707##### 参数
1708
1709* 不涉及。
1710
1711##### 返回值
1712
1713* 不涉及。
1714
1715##### 描述
1716* 该接口只能在FFRT task 内部调用,在FFRT task 外部调用存在未定义的行为。
1717* 此函数的确切行为取决于实现,特别是使用中的FFRT 调度程序的机制和系统状态。
1718
1719##### 样例
1720
1721* 省略。
1722
1723### ffrt timer
1724<hr />
1725FFRT支持启动和停止定时器的能力。
1726
1727#### ffrt_timer_start
1728<hr/>
1729启动timer定时器。
1730
1731##### 声明
1732```{.c}
1733typedef int ffrt_timer_t;
1734typedef void (*ffrt_timer_cb)(void* data);
1735
1736ffrt_timer_t ffrt_timer_start(ffrt_qos_t qos, uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat);
1737```
1738
1739##### 参数
1740
1741`qos`
1742
1743* qos等级。
1744
1745`timeout`
1746
1747* 超时时间。
1748
1749`data`
1750
1751* 超时后回调函数的入参。
1752
1753`cb`
1754
1755* 超时后回调函数。
1756
1757`repeat`
1758
1759* 是否重复执行该定时器。
1760
1761##### 返回值
1762
1763返回该定时器句柄。
1764
1765##### 描述
1766启动timer定时器。
1767
1768##### 样例
1769```{.c}
1770#include <stdint.h>
1771#include <unistd.h>
1772#include "ffrt.h"
1773
1774static void testfun(void *data)
1775{
1776    *(int *)data += 1;
1777}
1778
1779void (*cb)(void *) = testfun;
1780
1781int main(int narg, char** argv)
1782{
1783    static int x = 0;
1784    int *xf = &x;
1785    void *data = xf;
1786    uint64_t timeout = 200;
1787    int handle = ffrt_timer_start(ffrt_qos_default, timeout, data, cb, false);
1788    usleep(300000);
1789    ffrt_timer_stop(ffrt_qos_default, handle);
1790    printf("data: %d\n", x);
1791    return 0;
1792}
1793```
1794
1795预期输出为:
1796
1797```
1798data: 1
1799```
1800
1801#### ffrt_timer_stop
1802<hr/>
1803停止timer定时器。
1804
1805##### 声明
1806```{.c}
1807int ffrt_timer_stop(ffrt_qos_t qos, ffrt_timer_t handle);
1808```
1809
1810##### 参数
1811
1812`qos`
1813
1814* qos等级。
1815
1816`handle`
1817
1818* 定时器句柄。
1819
1820##### 返回值
1821
1822返回0成功,返回-1失败。
1823
1824##### 描述
1825停止timer定时器。
1826
1827##### 样例
1828```{.c}
1829#include <stdint.h>
1830#include <unistd.h>
1831#include "ffrt.h"
1832
1833static void testfun(void *data)
1834{
1835    *(int *)data += 1;
1836}
1837
1838void (*cb)(void *) = testfun;
1839
1840int main(int narg, char** argv)
1841{
1842    static int x = 0;
1843    int *xf = &x;
1844    void *data = xf;
1845    uint64_t timeout = 200;
1846    int handle = ffrt_timer_start(ffrt_qos_default, timeout, data, cb, false);
1847    usleep(300000);
1848    ffrt_timer_stop(ffrt_qos_default, handle);
1849    printf("data: %d\n", x);
1850    return 0;
1851}
1852```
1853
1854预期输出为:
1855
1856```
1857data: 1
1858```
1859
1860### ffrt looper
1861<hr />
1862FFRT 提供looper机制,looper支持任务提交,事件监听,定时器功能,looper运行在用户线程。
1863
1864#### ffrt_loop_create
1865<hr/>
1866创建loop对象。
1867
1868##### 声明
1869```{.c}
1870typedef void* ffrt_loop_t;
1871
1872ffrt_loop_t ffrt_loop_create(ffrt_queue_t queue);
1873```
1874
1875##### 参数
1876
1877`queue`
1878
1879* 需要是并行队列。
1880
1881##### 返回值
1882
1883loop对象。
1884
1885##### 描述
1886创建loop对象。
1887
1888##### 样例
1889```{.c}
1890#include <stdint.h>
1891#include <unistd.h>
1892#include <stdio.h>
1893#include "c/loop.h"
1894
1895int main(int narg, char** argv)
1896{
1897    ffrt_queue_attr_t queue_attr;
1898    (void)ffrt_queue_attr_init(&queue_attr);
1899    ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_concurrent, "test_queue", &queue_attr);
1900
1901    auto loop = ffrt_loop_create(queue_handle);
1902
1903    if (loop != NULL) {
1904        printf("loop is not null.\n");
1905    }
1906
1907    int ret = ffrt_loop_destroy(loop);
1908
1909    ffrt_queue_attr_destroy(&queue_attr);
1910    ffrt_queue_destroy(queue_handle);
1911    return 0;
1912}
1913```
1914
1915预期输出为:
1916
1917```
1918loop is not null.
1919```
1920
1921#### ffrt_loop_destroy
1922<hr/>
1923销毁loop对象。
1924
1925##### 声明
1926```{.c}
1927int ffrt_loop_destroy(ffrt_loop_t loop);
1928```
1929
1930##### 参数
1931
1932`loop`
1933
1934* loop对象。
1935
1936##### 返回值
1937
1938返回0表示成功,-1表示失败。
1939
1940##### 描述
1941销毁loop对象。
1942
1943##### 样例
1944```{.c}
1945#include <stdint.h>
1946#include <unistd.h>
1947#include <stdio.h>
1948#include "c/loop.h"
1949
1950int main(int narg, char** argv)
1951{
1952    ffrt_queue_attr_t queue_attr;
1953    (void)ffrt_queue_attr_init(&queue_attr);
1954    ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_concurrent, "test_queue", &queue_attr);
1955
1956    auto loop = ffrt_loop_create(queue_handle);
1957
1958    int ret = ffrt_loop_destroy(loop);
1959
1960    if (ret == 0) {
1961        printf("loop normal destruction.");
1962    }
1963
1964    ffrt_queue_attr_destroy(&queue_attr);
1965    ffrt_queue_destroy(queue_handle);
1966    return 0;
1967}
1968```
1969
1970预期输出为:
1971
1972```
1973loop normal destruction.
1974```
1975
1976#### ffrt_loop_run
1977<hr/>
1978启动loop循环。
1979
1980##### 声明
1981```{.c}
1982int ffrt_loop_run(ffrt_loop_t loop);
1983```
1984
1985##### 参数
1986
1987`loop`
1988
1989* loop对象。
1990
1991##### 返回值
1992
1993返回0表示成功,-1表示失败。
1994
1995##### 描述
1996启动loop循环。
1997
1998##### 样例
1999```{.c}
2000#include <pthread.h>
2001#include <unistd.h>
2002#include <stdio.h>
2003#include "c/loop.h"
2004
2005void* ThreadFunc(void* p)
2006{
2007    int ret = ffrt_loop_run(p);
2008    if (ret == 0) {
2009        printf("loop normal operation.");
2010    }
2011    return nullptr;
2012}
2013int main(int narg, char** argv)
2014{
2015    ffrt_queue_attr_t queue_attr;
2016    (void)ffrt_queue_attr_init(&queue_attr);
2017    ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_concurrent, "test_queue", &queue_attr);
2018
2019    auto loop = ffrt_loop_create(queue_handle);
2020    pthread_t thread;
2021    pthread_create(&thread, 0, ThreadFunc, loop);
2022
2023    ffrt_loop_stop(loop);
2024    int ret = ffrt_loop_destroy(loop);
2025
2026    ffrt_queue_attr_destroy(&queue_attr);
2027    ffrt_queue_destroy(queue_handle);
2028    return 0;
2029}
2030```
2031
2032预期输出为:
2033
2034```
2035loop normal operation.
2036```
2037
2038#### ffrt_loop_stop
2039<hr/>
2040停止loop循环。
2041
2042##### 声明
2043```{.c}
2044void ffrt_loop_stop(ffrt_loop_t loop);
2045```
2046
2047##### 参数
2048
2049`loop`
2050
2051* loop对象。
2052
2053##### 返回值
2054
2055NA。
2056
2057##### 描述
2058停止loop循环。
2059
2060##### 样例
2061```{.c}
2062#include <pthread.h>
2063#include <unistd.h>
2064#include <stdio.h>
2065#include "c/loop.h"
2066
2067void* ThreadFunc(void* p)
2068{
2069    int ret = ffrt_loop_run(p);
2070    return nullptr;
2071}
2072int main(int narg, char** argv)
2073{
2074    ffrt_queue_attr_t queue_attr;
2075    (void)ffrt_queue_attr_init(&queue_attr);
2076    ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_concurrent, "test_queue", &queue_attr);
2077
2078    auto loop = ffrt_loop_create(queue_handle);
2079    pthread_t thread;
2080    pthread_create(&thread, 0, ThreadFunc, loop);
2081
2082    ffrt_loop_stop(loop);
2083    int ret = ffrt_loop_destroy(loop);
2084
2085    ffrt_queue_attr_destroy(&queue_attr);
2086    ffrt_queue_destroy(queue_handle);
2087    return 0;
2088}
2089```
2090
2091预期输出为:
2092
2093```
2094正常停止loop对象,返回值是0。
2095```
2096
2097#### ffrt_loop_epoll_ctl
2098<hr/>
2099管理loop上的监听事件。
2100
2101##### 声明
2102```{.c}
2103int ffrt_loop_epoll_ctl(ffrt_loop_t loop, int op, int fd, uint32_t events, void *data, ffrt_poller_cb cb);
2104```
2105
2106##### 参数
2107
2108`loop`
2109
2110* loop对象。
2111
2112`op`
2113
2114* fd操作符,如EPOLL_CTL_ADD和EPOLL_CLT_DEL。
2115
2116`fd`
2117
2118* 事件描述符。
2119
2120`events`
2121
2122* 事件。
2123
2124`data`
2125
2126* 事件变化时触发的回调函数的入参。
2127
2128`cb`
2129
2130* 事件变化时触发的回调函数。
2131
2132##### 返回值
2133
2134返回0表示成功,-1表示失败。
2135
2136##### 描述
2137管理loop上的监听事件。
2138
2139##### 样例
2140```{.c}
2141#include <pthread.h>
2142#include <unistd.h>
2143#include <stdio.h>
2144#include <functional>
2145#include <sys/epoll.h>
2146#include <sys/eventfd.h>
2147#include "c/loop.h"
2148#include "ffrt.h"
2149
2150void* ThreadFunc(void* p)
2151{
2152    int ret = ffrt_loop_run(p);
2153    return nullptr;
2154}
2155
2156static void testfun(void* data)
2157{
2158    *(int*)data += 1;
2159}
2160
2161static void (*cb)(void*) = testfun;
2162
2163void testCallBack(void *data, unsigned int events) {}
2164
2165struct TestData {
2166    int fd;
2167    uint64_t expected;
2168};
2169
2170int main(int narg, char** argv)
2171{
2172    ffrt_queue_attr_t queue_attr;
2173    (void)ffrt_queue_attr_init(&queue_attr);
2174    ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_concurrent, "test_queue", &queue_attr);
2175
2176    auto loop = ffrt_loop_create(queue_handle);
2177    int result1 = 0;
2178    std::function<void()> &&basicFunc1 = [&result1]() {result1 += 10;};
2179    ffrt_task_handle_t task1 = ffrt_queue_submit_h(queue_handle, ffrt::create_function_wrapper(basicFunc1, ffrt_function_kind_queue), nullptr);
2180
2181    pthread_t thread;
2182    pthread_create(&thread, 0, ThreadFunc, loop);
2183
2184    static int x = 0;
2185    int* xf = &x;
2186    void* data = xf;
2187    uint64_t timeout1 = 20;
2188    uint64_t timeout2 = 10;
2189    uint64_t expected = 0xabacadae;
2190
2191    int testFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
2192    struct TestData testData {.fd = testFd, .expected = expected};
2193    ffrt_timer_t timeHandle = ffrt_loop_timer_start(loop, timeout1, data, cb, false);
2194
2195    int ret = ffrt_loop_epoll_ctl(loop, EPOLL_CTL_ADD, testFd, EPOLLIN, (void*)(&testData), testCallBack);
2196    if (ret == 0) {
2197        printf("ffrt_loop_epoll_ctl执行成功。\n");
2198    }
2199    ssize_t n = write(testFd, &expected, sizeof(uint64_t));
2200    usleep(25000);
2201    ffrt_loop_epoll_ctl(loop, EPOLL_CTL_DEL, testFd, 0, nullptr, nullptr);
2202
2203    ffrt_loop_stop(loop);
2204    pthread_join(thread, nullptr);
2205    ffrt_loop_timer_stop(loop, timeHandle);
2206    ret = ffrt_loop_destroy(loop);
2207
2208    ffrt_queue_attr_destroy(&queue_attr);
2209    ffrt_queue_destroy(queue_handle);
2210    return 0;
2211}
2212```
2213
2214预期输出为:
2215
2216```
2217ffrt_loop_epoll_ctl执行成功。
2218```
2219
2220#### ffrt_loop_timer_start
2221<hr/>
2222在loop上启动定时器。
2223
2224##### 声明
2225```{.c}
2226ffrt_timer_t ffrt_loop_timer_start(ffrt_loop_t loop, uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat);
2227```
2228
2229##### 参数
2230
2231`loop`
2232
2233* loop对象。
2234
2235`timeout`
2236
2237* 超时时间。
2238
2239`data`
2240
2241* 事件变化时触发的回调函数的入参。
2242
2243`cb`
2244
2245* 事件变化时触发的回调函数。
2246
2247`repeat`
2248
2249* 是否重复执行该定时器。
2250
2251##### 返回值
2252
2253定时器句柄。
2254
2255##### 描述
2256在loop上启动定时器。
2257
2258##### 样例
2259参考ffrt_loop_epoll_ctl接口样例。
2260
2261#### ffrt_loop_timer_stop
2262<hr/>
2263停止timer定时器。
2264
2265##### 声明
2266```{.c}
2267int ffrt_loop_timer_stop(ffrt_loop_t loop, ffrt_timer_t handle)
2268```
2269
2270##### 参数
2271
2272`loop`
2273
2274* loop对象。
2275
2276`handle`
2277
2278* 定时器句柄。
2279
2280##### 返回值
2281
2282返回0表示成功,返回-1表示失败。
2283
2284##### 描述
2285停止timer定时器。
2286
2287##### 样例
2288参考ffrt_loop_epoll_ctl接口样例。
2289
2290## 长耗时任务监测
2291
2292### 机制
2293* 当任务执行时间超过一秒时,会触发一次堆栈打印,后续该任务堆栈打印频率调整为一分钟。连续打印十次后,打印频率调整为十分钟。再触发十次打印后,打印频率固定为三十分钟。
2294* 该机制的堆栈打印调用的是DFX的 `GetBacktraceStringByTid` 接口,该接口会向阻塞线程发送抓栈信号,触发中断并抓取调用栈返回。
2295
2296### 样例
2297在对应进程日志中搜索 `RecordSymbolAndBacktrace` 关键字,对应的日志示例如下:
2298
2299```
2300W C01719/ffrt: 60500:RecordSymbolAndBacktrace:159 Tid[16579] function occupies worker for more than [1]s.
2301W C01719/ffrt: 60501:RecordSymbolAndBacktrace:164 Backtrace:
2302W C01719/ffrt: #00 pc 00000000000075f0 /system/lib64/module/file/libhash.z.so
2303W C01719/ffrt: #01 pc 0000000000008758 /system/lib64/module/file/libhash.z.so
2304W C01719/ffrt: #02 pc 0000000000012b98 /system/lib64/module/file/libhash.z.so
2305W C01719/ffrt: #03 pc 000000000002aaa0 /system/lib64/platformsdk/libfilemgmt_libn.z.so
2306W C01719/ffrt: #04 pc 0000000000054b2c /system/lib64/platformsdk/libace_napi.z.so
2307W C01719/ffrt: #05 pc 00000000000133a8 /system/lib64/platformsdk/libuv.so
2308W C01719/ffrt: #06 pc 00000000000461a0 /system/lib64/chipset-sdk/libffrt.so
2309W C01719/ffrt: #07 pc 0000000000046d44 /system/lib64/chipset-sdk/libffrt.so
2310W C01719/ffrt: #08 pc 0000000000046a6c /system/lib64/chipset-sdk/libffrt.so
2311W C01719/ffrt: #09 pc 00000000000467b0 /system/lib64/chipset-sdk/libffrt.so
2312```
2313该维测会打印出worker上执行时间超过阈值的任务堆栈、worker线程号、执行时间,请自行根据堆栈找对应组件确认阻塞原因。
2314
2315
2316### 注意事项
2317长耗时任务监测会发送中断信号,如果用户的代码中存在 `sleep` 等会被中断唤醒的阻塞,用户需主动接收该阻塞的返回值,并重新调用。
2318示例如下:
2319```
2320unsigned int leftTime = sleep(10);
2321while (leftTime != 0) {
2322    leftTime = sleep(leftTime);
2323}
2324```
2325
2326## 开发步骤
2327
2328以下步骤描述了如何使用`FFRT`提供的Native API接口,创建并行任务和串行队列任务以及销毁相应资源。
2329
2330**添加动态链接库**
2331
2332CMakeLists.txt中添加以下lib:
2333```txt
2334libffrt.z.so
2335```
2336
2337**头文件**
2338```c++
2339#include "ffrt/task.h"
2340#include "ffrt/type_def.h"
2341#include "ffrt/condition_variable.h"
2342#include "ffrt/mutex.h"
2343#include "ffrt/queue.h"
2344#include "ffrt/sleep.h"
2345```
2346
23471. **首先需要对执行的函数进行封装**。
2348    ```c++
2349    // 第一种使用模板,支持C++
2350    template<class T>
2351    struct Function {
2352        ffrt_function_header_t header;
2353        T closure;
2354    };
2355
2356    template<class T>
2357    void ExecFunctionWrapper(void* t)
2358    {
2359        auto f = reinterpret_cast<Function<std::decay_t<T>>*>(t);
2360        f->closure();
2361    }
2362
2363    template<class T>
2364    void DestroyFunctionWrapper(void* t)
2365    {
2366        auto f = reinterpret_cast<Function<std::decay_t<T>>*>(t);
2367        f->closure = nullptr;
2368    }
2369
2370    template<class T>
2371    static inline ffrt_function_header_t* create_function_wrapper(T&& func,
2372        ffrt_function_kind_t kind = ffrt_function_kind_general)
2373    {
2374        using function_type = Function<std::decay_t<T>>;
2375        auto p = ffrt_alloc_auto_managed_function_storage_base(kind);
2376        auto f = new (p)function_type;
2377        f->header.exec = ExecFunctionWrapper<T>;
2378        f->header.destroy = DestroyFunctionWrapper<T>;
2379        f->closure = std::forward<T>(func);
2380        return reinterpret_cast<ffrt_function_header_t*>(f);
2381    }
2382
2383    // 第二种创建方式
2384    typedef struct {
2385        ffrt_function_header_t header;
2386        ffrt_function_t func;
2387        ffrt_function_t after_func;
2388        void* arg;
2389    } CFunction;
2390
2391    static void FfrtExecFunctionWrapper(void* t)
2392    {
2393        CFunction* f = static_cast<CFunction*>(t);
2394        if (f->func) {
2395            f->func(f->arg);
2396        }
2397    }
2398
2399    static void FfrtDestroyFunctionWrapper(void* t)
2400    {
2401        CFunction* f = static_cast<CFunction*>(t);
2402        if (f->after_func) {
2403            f->after_func(f->arg);
2404        }
2405    }
2406
2407    #define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1])
2408    static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func,
2409        const ffrt_function_t after_func, void* arg, ffrt_function_kind_t kind_t = ffrt_function_kind_general)
2410    {
2411        FFRT_STATIC_ASSERT(sizeof(CFunction) <= ffrt_auto_managed_function_storage_size,
2412            size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size);
2413        CFunction* f = static_cast<CFunction*>(ffrt_alloc_auto_managed_function_storage_base(kind_t));
2414        f->header.exec = FfrtExecFunctionWrapper;
2415        f->header.destroy = FfrtDestroyFunctionWrapper;
2416        f->func = func;
2417        f->after_func = after_func;
2418        f->arg = arg;
2419        return reinterpret_cast<ffrt_function_header_t*>(f);
2420    }
2421
2422    // 样例:待提交执行的函数
2423    void OnePlusForTest(void* arg)
2424    {
2425        (*static_cast<int*>(arg)) += 1;
2426    }
2427    ```
2428
24292. **设置task属性值**。
2430
2431    用户提交任务时可以设置任务属性,包括qos等级,名称等,具体可参考接口文档。
2432    ```c++
2433    // ******初始化并行任务属性******
2434    ffrt_task_attr_t attr;
2435    ffrt_task_attr_init(&attr);
2436
2437    // ******创建串行队列******
2438
2439    // 创建串行队列的属性
2440    ffrt_queue_attr_t queue_attr;
2441    // 创建串行队列的handle
2442    ffrt_queue_t queue_handle;
2443
2444    // 初始化队列属性
2445    (void)ffrt_queue_attr_init(&queue_attr);
2446
2447    // 如有需要,设置指定qos等级
2448    ffrt_queue_attr_set_qos(&queue_attr, static_cast<ffrt_qos_t>(ffrt_qos_inherit));
2449    // 如有需要,设置超时时间(ms)
2450    ffrt_queue_attr_set_timeout(&queue_attr, 10000);
2451    // 如有需要,设置超时回调
2452    int x = 0;
2453    ffrt_queue_attr_set_callback(&queue_attr, ffrt_create_function_wrapper(OnePlusForTest, NULL, &x,
2454        ffrt_function_kind_queue));
2455
2456    // 基于属性,初始化队列
2457    queue_handle = ffrt_queue_create(ffrt_queue_serial, "test_queue", &queue_attr);
2458    ```
2459
24603. **提交任务**。
2461    ```c++
2462    int a = 0;
2463    // ******并行任务******
2464    // 提交不带handle返回值的并行任务
2465    ffrt_submit_base(ffrt_create_function_wrapper(OnePlusForTest, NULL, &a), NULL, NULL, &attr);
2466    // 提交带handle返回值的并行任务
2467    ffrt_task_handle_t task = ffrt_submit_h_base(
2468        ffrt_create_function_wrapper(OnePlusForTest, NULL, &a), NULL, NULL, &attr);
2469
2470    // ******串行任务******
2471    // 提交不返回handle的串行队列任务
2472    ffrt_queue_submit(queue_handle, ffrt_create_function_wrapper(OnePlusForTest, nullptr, &a,
2473        ffrt_function_kind_queue), nullptr);
2474    // 提交带handle的串行队列任务
2475    ffrt_task_handle_t handle = ffrt_queue_submit_h(queue_handle,
2476        ffrt_create_function_wrapper(OnePlusForTest, nullptr, &a, ffrt_function_kind_queue), nullptr);
2477
2478    // 如果需要等待执行结果,则调用wait
2479    const std::vector<ffrt_dependence_t> wait_deps = {{ffrt_dependence_task, task}};
2480    ffrt_deps_t wait{static_cast<uint32_t>(wait_deps.size()), wait_deps.data()};
2481    ffrt_wait_deps(&wait);
2482
2483    ffrt_queue_wait(handle);
2484    ```
2485
24864. **任务提交完成后销毁相应资源**。
2487    ```c++
2488    // ******销毁并行任务******
2489    ffrt_task_attr_destroy(&attr);
2490    ffrt_task_handle_destroy(task);
2491
2492    // ******销毁串行队列任务******
2493    // 先销毁任务handle,再销毁队列
2494    ffrt_queue_attr_destroy(&queue_attr);
2495    ffrt_task_handle_destroy(handle);
2496    ffrt_queue_destroy(queue_handle);
2497    ```
2498
2499## 使用建议
2500
2501### 建议1: 函数化
2502
2503**基本思想:计算过程函数化**
2504
2505* 程序过程各步骤以函数封装表达,函数满足类纯函数特性。
2506* 无全局数据访问。
2507* 无内部状态保留。
2508* 通过ffrt_submit_base()接口以异步任务方式提交函数执行。
2509* 将函数访问的数据对象以及访问方式在ffrt_submit_base()接口中的in_deps/out_deps参数表达。
2510* 程序员通过inDeps/outDeps参数表达任务间依赖关系以保证程序执行的正确性。
2511
2512> 做到纯函数的好处在于:1. 能够最大化挖掘并行度,2.避免DataRace和锁的问题。
2513
2514
2515
2516**在实际中,可以根据场景放松纯函数的约束,但前提是:**
2517
2518* 确定添加的in_deps/out_deps可确保程序正确执行。
2519* 通过FFRT提供的锁机制保护对全局变量的访问。
2520
2521
2522### 建议2: 使用FFRT提供的替代API
2523
2524* 禁止在FFRT任务中使用系统线程库API创建线程,使用submit提交任务。
2525* 使用FFRT提供的锁,条件变量,睡眠,IO等API代替系统线程库API。
2526  * 使用系统线程库API可能造成工作线程阻塞,引起额外性能开销。
2527
2528
2529
2530### 建议3: Deadline机制
2531
2532* **必须用于具备周期/重复执行特征的处理流程。**
2533* 在有明确时间约束和性能关键的处理流程中使用,避免滥用。
2534* 在相对大颗粒度的处理流程中使用,例如具有16.6ms时间约束的帧处理流程。
2535
2536
2537
2538### 建议4: 从线程模型迁移
2539
2540* 创建线程替代为创建FFRT任务。
2541  * 线程从逻辑上类似无in_deps的任务。
2542* 识别线程间的依赖关系,并将其表达在任务的依赖关系in_deps/out_deps上。
2543* 线程内计算过程分解为异步任务调用。
2544* 通过任务依赖关系和锁机制避免并发任务数据竞争问题。
2545
2546
2547
2548### 建议5: 推荐使用C++接口
2549
2550* FFRT的C++接口是基于C接口实现,在使用API接口时可以手动添加C++相关头文件后配套使用。
2551* 相关C++接口下载参考:[FFRT C++接口](https://gitee.com/openharmony/resourceschedule_ffrt/tree/master/interfaces/kits)
2552
2553
2554
2555
2556
2557## 已知限制
2558
2559
2560### C API中初始化ffrt对象后,对象的置空与销毁由用户负责
2561
2562* 为保证较高的性能,ffrt的C API中内部不包含对对象的销毁状态的标记,用户需要合理地进行资源的释放,重复调用各个对象的destroy操作,其结果是未定义的。
2563* 错误示例1,重复调用destroy可能造成不可预知的数据损坏。
2564
2565```{.c}
2566#include "ffrt.h"
2567void abnormal_case_1()
2568{
2569    ffrt_task_handle_t h = ffrt_submit_h_base([](){printf("Test task running...\n");}, NULL, NULL, NULL, NULL, NULL);
2570    ...
2571    ffrt_task_handle_destroy(h);
2572    ffrt_task_handle_destroy(h); // double free
2573}
2574```
2575
2576* 错误示例2,未调用destroy会造成内存泄漏
2577
2578```{.c}
2579#include "ffrt.h"
2580void abnormal_case_2()
2581{
2582    ffrt_task_handle_t h = ffrt_submit_h_base([](){printf("Test task running...\n");}, NULL, NULL, NULL, NULL, NULL);
2583    ...
2584    // memory leak
2585}
2586```
2587
2588* 建议示例,仅调用一次destroy,如有必要可进行置空
2589
2590```{.c}
2591#include "ffrt.h"
2592void normal_case()
2593{
2594    ffrt_task_handle_t h = ffrt_submit_h_base([](){printf("Test task running...\n");}, NULL, NULL, NULL, NULL, NULL);
2595    ...
2596    ffrt_task_handle_destroy(h);
2597    h = nullptr; // if necessary
2598}
2599```
2600