IT评测·应用市场-qidao123.com

标题: 鸿蒙HarmonyOS应用开辟之FFRT 开辟引导 [打印本页]

作者: 兜兜零元    时间: 2024-11-3 18:48
标题: 鸿蒙HarmonyOS应用开辟之FFRT 开辟引导
场景介绍

Function Flow编程模子是一种基于任务和数据驱动的并发编程模子,允许开辟者通过任务及其依赖关系形貌的方式进行应用开辟。FFRT(Function Flow运行时)是支持Function Flow编程模子的软件运行时库,用于调度实验开辟者基于Function Flow编程模子开辟的应用。通过Function Flow编程模子和FFRT,开辟者可专注于应勤奋能开辟,由FFRT在运行时根据任务依赖状态和可用实验资源自动并发调度和实验任务。
本文用于引导开辟者基于Function Flow编程模子和FFRT实现并行编程。
两种编程模子

线程编程模子FFRT任务编程模子并行度发掘方式步伐员通过创建多线程并把任务分配到每个线程中实验来发掘运行时的并行度。步伐员(编译器工具或语言特性共同)静态编程时将应用分解成任务及其数据依赖关系,运行时调度器分配任务到工作线程实验。谁负责线程创建步伐员负责创建线程,线程编程模子无法约束线程的创建,滥用可能造成体系中大量线程。由调度器负责工作线程池的创建和管理,步伐员无法直接创建线程。负载均衡步伐员静态编程时将任务映射到线程,映射不公道或任务实验时间不确定造成线程负载不均。FFRT运行时根据线程实验状态调度停当任务到空闲线程实验,减轻了线程负载不均标题。调度开销线程调度由内核态调度器完成,调度开销大。FFRT运行时在用户态以协程方式调度实验,相比内核线程调度机制更为轻量,减小调度的开销,并可通过硬化调度卸载进一步减小调度开销。依赖表达线程创建时即处于可实验状态,实验时与其他线程同步操作,增长线程切换。FFRT运行时根据任务创建时显式表达的输入依赖和输出依赖关系判断任务可实验状态,当输入依赖不满足时,任务不被调度实验。 根本概念

Function Flow 任务编程模子

Function Flow编程模子允许开辟者通过任务及其依赖关系形貌的方式进行应用开辟,其重要特性包罗Task-Based 和 Data-Driven 。
Task-Based 特性

Task-Based 指在Function Flow编程模子中开辟者以任务方式来组织应用步伐表达,运行时以任务粒度实验调度。
任务界说为一种面向开辟者的编程线索和面向运行时的实验对象,通常包罗一组指令序列及其操作的数据上下文情况。
Function Flow编程模子中的任务包罗以下重要特性:

   留意
任务颗粒度影响应用实验性能,颗粒度过小增长调度开销,颗粒度过大降低并行度。Function Flow编程模子中任务的目标颗粒度最小为100us量级,开辟者应留意公道控制任务颗粒度。
  Data-Driven 特性

Data-Driven指任务之间的依赖关系通过数据依赖表达。
任务实验过程中对其关联的数据对象进行读写操作。在Function Flow编程模子中,数据对象表达抽象为数据签名,每个数据签名唯一对应一个数据对象。
数据依赖抽象为任务所操作的数据对象的数据签名列表,包罗输入数据依赖in_deps和输出数据依赖out_deps。数据对象的签名出现在一个任务的in_deps中时,该任务称为数据对象的消耗者任务,消耗者任务实验不改变其输入数据对象的内容;数据对象的签名出现在任务的out_deps中时,该任务称为数据对象的生产者任务,生产者任务实验改变其输出数据对象的内容,从而天生该数据对象的一个新的版本。
一个数据对象可能存在多个版本,每个版本对应一个生产者任务和零个,一个或多个消耗者任务,根据生产者任务和消耗者任务的下发次序界说数据对象的多个版本的次序以及每个版本所对应的生产者和消耗者任务。
数据依赖清除的任务进入停当状态允许被调度实验,依赖清除状态指任务全部输入数据对象版本的生产者任务实验完成,且全部输出数据对象版本的全部消耗者任务实验完成的状态。
通过上述Data-Driven的数据依赖表达,FFRT在运行时可动态构建任务之间的基于生产者/消耗者的数据依赖关系并遵循任务数据依赖状态实验调度,包罗:

例如,如果有这么一些任务,与数据A的关系表述为:
  1. task1(OUT A);
  2. task2(IN A);
  3. task3(IN A);
  4. task4(OUT A);
  5. task5(OUT A);
复制代码

   为表述方便,本文中的数据流图均以圆圈表示 Task,方块表示数据。
  可以得出以下结论:

接口说明

接口名形貌ffrt_condattr_init (ffrt_condattr_t* attr)初始化条件变量属性。ffrt_condattr_destroy(ffrt_condattr_t* attr)烧毁条件变量属性。ffrt_condattr_setclock(ffrt_condattr_t* attr, ffrt_clockid_t clock)设置条件变量的时钟属性。ffrt_condattr_getclock(const ffrt_condattr_t* attr, ffrt_clockid_t* clock)获取条件变量的时钟属性。ffrt_cond_init(ffrt_cond_t* cond, const ffrt_condattr_t* attr)初始化条件变量。ffrt_cond_signal(ffrt_cond_t* cond)唤醒阻塞在条件变量上的一个任务。ffrt_cond_broadcast(ffrt_cond_t* cond)唤醒阻塞在条件变量上的全部任务。ffrt_cond_wait(ffrt_cond_t* cond, ffrt_mutex_t* mutex)条件变量期待函数,条件变量不满足时阻塞当前任务。ffrt_cond_timedwait(ffrt_cond_t* cond, ffrt_mutex_t* mutex, const struct timespec* time_point)条件变量超时期待函数,条件变量不满足时阻塞当前任务,超时期待返回。ffrt_cond_destroy(ffrt_cond_t* cond)烧毁条件变量。ffrt_mutex_init(ffrt_mutex_t* mutex, const ffrt_mutexattr_t* attr)初始化mutex。ffrt_mutex_lock(ffrt_mutex_t* mutex)获取mutex。ffrt_mutex_unlock(ffrt_mutex_t* mutex)开释mutex。ffrt_mutex_trylock(ffrt_mutex_t* mutex)实验获取mutex。ffrt_mutex_destroy(ffrt_mutex_t* mutex)烧毁mutex。ffrt_queue_attr_init(ffrt_queue_attr_t* attr)初始化串行队列属性。ffrt_queue_attr_destroy(ffrt_queue_attr_t* attr)烧毁串行队列属性。ffrt_queue_attr_set_qos(ffrt_queue_attr_t* attr, ffrt_qos_t qos)设置串行队列qos属性。ffrt_queue_attr_get_qos(const ffrt_queue_attr_t* attr)获取串行队列qos属性。ffrt_queue_create(ffrt_queue_type_t type, const char* name, const ffrt_queue_attr_t* attr)创建队列。ffrt_queue_destroy(ffrt_queue_t queue)烧毁队列。ffrt_queue_submit(ffrt_queue_t queue, ffrt_function_header_t* f, const ffrt_task_attr_t* attr)提交一个任务到队列中调度实验。ffrt_queue_submit_h(ffrt_queue_t queue, ffrt_function_header_t* f, const ffrt_task_attr_t* attr)提交一个任务到队列中调度实验,并返回任务句柄。ffrt_queue_wait(ffrt_task_handle_t handle)期待队列中一个任务实验完成。ffrt_queue_cancel(ffrt_task_handle_t handle)取消队列中一个任务。ffrt_usleep(uint64_t usec)延迟usec微秒。ffrt_yield(void)当前任务自动放权,让其他任务有机会调度实验。ffrt_task_attr_init(ffrt_task_attr_t* attr)初始化任务属性。ffrt_task_attr_set_name(ffrt_task_attr_t* attr, const char* name)设置任务名字。ffrt_task_attr_get_name(const ffrt_task_attr_t* attr)获取任务名字。ffrt_task_attr_destroy(ffrt_task_attr_t* attr)烧毁任务属性。ffrt_task_attr_set_qos(ffrt_task_attr_t* attr, ffrt_qos_t qos)设置任务qos。ffrt_task_attr_get_qos(const ffrt_task_attr_t* attr)获取任务qos。ffrt_task_attr_set_delay(ffrt_task_attr_t* attr, uint64_t delay_us)设置任务延迟时间。ffrt_task_attr_get_delay(const ffrt_task_attr_t* attr)获取任务延迟时间。ffrt_this_task_update_qos(ffrt_qos_t qos)更新任务qos。ffrt_this_task_get_id(void)获取任务id。ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_t kind)申请函数实验布局的内存。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)提交任务调度实验。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)提交任务调度实验并返回任务句柄。ffrt_task_handle_destroy(ffrt_task_handle_t handle)烧毁任务句柄。ffrt_skip(ffrt_task_handle_t handle)跳过指定任务。ffrt_wait_deps(const ffrt_deps_t* deps)期待依赖的任务完成,当前任务开始实验。 函数介绍

任务管理

ffrt_submit_base


声明

  1. const int ffrt_auto_managed_function_storage_size = 64 + sizeof(ffrt_function_header_t);
  2. typedef enum {
  3.     ffrt_function_kind_general,
  4.     ffrt_function_kind_queue
  5. } ffrt_function_kind_t;
  6. void* ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_t kind);
  7. typedef void(*ffrt_function_t)(void*);
  8. typedef struct {
  9.     ffrt_function_t exec;
  10.     ffrt_function_t destroy;
  11.     uint64_t reserve[2];
  12. } ffrt_function_header_t;
  13. void 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);
复制代码
参数

kind

func

in_deps

out_deps

attr

返回值


形貌


样例

  1. template<class T>
  2. struct function {
  3.     template<class CT>
  4.     function(ffrt_function_header_t h, CT&& c) : header(h), closure(std::forward<CT>(c)) {}
  5.     ffrt_function_header_t header;
  6.     T closure;
  7. };
  8. template<class T>
  9. void exec_function_wrapper(void* t)
  10. {
  11.     auto f = (function<std::decay_t<T>>*)t;
  12.     f->closure();
  13. }
  14. template<class T>
  15. void destroy_function_wrapper(void* t)
  16. {
  17.     auto f = (function<std::decay_t<T>>*)t;
  18.     f->closure = nullptr;
  19. }
  20. template<class T>
  21. inline ffrt_function_header_t* create_function_wrapper(T&& func)
  22. {
  23.     using function_type = function<std::decay_t<T>>;
  24.     static_assert(sizeof(function_type) <= ffrt_auto_managed_function_storage_size,
  25.         "size of function must be less than ffrt_auto_managed_function_storage_size");
  26.     auto p = ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general);
  27.     auto f = new (p) function_type(
  28.         {exec_function_wrapper<T>, destroy_function_wrapper<T>},
  29.         std::forward<T>(func));
  30.     return (ffrt_function_header_t*)f;
  31. }
  32. static inline void submit(std::function<void()>&& func)
  33. {
  34.     return ffrt_submit_base(create_function_wrapper(std::move(func)), NULL, NULL, NULL);
  35. }
复制代码
ffrt_wait



声明

  1. void ffrt_wait_deps(ffrt_deps_t* deps);
  2. void ffrt_wait();
复制代码
参数

deps

返回值


形貌


样例

recursive fibonacci
串行版的fibonacci 可以实现为:
  1. #include <stdio.h>
  2. void fib(int x, int* y) {
  3.     if (x <= 1) {
  4.         *y = x;
  5.     } else {
  6.         int y1, y2;
  7.         fib(x - 1, &y1);
  8.         fib(x - 2, &y2);
  9.         *y = y1 + y2;
  10.     }
  11. }
  12. int main(int narg, char** argv)
  13. {
  14.     int r;
  15.     fib(10, &r);
  16.     printf("fibonacci 10: %d\n", r);
  17.     return 0;
  18. }
复制代码
若要利用 FFRT 实现并行(注,对于单纯的fibonacci,单个 Task 的计算量极小,不具有并行加快的意义,但这种调用pattern 对并行编程模子的灵活性考验黑白常高的),其中1种可行的实现为:
  1. #include <stdio.h>
  2. #include "ffrt.h"  //包含所有ffrt涉及的头文件
  3. typedef struct {
  4.     int x;
  5.     int* y;
  6. } fib_ffrt_s;
  7. typedef struct {
  8.     ffrt_function_header_t header;
  9.     ffrt_function_t func;
  10.     ffrt_function_t after_func;
  11.     void* arg;
  12. } c_function;
  13. static void ffrt_exec_function_wrapper(void* t)
  14. {
  15.     c_function* f = (c_function*)t;
  16.     if (f->func) {
  17.         f->func(f->arg);
  18.     }
  19. }
  20. static void ffrt_destroy_function_wrapper(void* t)
  21. {
  22.     c_function* f = (c_function*)t;
  23.     if (f->after_func) {
  24.         f->after_func(f->arg);
  25.     }
  26. }
  27. #define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1])
  28. static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func,
  29.     const ffrt_function_t after_func, void* arg)
  30. {
  31.     FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size,
  32.         size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size);
  33.     c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general);
  34.     f->header.exec = ffrt_exec_function_wrapper;
  35.     f->header.destroy = ffrt_destroy_function_wrapper;
  36.     f->func = func;
  37.     f->after_func = after_func;
  38.     f->arg = arg;
  39.     return (ffrt_function_header_t*)f;
  40. }
  41. static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func,
  42.     void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr)
  43. {
  44.     ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr);
  45. }
  46. #define ffrt_deps_define(name, dep1, ...) const void* __v_##name[] = {dep1, ##__VA_ARGS__}; \
  47.     ffrt_deps_t name = {sizeof(__v_##name) / sizeof(void*), __v_##name}
  48. void fib_ffrt(void* arg)
  49. {
  50.     fib_ffrt_s* p = (fib_ffrt_s*)arg;
  51.     int x = p->x;
  52.     int* y = p->y;
  53.     if (x <= 1) {
  54.         *y = x;
  55.     } else {
  56.         int y1, y2;
  57.         fib_ffrt_s s1 = {x - 1, &y1};
  58.         fib_ffrt_s s2 = {x - 2, &y2};
  59.         ffrt_deps_define(dx, &x);
  60.         ffrt_deps_define(dy1, &y1);
  61.         ffrt_deps_define(dy2, &y2);
  62.         ffrt_deps_define(dy12, &y1, &y2);
  63.         ffrt_submit_c(fib_ffrt, NULL, &s1, &dx, &dy1, NULL);
  64.         ffrt_submit_c(fib_ffrt, NULL, &s2, &dx, &dy2, NULL);
  65.         ffrt_wait_deps(&dy12);
  66.         *y = y1 + y2;
  67.     }
  68. }
  69. int main(int narg, char** argv)
  70. {
  71.     int r;
  72.     fib_ffrt_s s = {10, &r};
  73.     ffrt_deps_define(dr, &r);
  74.     ffrt_submit_c(fib_ffrt, NULL, &s, NULL, &dr, NULL);
  75.     ffrt_wait_deps(&dr);
  76.     printf("fibonacci 10: %d\n", r);
  77.     return 0;
  78. }
复制代码
解析:

   以上实现,因为需要用户显式管理数据生命周期和函数入参打包两个因素,所以使得代码实现非常复杂。
  ffrt_deps_t


声明

  1. typedef enum {
  2.     ffrt_dependence_data,
  3.     ffrt_dependence_task,
  4. } ffrt_dependence_type_t;
  5. typedef struct {
  6.     ffrt_dependence_type_t type;
  7.     const void* ptr;
  8. } ffrt_dependence_t;
  9. typedef struct {
  10.     uint32_t len;
  11.     const ffrt_dependence_t* items;
  12. } ffrt_deps_t;
复制代码
参数

len

item

type

ptr

返回值


形貌


样例


  1. // 创建数据依赖的ffrt_deps_t
  2. int x = 0;
  3. const std::vector<ffrt_dependence_t> in_deps = {{ffrt_dependence_data, &x}};
  4. ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.data()};
  5. // 提交某个返回handle任务
  6. ffrt_task_handle_t task = ffrt_submit_h_base(
  7.         ffrt_create_function_wrapper(OnePlusForTest, NULL, &a), NULL, NULL, &attr);
  8. // 创建任务依赖的ffrt_deps_t
  9. const std::vector<ffrt_dependence_t> wait_deps = {{ffrt_dependence_task, task}};
  10. ffrt_deps_t wait{static_cast<uint32_t>(wait_deps.size()), wait_deps.data()};
复制代码
ffrt_task_attr_t



声明

  1. typedef enum {
  2.     ffrt_qos_inherent = -1,
  3.     ffrt_qos_background,
  4.     ffrt_qos_utility,
  5.     ffrt_qos_default,
  6.     ffrt_qos_user_initiated,
  7. } ffrt_qos_default_t;
  8. typedef int ffrt_qos_t;
  9. typedef struct {
  10.     uint32_t storage[(ffrt_task_attr_storage_size + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
  11. } ffrt_task_attr_t;
  12. typedef void* ffrt_task_handle_t;
  13. int ffrt_task_attr_init(ffrt_task_attr_t* attr);
  14. void ffrt_task_attr_destroy(ffrt_task_attr_t* attr);
  15. void ffrt_task_attr_set_qos(ffrt_task_attr_t* attr, ffrt_qos_t qos);
  16. ffrt_qos_t ffrt_task_attr_get_qos(const ffrt_task_attr_t* attr);
  17. void ffrt_task_attr_set_name(ffrt_task_attr_t* attr, const char* name);
  18. const char* ffrt_task_attr_get_name(const ffrt_task_attr_t* attr);
  19. void ffrt_task_attr_set_delay(ffrt_task_attr_t* attr, uint64_t delay_us);
  20. uint64_t ffrt_task_attr_get_delay(const ffrt_task_attr_t* attr);
复制代码
参数

attr

qos

delay_us

返回值


形貌


样例


  1. #include <stdio.h>
  2. #include "ffrt.h"
  3. void my_print(void* arg)
  4. {
  5.     printf("hello ffrt\n");
  6. }
  7. typedef struct {
  8.     ffrt_function_header_t header;
  9.     ffrt_function_t func;
  10.     ffrt_function_t after_func;
  11.     void* arg;
  12. } c_function;
  13. static void ffrt_exec_function_wrapper(void* t)
  14. {
  15.     c_function* f = (c_function*)t;
  16.     if (f->func) {
  17.         f->func(f->arg);
  18.     }
  19. }
  20. static void ffrt_destroy_function_wrapper(void* t)
  21. {
  22.     c_function* f = (c_function*)t;
  23.     if (f->after_func) {
  24.         f->after_func(f->arg);
  25.     }
  26. }
  27. #define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1])
  28. static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func,
  29.     const ffrt_function_t after_func, void* arg)
  30. {
  31.     FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size,
  32.         size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size);
  33.     c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general);
  34.     f->header.exec = ffrt_exec_function_wrapper;
  35.     f->header.destroy = ffrt_destroy_function_wrapper;
  36.     f->func = func;
  37.     f->after_func = after_func;
  38.     f->arg = arg;
  39.     return (ffrt_function_header_t*)f;
  40. }
  41. static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func,
  42.     void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr)
  43. {
  44.     ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr);
  45. }
  46. int main(int narg, char** argv)
  47. {
  48.     ffrt_task_attr_t attr;
  49.     ffrt_task_attr_init(&attr);
  50.     ffrt_task_attr_set_qos(&attr, ffrt_qos_background);
  51.     ffrt_task_attr_set_delay(&attr, 10000);
  52.     ffrt_submit_c(my_print, NULL, NULL, NULL, NULL, &attr);
  53.     ffrt_task_attr_destroy(&attr);
  54.     ffrt_wait();
  55.     return 0;
  56. }
复制代码
ffrt_submit_h_base



声明

  1. typedef void* ffrt_task_handle_t;
  2. ffrt_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);
  3. void ffrt_task_handle_destroy(ffrt_task_handle_t handle);
复制代码
参数

func

in_deps

out_deps

attr

返回值


形貌


样例

  1. #include <stdio.h>
  2. #include "ffrt.h"
  3. void func0(void* arg)
  4. {
  5.     printf("hello ");
  6. }
  7. void func1(void* arg)
  8. {
  9.     (*(int*)arg)++;
  10. }
  11. void func2(void* arg)
  12. {
  13.     printf("world, x = %d\n", *(int*)arg);
  14. }
  15. void func3(void* arg)
  16. {
  17.     printf("handle wait");
  18.     (*(int*)arg)++;
  19. }
  20. typedef struct {
  21.     ffrt_function_header_t header;
  22.     ffrt_function_t func;
  23.     ffrt_function_t after_func;
  24.     void* arg;
  25. } c_function;
  26. static void ffrt_exec_function_wrapper(void* t)
  27. {
  28.     c_function* f = (c_function*)t;
  29.     if (f->func) {
  30.         f->func(f->arg);
  31.     }
  32. }
  33. static void ffrt_destroy_function_wrapper(void* t)
  34. {
  35.     c_function* f = (c_function*)t;
  36.     if (f->after_func) {
  37.         f->after_func(f->arg);
  38.     }
  39. }
  40. #define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1])
  41. static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func,
  42.     const ffrt_function_t after_func, void* arg)
  43. {
  44.     FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size,
  45.         size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size);
  46.     c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general);
  47.     f->header.exec = ffrt_exec_function_wrapper;
  48.     f->header.destroy = ffrt_destroy_function_wrapper;
  49.     f->func = func;
  50.     f->after_func = after_func;
  51.     f->arg = arg;
  52.     return (ffrt_function_header_t*)f;
  53. }
  54. static inline ffrt_task_handle_t ffrt_submit_h_c(ffrt_function_t func, const ffrt_function_t after_func,
  55.     void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr)
  56. {
  57.     return ffrt_submit_h_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr);
  58. }
  59. static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func,
  60.     void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr)
  61. {
  62.     ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr);
  63. }
  64. int main(int narg, char** argv)
  65. {  
  66.     // handle work with submit
  67.     ffrt_task_handle_t h = ffrt_submit_h_c(func0, NULL, NULL, NULL, NULL, NULL); // not need some data in this task
  68.     int x = 1;
  69.     const std::vector<ffrt_dependence_t> in_deps = {{ffrt_dependence_data, &x}};
  70.     ffrt_deps_t d2{static_cast<uint32_t>(in_deps.size()), in_deps.data()};
  71.     const std::vector<ffrt_dependence_t> out_deps = {{ffrt_dependence_data, &x}};
  72.     ffrt_deps_t d1{static_cast<uint32_t>(out_deps.size()), out_deps.data()};
  73.     ffrt_submit_c(func1, NULL, &x, NULL, &d1, NULL);
  74.     ffrt_submit_c(func2, NULL, &x, &d2, NULL, NULL); // this task depend x and h
  75.     ffrt_task_handle_destroy(h);
  76.    
  77.     // handle work with wait
  78.     ffrt_task_handle_t h2 = ffrt_submit_h_c(func3, NULL, &x, NULL, NULL, NULL);
  79.     const std::vector<ffrt_dependence_t> wait_deps = {{ffrt_dependence_task, h2}};
  80.     ffrt_deps_t d3{static_cast<uint32_t>(wait_deps.size()), wait_deps.data()};
  81.     ffrt_wait_deps(&d3);
  82.     ffrt_task_handle_destroy(h2);
  83.     printf("x = %d", x);
  84.     ffrt_wait();
  85.     return 0;
  86. }
复制代码

  1. hello world, x = 2
  2. handle wait
  3. x = 3
复制代码
ffrt_this_task_get_id



声明

  1. uint64_t ffrt_this_task_get_id();
复制代码
参数


返回值


形貌


样例


ffrt_this_task_update_qos



声明

  1. int ffrt_this_task_update_qos(ffrt_qos_t qos);
复制代码
参数


返回值


形貌


样例


串行队列



ffrt_queue_attr_t

声明

  1. typedef struct {
  2.     uint32_t storage[(ffrt_queue_attr_storage_size + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
  3. } ffrt_queue_attr_t;
  4. int ffrt_queue_attr_init(ffrt_queue_attr_t* attr);
  5. void ffrt_queue_attr_destroy(ffrt_queue_attr_t* attr);
复制代码
参数

attr

返回值


形貌


样例

参考ffrt_queue_t章节的样例。
ffrt_queue_t

声明

  1. typedef enum { ffrt_queue_serial, ffrt_queue_max } ffrt_queue_type_t;
  2. typedef void* ffrt_queue_t;
  3. ffrt_queue_t ffrt_queue_create(ffrt_queue_type_t type, const char* name, const ffrt_queue_attr_t* attr)
  4. void ffrt_queue_destroy(ffrt_queue_t queue)
复制代码
参数

type

name

attr

返回值


形貌


样例

  1. #include <stdio.h>
  2. #include "ffrt.h"
  3. using namespace std;
  4. template<class T>
  5. struct Function {
  6.     template<class CT>
  7.     Function(ffrt_function_header_t h, CT&& c) : header(h), closure(std::forward<CT>(c)) {}
  8.     ffrt_function_header_t header;
  9.     T closure;
  10. };
  11. template<class T>
  12. void ExecFunctionWrapper(void* t)
  13. {
  14.     auto f = reinterpret_cast<Function<std::decay_t<T>>*>(t);
  15.     f->closure();
  16. }
  17. template<class T>
  18. void DestroyFunctionWrapper(void* t)
  19. {
  20.     auto f = reinterpret_cast<Function<std::decay_t<T>>*>(t);
  21.     f->closure = nullptr;
  22. }
  23. template<class T>
  24. static inline ffrt_function_header_t* create_function_wrapper(T&& func,
  25.     ffrt_function_kind_t kind = ffrt_function_kind_general)
  26. {
  27.     using function_type = Function<std::decay_t<T>>;
  28.     auto p = ffrt_alloc_auto_managed_function_storage_base(kind);
  29.     auto f =
  30.         new (p)function_type({ ExecFunctionWrapper<T>, DestroyFunctionWrapper<T>, { 0 } }, std::forward<T>(func));
  31.     return reinterpret_cast<ffrt_function_header_t*>(f);
  32. }
  33. int main(int narg, char** argv)
  34. {
  35.     ffrt_queue_attr_t queue_attr;
  36.     (void)ffrt_queue_attr_init(&queue_attr);
  37.     ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_serial, "test_queue", &queue_attr);
  38.     ffrt_queue_submit(queue_handle, create_function_wrapper([]() {printf("Task done.\n");}, ffrt_function_kind_queue), nullptr);
  39.     ffrt_queue_attr_destroy(&queue_attr);
  40.     ffrt_queue_destroy(queue_handle);
  41. }
复制代码
同步原语

ffrt_mutex_t



声明

  1. typedef enum {
  2.     ffrt_error = -1,
  3.     ffrt_success = 0,
  4.     ffrt_error_nomem = ENOMEM,
  5.     ffrt_error_timedout = ETIMEDOUT,
  6.     ffrt_error_busy = EBUSY,
  7.     ffrt_error_inval = EINVAL
  8. } ffrt_error_t;
  9. struct ffrt_mutex_t;
  10. int ffrt_mutex_init(ffrt_mutex_t* mutex, const ffrt_mutexattr_t* attr);
  11. int ffrt_mutex_lock(ffrt_mutex_t* mutex);
  12. int ffrt_mutex_unlock(ffrt_mutex_t* mutex);
  13. int ffrt_mutex_trylock(ffrt_mutex_t* mutex);
  14. int ffrt_mutex_destroy(ffrt_mutex_t* mutex);
复制代码
参数

attr

mutex

返回值


形貌


样例

  1. #include <stdio.h>
  2. #include "ffrt.h"
  3. typedef struct {
  4.     int* sum;
  5.     ffrt_mutex_t* mtx;
  6. } tuple;
  7. void func(void* arg)
  8. {
  9.     tuple* t = (tuple*)arg;
  10.    
  11.     int ret = ffrt_mutex_lock(t->mtx);
  12.     if (ret != ffrt_success) {
  13.         printf("error\n");
  14.     }
  15.     (*t->sum)++;
  16.     ret = ffrt_mutex_unlock(t->mtx);
  17.     if (ret != ffrt_success) {
  18.         printf("error\n");
  19.     }
  20. }
  21. typedef struct {
  22.     ffrt_function_header_t header;
  23.     ffrt_function_t func;
  24.     ffrt_function_t after_func;
  25.     void* arg;
  26. } c_function;
  27. static void ffrt_exec_function_wrapper(void* t)
  28. {
  29.     c_function* f = (c_function*)t;
  30.     if (f->func) {
  31.         f->func(f->arg);
  32.     }
  33. }
  34. static void ffrt_destroy_function_wrapper(void* t)
  35. {
  36.     c_function* f = (c_function*)t;
  37.     if (f->after_func) {
  38.         f->after_func(f->arg);
  39.     }
  40. }
  41. #define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1])
  42. static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func,
  43.     const ffrt_function_t after_func, void* arg)
  44. {
  45.     FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size,
  46.         size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size);
  47.     c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general);
  48.     f->header.exec = ffrt_exec_function_wrapper;
  49.     f->header.destroy = ffrt_destroy_function_wrapper;
  50.     f->func = func;
  51.     f->after_func = after_func;
  52.     f->arg = arg;
  53.     return (ffrt_function_header_t*)f;
  54. }
  55. static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func,
  56.     void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr)
  57. {
  58.     ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr);
  59. }
  60. void ffrt_mutex_task()
  61. {
  62.     int sum = 0;
  63.     ffrt_mutex_t mtx;
  64.     tuple t = {&sum, &mtx};
  65.     int ret = ffrt_mutex_init(&mtx, NULL);
  66.     if (ret != ffrt_success) {
  67.         printf("error\n");
  68.     }
  69.     for (int i = 0; i < 10; i++) {
  70.         ffrt_submit_c(func, NULL, &t, NULL, NULL, NULL);
  71.     }
  72.     ffrt_mutex_destroy(&mtx);
  73.     ffrt_wait();
  74.     printf("sum = %d", sum);
  75. }
  76. int main(int narg, char** argv)
  77. {
  78.     int r;
  79.     ffrt_submit_c(ffrt_mutex_task, NULL, NULL, NULL, NULL, NULL);
  80.     ffrt_wait();
  81.     return 0;
  82. }
复制代码
预期输出为:
  1. sum=10
复制代码

ffrt_cond_t



声明

  1. typedef enum {
  2.     ffrt_error = -1,
  3.     ffrt_success = 0,
  4.     ffrt_error_nomem = ENOMEM,
  5.     ffrt_error_timedout = ETIMEDOUT,
  6.     ffrt_error_busy = EBUSY,
  7.     ffrt_error_inval = EINVAL
  8. } ffrt_error_t;
  9. struct ffrt_cond_t;
  10. int ffrt_cond_init(ffrt_cond_t* cond, const ffrt_condattr_t* attr);
  11. int ffrt_cond_signal(ffrt_cond_t* cond);
  12. int ffrt_cond_broadcast(ffrt_cond_t* cond);
  13. int ffrt_cond_wait(ffrt_cond_t*cond, ffrt_mutex_t* mutex);
  14. int ffrt_cond_timedwait(ffrt_cond_t* cond, ffrt_mutex_t* mutex, const struct timespec* time_point);
  15. int ffrt_cond_destroy(ffrt_cond_t* cond);
复制代码
参数

cond

attr

mutex

time_point

返回值


形貌


样例

  1. #include <stdio.h>
  2. #include "ffrt.h"
  3. typedef struct {
  4.     ffrt_cond_t* cond;
  5.     int* a;
  6.     ffrt_mutex_t* lock_;
  7. } tuple;
  8. void func1(void* arg)
  9. {
  10.     tuple* t = (tuple*)arg;
  11.     int ret = ffrt_mutex_lock(t->lock_);
  12.     if (ret != ffrt_success) {
  13.         printf("error\n");
  14.     }
  15.     while (*t->a != 1) {
  16.         ret = ffrt_cond_wait(t->cond, t->lock_);
  17.         if (ret != ffrt_success) {
  18.             printf("error\n");
  19.         }
  20.     }
  21.     ret = ffrt_mutex_unlock(t->lock_);
  22.     if (ret != ffrt_success) {
  23.         printf("error\n");
  24.     }
  25.     printf("a = %d", *(t->a));
  26. }
  27. void func2(void* arg)
  28. {
  29.     tuple* t = (tuple*)arg;
  30.     int ret = ffrt_mutex_lock(t->lock_);
  31.     if (ret != ffrt_success) {
  32.         printf("error\n");
  33.     }
  34.     *(t->a) = 1;
  35.     ret = ffrt_cond_signal(t->cond);
  36.     if (ret != ffrt_success) {
  37.         printf("error\n");
  38.     }
  39.     ret = ffrt_mutex_unlock(t->lock_);
  40.     if (ret != ffrt_success) {
  41.         printf("error\n");
  42.     }
  43. }
  44. typedef struct {
  45.     ffrt_function_header_t header;
  46.     ffrt_function_t func;
  47.     ffrt_function_t after_func;
  48.     void* arg;
  49. } c_function;
  50. static void ffrt_exec_function_wrapper(void* t)
  51. {
  52.     c_function* f = (c_function*)t;
  53.     if (f->func) {
  54.         f->func(f->arg);
  55.     }
  56. }
  57. static void ffrt_destroy_function_wrapper(void* t)
  58. {
  59.     c_function* f = (c_function*)t;
  60.     if (f->after_func) {
  61.         f->after_func(f->arg);
  62.     }
  63. }
  64. #define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1])
  65. static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func,
  66.     const ffrt_function_t after_func, void* arg)
  67. {
  68.     FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size,
  69.         size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size);
  70.     c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general);
  71.     f->header.exec = ffrt_exec_function_wrapper;
  72.     f->header.destroy = ffrt_destroy_function_wrapper;
  73.     f->func = func;
  74.     f->after_func = after_func;
  75.     f->arg = arg;
  76.     return (ffrt_function_header_t*)f;
  77. }
  78. static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func,
  79.     void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr)
  80. {
  81.     ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr);
  82. }
  83. void ffrt_cv_task()
  84. {
  85.     ffrt_cond_t cond;
  86.     int ret = ffrt_cond_init(&cond, NULL);
  87.     if (ret != ffrt_success) {
  88.         printf("error\n");
  89.     }
  90.     int a = 0;
  91.     ffrt_mutex_t lock_;
  92.     tuple t = {&cond, &a, &lock_};
  93.     ret = ffrt_mutex_init(&lock_, NULL);
  94.     if (ret != ffrt_success) {
  95.         printf("error\n");
  96.     }
  97.     ffrt_submit_c(func1, NULL, &t, NULL, NULL, NULL);
  98.     ffrt_submit_c(func2, NULL, &t, NULL, NULL, NULL);
  99.     ffrt_wait();
  100.     ffrt_cond_destroy(&cond);
  101.     ffrt_mutex_destroy(&lock_);
  102. }
  103. int main(int narg, char** argv)
  104. {
  105.     ffrt_submit_c(ffrt_cv_task, NULL, NULL, NULL, NULL, NULL);
  106.     ffrt_wait();
  107.     return 0;
  108. }
复制代码
预期输出为:
  1. a=1
复制代码

杂项

ffrt_usleep



声明

  1. int ffrt_usleep(uint64_t usec);
复制代码
参数

usec

返回值


形貌


样例

  1. #include <time.h>
  2. #include <stdio.h>
  3. #include "ffrt.h"
  4. void func(void* arg)
  5. {
  6.     printf("Time: %s", ctime(&(time_t){time(NULL)}));
  7.     ffrt_usleep(2000000); // 睡眠 2 秒
  8.     printf("Time: %s", ctime(&(time_t){time(NULL)}));
  9. }
  10. typedef struct {
  11.     ffrt_function_header_t header;
  12.     ffrt_function_t func;
  13.     ffrt_function_t after_func;
  14.     void* arg;
  15. } c_function;
  16. static void ffrt_exec_function_wrapper(void* t)
  17. {
  18.     c_function* f = (c_function*)t;
  19.     if (f->func) {
  20.         f->func(f->arg);
  21.     }
  22. }
  23. static void ffrt_destroy_function_wrapper(void* t)
  24. {
  25.     c_function* f = (c_function*)t;
  26.     if (f->after_func) {
  27.         f->after_func(f->arg);
  28.     }
  29. }
  30. #define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1])
  31. static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func,
  32.     const ffrt_function_t after_func, void* arg)
  33. {
  34.     FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size,
  35.         size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size);
  36.     c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general);
  37.     f->header.exec = ffrt_exec_function_wrapper;
  38.     f->header.destroy = ffrt_destroy_function_wrapper;
  39.     f->func = func;
  40.     f->after_func = after_func;
  41.     f->arg = arg;
  42.     return (ffrt_function_header_t*)f;
  43. }
  44. static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func,
  45.     void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr)
  46. {
  47.     ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr);
  48. }
  49. int main(int narg, char** argv)
  50. {
  51.     ffrt_submit_c(func, NULL, NULL, NULL, NULL, NULL);
  52.     ffrt_wait();
  53.     return 0;
  54. }
复制代码
ffrt_yield



声明

  1. void ffrt_yield();
复制代码
参数


返回值


形貌


样例


开辟步调

以下步调形貌了怎样利用FFRT提供的Native API接口,创建并行任务和串行队列任务以及烧毁相应资源。
添加动态链接库
CMakeLists.txt中添加以下lib:
  1. libffrt.z.so
复制代码
头文件
  1. #include "ffrt/task.h"
  2. #include "ffrt/type_def.h"
  3. #include "ffrt/condition_variable.h"
  4. #include "ffrt/mutex.h"
  5. #include "ffrt/queue.h"
  6. #include "ffrt/sleep.h"
复制代码
  1. // 第一种使用模板,支持C++
  2. template<class T>
  3. struct Function {
  4.     template<class CT>
  5.     Function(ffrt_function_header_t h, CT&& c) : header(h), closure(std::forward<CT>(c)) {}
  6.     ffrt_function_header_t header;
  7.     T closure;
  8. };
  9. template<class T>
  10. void ExecFunctionWrapper(void* t)
  11. {
  12.     auto f = reinterpret_cast<Function<std::decay_t<T>>*>(t);
  13.     f->closure();
  14. }
  15. template<class T>
  16. void DestroyFunctionWrapper(void* t)
  17. {
  18.     auto f = reinterpret_cast<Function<std::decay_t<T>>*>(t);
  19.     f->closure = nullptr;
  20. }
  21. template<class T>
  22. static inline ffrt_function_header_t* create_function_wrapper(T&& func,
  23.     ffrt_function_kind_t kind = ffrt_function_kind_general)
  24. {
  25.     using function_type = Function<std::decay_t<T>>;
  26.     auto p = ffrt_alloc_auto_managed_function_storage_base(kind);
  27.     auto f =
  28.         new (p)function_type({ ExecFunctionWrapper<T>, DestroyFunctionWrapper<T>, { 0 } }, std::forward<T>(func));
  29.     return reinterpret_cast<ffrt_function_header_t*>(f);
  30. }
  31. // 第二种创建方式
  32. typedef struct {
  33.     ffrt_function_header_t header;
  34.     ffrt_function_t func;
  35.     ffrt_function_t after_func;
  36.     void* arg;
  37. } CFunction;
  38. static void FfrtExecFunctionWrapper(void* t)
  39. {
  40.     CFunction* f = static_cast<CFunction*>(t);
  41.     if (f->func) {
  42.         f->func(f->arg);
  43.     }
  44. }
  45. static void FfrtDestroyFunctionWrapper(void* t)
  46. {
  47.     CFunction* f = static_cast<CFunction*>(t);
  48.     if (f->after_func) {
  49.         f->after_func(f->arg);
  50.     }
  51. }
  52. #define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1])
  53. static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func,
  54.     const ffrt_function_t after_func, void* arg, ffrt_function_kind_t kind_t = ffrt_function_kind_general)
  55. {
  56.     FFRT_STATIC_ASSERT(sizeof(CFunction) <= ffrt_auto_managed_function_storage_size,
  57.         size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size);
  58.     CFunction* f = static_cast<CFunction*>(ffrt_alloc_auto_managed_function_storage_base(kind_t));
  59.     f->header.exec = FfrtExecFunctionWrapper;
  60.     f->header.destroy = FfrtDestroyFunctionWrapper;
  61.     f->func = func;
  62.     f->after_func = after_func;
  63.     f->arg = arg;
  64.     return reinterpret_cast<ffrt_function_header_t*>(f);
  65. }
  66. // 样例:待提交执行的函数
  67. void OnePlusForTest(void* arg)
  68. {
  69.     (*static_cast<int*>(arg)) += 1;
  70. }
复制代码
用户提交任务时可以设置任务属性,包罗qos优先级,名称等,具体可参考接口文档。
  1. // ******初始化并行任务属性******
  2. ffrt_task_attr_t attr;
  3. ffrt_task_attr_init(&attr);
  4. // ******创建串行队列******
  5. // 创建串行队列的属性
  6. ffrt_queue_attr_t queue_attr;
  7. // 创建串行队列的handle
  8. ffrt_queue_t queue_handle;
  9. // 初始化队列属性
  10. (void)ffrt_queue_attr_init(&queue_attr);
  11. // 如有需要,设置指定优先级
  12. ffrt_queue_attr_set_qos(&queue_attr, static_cast<ffrt_qos_t>(ffrt_qos_inherit));
  13. // 如有需要,设置超时时间(ms)
  14. ffrt_queue_attr_set_timeout(&queue_attr, 10000);
  15. // 如有需要,设置超时回调
  16. int x = 0;
  17. ffrt_queue_attr_set_callback(&queue_attr, ffrt_create_function_wrapper(OnePlusForTest, NULL, &x,
  18.     ffrt_function_kind_queue));
  19. // 基于属性,初始化队列
  20. queue_handle = ffrt_queue_create(ffrt_queue_serial, "test_queue", &queue_attr);
复制代码
  1. int a = 0;
  2. // ******并行任务******
  3. // 提交不带handle返回值的并行任务
  4. ffrt_submit_base(ffrt_create_function_wrapper(OnePlusForTest, NULL, &a), NULL, NULL, &attr);
  5. // 提交带handle返回值的并行任务
  6. ffrt_task_handle_t task = ffrt_submit_h_base(
  7.     ffrt_create_function_wrapper(OnePlusForTest, NULL, &a), NULL, NULL, &attr);
  8. // ******串行任务******
  9. // 提交不返回handle的串行队列任务
  10. ffrt_queue_submit(queue_handle, ffrt_create_function_wrapper(OnePlusForTest, nullptr, &a,
  11.     ffrt_function_kind_queue), nullptr);
  12. // 提交带handle的串行队列任务
  13. ffrt_task_handle_t handle = ffrt_queue_submit_h(queue_handle,
  14.     ffrt_create_function_wrapper(OnePlusForTest, nullptr, &a, ffrt_function_kind_queue), nullptr);
  15. // 如果需要等待执行结果,则调用wait
  16. const std::vector<ffrt_dependence_t> wait_deps = {{ffrt_dependence_task, task}};
  17. ffrt_deps_t wait{static_cast<uint32_t>(wait_deps.size()), wait_deps.data()};
  18. ffrt_wait_deps(&wait);
  19. ffrt_queue_wait(handle);
复制代码
  1. // ******销毁并行任务******
  2. ffrt_task_attr_destroy(&attr);
  3. ffrt_task_handle_destroy(task);
  4. // ******销毁串行队列任务******
  5. // 先销毁任务handle,再销毁队列
  6. ffrt_queue_attr_destroy(&queue_attr);
  7. ffrt_task_handle_destroy(handle);
  8. ffrt_queue_destroy(queue_handle);
复制代码
利用发起

发起1: 函数化

根本头脑:计算过程函数化

   做到纯函数的好处在于:1. 可以或许最大化发掘并行度,2.避免DataRace和锁的标题。
  在现实中,可以根据场景放松纯函数的约束,但前提是:

发起2: 利用FFRT提供的替换API


发起3: Deadline机制


发起4: 从线程模子迁移


已知限定

C API中初始化ffrt对象后,对象的置空与烧毁由用户负责


  1. #include "ffrt.h"
  2. void abnormal_case_1()
  3. {
  4.     ffrt_task_handle_t h = ffrt_submit_h_base([](){printf("Test task running...\n");}, NULL, NULL, NULL, NULL, NULL);
  5.     ...
  6.     ffrt_task_handle_destroy(h);
  7.     ffrt_task_handle_destroy(h); // double free
  8. }
复制代码

  1. #include "ffrt.h"
  2. void abnormal_case_2()
  3. {
  4.     ffrt_task_handle_t h = ffrt_submit_h_base([](){printf("Test task running...\n");}, NULL, NULL, NULL, NULL, NULL);
  5.     ...
  6.     // memory leak
  7. }
复制代码

  1. #include "ffrt.h"
  2. void normal_case()
  3. {
  4.     ffrt_task_handle_t h = ffrt_submit_h_base([](){printf("Test task running...\n");}, NULL, NULL, NULL, NULL, NULL);
  5.     ...
  6.     ffrt_task_handle_destroy(h);
  7.     h = nullptr; // if necessary
  8. }
复制代码
为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开辟技能,这边特意整理了《鸿蒙开辟学习手册》(共计890页),希望对大家有所资助:https://qr21.cn/FV7h05
《鸿蒙开辟学习手册》:

怎样快速入门:https://qr21.cn/FV7h05


开辟底子知识:https://qr21.cn/FV7h05


基于ArkTS 开辟:https://qr21.cn/FV7h05


鸿蒙开辟面试真题(含参考答案):https://qr18.cn/F781PH


鸿蒙开辟面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开辟必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开辟体系底层方向
5.鸿蒙音视频开辟方向
6.鸿蒙车载开辟方向
7.鸿蒙南向开辟方向


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4