# Function Flow Runtime 开呿Œ‡å¯¼ ## åœºæ™¯ä»‹ç» Function Flow编程模型是一ç§åŸºäºŽä»»åŠ¡å’Œæ•°æ®é©±åŠ¨çš„å¹¶å‘编程模型,å…许开å‘者通过任务åŠå…¶ä¾èµ–关系æè¿°çš„æ–¹å¼è¿›è¡Œåº”用开å‘。FFRT(Function Flowè¿è¡Œæ—¶ï¼‰æ˜¯æ”¯æŒFunction Flow编程模型的软件è¿è¡Œæ—¶åº“,用于调度执行开å‘者基于Function Flow编程模型开å‘的应用。通过Function Flow编程模型和FFRT,开å‘者å¯ä¸“注于应用功能开å‘,由FFRT在è¿è¡Œæ—¶æ ¹æ®ä»»åŠ¡ä¾èµ–状æ€å’Œå¯ç”¨æ‰§è¡Œèµ„æºè‡ªåЍ并å‘调度和执行任务。 本文用于指导开å‘者基于Function Flow编程模型和FFRT实现并行编程。 ## 接å£è¯´æ˜Ž | 接å£å | æè¿° | | ------------------------------------------------------------ | ------------------------------------------------------------ | | 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_queue_attr_set_max_concurrency(ffrt_queue_attr_t* attr, const int max_concurrency) | 设置并行队列最大并å‘度。 | | ffrt_queue_attr_get_max_concurrency(ffrt_queue_attr_t* attr) | 获å–并行队列最大并å‘度。 | | ffrt_get_main_queue() | 获å–主线程队列。 | | ffrt_get_current_queue() | 获å–Worker线程队列。 | | 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_task_attr_set_queue_priority(ffrt_task_attr_t* attr, ffrt_queue_priority_t priority) | 设置并行队列任务优先级。 | | ffrt_task_attr_get_queue_priority(const ffrt_task_attr_t* attr) | 获å–并行队列任务优先级。 | | ffrt_this_task_get_qos() | 获å–任务qos。 | | 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_loop_create(ffrt_queue_t queue) | 创建loop对象。 | | ffrt_loop_destroy(ffrt_loop_t loop) | 销æ¯loop对象。 | | ffrt_loop_run(ffrt_loop_t loop) | å¯åЍloop循环。 | | ffrt_loop_stop(ffrt_loop_t loop) | åœæ¢loop循环。 | | ffrt_loop_epoll_ctl(ffrt_loop_t loop, int op, int fd, uint32_t events, void* data, ffrt_poller_cb cb) | 管ç†LOOP上的监å¬äº‹ä»¶ã€‚ | | ffrt_loop_timer_start(ffrt_loop_t loop, uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat) | 在LOOP上å¯åŠ¨ä¸€ä¸ªå®šæ—¶å™¨ã€‚ | | ffrt_loop_timer_stop(ffrt_loop_t loop, ffrt_timer_t handle) | 在LOOPä¸Šåœæ¢å®šæ—¶å™¨ã€‚ | | ffrt_timer_start(ffrt_qos_t qos, uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat) | å¯åЍtimer定时器。 | | ffrt_timer_stop(ffrt_qos_t qos, ffrt_timer_t handle); | åœæ¢timer定时器。 | ## å‡½æ•°ä»‹ç» ### ä»»åŠ¡ç®¡ç† #### ffrt_submit_base * 该接å£ä¸ºffrt动æ€åº“的导出接å£ï¼ŒåŸºäºŽæ¤å¯ä»¥å°è£…出C API ffrt_submit,满足二进制兼容。 ##### 声明 ```{.c} const int ffrt_auto_managed_function_storage_size = 64 + sizeof(ffrt_function_header_t); typedef enum { ffrt_function_kind_general, ffrt_function_kind_queue } ffrt_function_kind_t; void* ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_t kind); typedef void(*ffrt_function_t)(void*); typedef struct { ffrt_function_t exec; ffrt_function_t destroy; uint64_t reserve[2]; } ffrt_function_header_t; 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` * functionå类型,用于优化内部数æ®ç»“构,默认使用ffrt_function_kind_general类型。 `func` * CPU Function的指针,该指针执行的数æ®ç»“构,按照`ffrt_function_header_t`定义的æè¿°äº†è¯¥CPU Task如何执行和销æ¯çš„函数指针,FFRT通过这两个函数指针完æˆTask的执行和销æ¯ã€‚ `in_deps` * è¯¥å‚æ•°æ˜¯å¯é€‰çš„。 * è¯¥å‚æ•°ç”¨äºŽæè¿°è¯¥ä»»åŠ¡çš„è¾“å…¥ä¾èµ–,FFRT 通过数æ®çš„虚拟地å€ä½œä¸ºæ•°æ®çš„Signature æ¥å»ºç«‹ä¾èµ–。 `out_deps` * è¯¥å‚æ•°æ˜¯å¯é€‰çš„。 * è¯¥å‚æ•°ç”¨äºŽæè¿°è¯¥ä»»åŠ¡çš„è¾“å‡ºä¾èµ–。 * `注æ„`:该ä¾èµ–值本质上是一个数值,ffrt没办法区分该值是åˆç†çš„还是ä¸åˆç†çš„,会å‡å®šè¾“入的值是åˆç†çš„进行处ç†ï¼›ä½†ä¸å»ºè®®é‡‡ç”¨NULL,1, 2 ç‰å€¼æ¥å»ºç«‹ä¾èµ–关系,建议采用实际的内å˜åœ°å€ï¼Œå› 为å‰è€…使用ä¸å½“会建立起ä¸å¿…è¦çš„ä¾èµ–,影å“å¹¶å‘。 `attr` * è¯¥å‚æ•°æ˜¯å¯é€‰çš„。 * è¯¥å‚æ•°ç”¨äºŽæè¿°Task 的属性,比如qos ç‰ï¼Œè¯¦è§ [ffrt_task_attr_t](#ffrt_task_attr_t)ç« èŠ‚ã€‚ ##### 返回值 * 䏿¶‰åŠã€‚ ##### æè¿° * 建议用户对ffrt_submit_base进行å°è£…åŽè°ƒç”¨ï¼Œå…·ä½“å¯å‚è€ƒæ ·ä¾‹ã€‚ * **ffrt_submit_baseä½œä¸ºåº•å±‚èƒ½åŠ›ï¼Œä½¿ç”¨æ—¶éœ€è¦æ»¡è¶³ä»¥ä¸‹é™åˆ¶ï¼š** * ffrt_submit_baseå…¥å‚ä¸çš„func指针åªèƒ½é€šè¿‡ffrt_alloc_auto_managed_function_storage_base申请,且二者的调用需一一对应。 * ffrt_alloc_auto_managed_function_storage_base申请的内å˜ä¸ºffrt_auto_managed_function_storage_sizeå—节,其生命周期归ffrt管ç†ï¼Œåœ¨è¯¥taskç»“æŸæ—¶ï¼Œç”±FFRTè‡ªåŠ¨é‡Šæ”¾ï¼Œç”¨æˆ·æ— éœ€é‡Šæ”¾ã€‚ * ffrt_function_header_t ä¸å®šä¹‰äº†ä¸¤ä¸ªå‡½æ•°æŒ‡é’ˆï¼š * exec:用于æè¿°è¯¥Task如何被执行,当FFRTéœ€è¦æ‰§è¡Œè¯¥Taskæ—¶ç”±FFRT调用。 * destroy:用于æè¿°è¯¥Task如何被销æ¯ï¼Œå½“FFRT需è¦é”€æ¯è¯¥Taskæ—¶ç”±FFRT调用。 ##### æ ·ä¾‹ ```{.c} template<class T> struct function { template<class CT> function(ffrt_function_header_t h, CT&& c) : header(h), closure(std::forward<CT>(c)) {} ffrt_function_header_t header; T closure; }; template<class T> void exec_function_wrapper(void* t) { auto f = (function<std::decay_t<T>>*)t; f->closure(); } template<class T> void destroy_function_wrapper(void* t) { auto f = (function<std::decay_t<T>>*)t; f->closure = nullptr; } template<class T> inline ffrt_function_header_t* create_function_wrapper(T&& func) { using function_type = function<std::decay_t<T>>; static_assert(sizeof(function_type) <= ffrt_auto_managed_function_storage_size, "size of function must be less than ffrt_auto_managed_function_storage_size"); auto p = ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); auto f = new (p) function_type( {exec_function_wrapper<T>, destroy_function_wrapper<T>}, std::forward<T>(func)); return (ffrt_function_header_t*)f; } static inline void submit(std::function<void()>&& func) { return ffrt_submit_base(create_function_wrapper(std::move(func)), NULL, NULL, NULL); } ``` #### ffrt_wait <hr/> * åŒæ¥ç‰å¾…,与ffrt_submit_base é…åˆä½¿ç”¨ã€‚ * ç‰å¾…指定的数æ®è¢«ç”Ÿäº§å®Œæˆï¼Œæˆ–ç‰å¾…当å‰ä»»åŠ¡çš„æ‰€æœ‰å任务完æˆï¼Œåœ¨ä¸æ»¡è¶³æ¡ä»¶ä¹‹å‰ï¼Œå½“å‰çš„æ‰§è¡Œä¸Šä¸‹æ–‡è¢«suspend,在满足æ¡ä»¶åŽæ¢å¤æ‰§è¡Œã€‚ ##### 声明 ```{.c} void ffrt_wait_deps(ffrt_deps_t* deps); void ffrt_wait(); ``` ##### 傿•° `deps` * 需è¦ç‰å¾…被生产完æˆçš„æ•°æ®çš„虚拟地å€ï¼Œè¿™äº›åœ°å€å¯èƒ½ä½œä¸ºæŸäº›ä»»åŠ¡åœ¨submit æ—¶çš„out_deps,该ä¾èµ–的生æˆè§ffrt_deps_tç« èŠ‚ï¼Œç©ºæŒ‡é’ˆè¡¨ç¤ºæ— ä¾èµ–。 ##### 返回值 * 䏿¶‰åŠã€‚ ##### æè¿° * ffrt_wait_deps(deps) 用于ç‰å¾…deps指代的数æ®è¢«ç”Ÿäº§å®Œæˆæ‰èƒ½æ‰§è¡ŒåŽé¢çš„代ç 。 * ffrt_wait() 用于ç‰å¾…当å‰ä¸Šä¸‹æ–‡æäº¤çš„æ‰€æœ‰å任务(`注æ„:ä¸åŒ…括å™ä»»åŠ¡å’Œä¸‹çº§å任务`ï¼‰éƒ½å®Œæˆæ‰èƒ½æ‰§è¡ŒåŽé¢çš„代ç 。 * è¯¥æŽ¥å£æ”¯æŒåœ¨FFRT task 内部调用,也支æŒåœ¨FFRT task 外部调用。 * 在FFRT task 外部调用的wait 是OS 能够感知的ç‰å¾…,相对于FFRT task 内部调用的wait æ˜¯æ›´åŠ æ˜‚è´µçš„ï¼Œå› æ¤æˆ‘们希望尽å¯èƒ½è®©æ›´å¤šçš„wait å‘生在FFRT task 内部 ï¼Œè€Œä¸æ˜¯FFRT task 外部。 ##### æ ·ä¾‹ **recursive fibonacci** 串行版的fibonacci å¯ä»¥å®žçŽ°ä¸ºï¼š ```{.c} #include <stdio.h> void fib(int x, int* y) { if (x <= 1) { *y = x; } else { int y1, y2; fib(x - 1, &y1); fib(x - 2, &y2); *y = y1 + y2; } } int main(int narg, char** argv) { int r; fib(10, &r); printf("fibonacci 10: %d\n", r); return 0; } ``` è‹¥è¦ä½¿ç”¨ FFRT 实现并行(注,对于å•纯的fibonacci,å•个 Task çš„è®¡ç®—é‡æžå°ï¼Œä¸å…·æœ‰å¹¶è¡ŒåŠ é€Ÿçš„æ„义,但这ç§è°ƒç”¨pattern å¯¹å¹¶è¡Œç¼–ç¨‹æ¨¡åž‹çš„çµæ´»æ€§è€ƒéªŒæ˜¯éžå¸¸é«˜çš„),其ä¸1ç§å¯è¡Œçš„实现为: ```{.c} #include <stdio.h> #include "ffrt.h" //åŒ…å«æ‰€æœ‰ffrt涉åŠçš„头文件 typedef struct { int x; int* y; } fib_ffrt_s; typedef struct { ffrt_function_header_t header; ffrt_function_t func; ffrt_function_t after_func; void* arg; } c_function; static void ffrt_exec_function_wrapper(void* t) { c_function* f = (c_function*)t; if (f->func) { f->func(f->arg); } } static void ffrt_destroy_function_wrapper(void* t) { c_function* f = (c_function*)t; if (f->after_func) { f->after_func(f->arg); } } #define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1]) static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func, const ffrt_function_t after_func, void* arg) { FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size, size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size); c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); f->header.exec = ffrt_exec_function_wrapper; f->header.destroy = ffrt_destroy_function_wrapper; f->func = func; f->after_func = after_func; f->arg = arg; return (ffrt_function_header_t*)f; } static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func, void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr) { ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr); } void fib_ffrt(void* arg) { fib_ffrt_s* p = (fib_ffrt_s*)arg; int x = p->x; int* y = p->y; if (x <= 1) { *y = x; } else { int y1, y2; fib_ffrt_s s1 = {x - 1, &y1}; fib_ffrt_s s2 = {x - 2, &y2}; const std::vector<ffrt_dependence_t> dx_deps = {{ffrt_dependence_data, &x}}; ffrt_deps_t dx{static_cast<uint32_t>(dx_deps.size()), dx_deps.data()}; const std::vector<ffrt_dependence_t> dy1_deps = {{ffrt_dependence_data, &y1}}; ffrt_deps_t dy1{static_cast<uint32_t>(dy1_deps.size()), dy1_deps.data()}; const std::vector<ffrt_dependence_t> dy2_deps = {{ffrt_dependence_data, &y2}}; ffrt_deps_t dy2{static_cast<uint32_t>(dy2_deps.size()), dy2_deps.data()}; const std::vector<ffrt_dependence_t> dy12_deps = {{ffrt_dependence_data, &y1}, {ffrt_dependence_data, &y2}}; ffrt_deps_t dy12{static_cast<uint32_t>(dy12_deps.size()), dy12_deps.data()}; ffrt_submit_c(fib_ffrt, NULL, &s1, &dx, &dy1, NULL); ffrt_submit_c(fib_ffrt, NULL, &s2, &dx, &dy2, NULL); ffrt_wait_deps(&dy12); *y = y1 + y2; } } int main(int narg, char** argv) { int r; fib_ffrt_s s = {10, &r}; const std::vector<ffrt_dependence_t> dr_deps = {{ffrt_dependence_data, &r}}; ffrt_deps_t dr{static_cast<uint32_t>(dr_deps.size()), dr_deps.data()}; ffrt_submit_c(fib_ffrt, NULL, &s, NULL, &dr, NULL); ffrt_wait_deps(&dr); printf("fibonacci 10: %d\n", r); return 0; } ``` `è§£æž`: 1) å°†fibonacci (x-1)å’Œfibonacci (x-2) 作为2个Task æäº¤ç»™FFRT,在两个Task 完æˆä¹‹åŽå°†ç»“æžœç´¯åŠ ï¼› 2) 虽然å•个Task åªèƒ½æ‹†åˆ†æˆ2个SubTask 但是åTask å¯ä»¥ç»§ç»æ‹†åˆ†ï¼Œå› æ¤ï¼Œæ•´ä¸ªè®¡ç®—图的并行度是éžå¸¸é«˜çš„,Task 之间在FFRT 内部形æˆäº†ä¸€é¢—è°ƒç”¨æ ‘ï¼› <img src="figures/ffrtfigure2.png" style="zoom:100%" /> > ä»¥ä¸Šå®žçŽ°ï¼Œå› ä¸ºéœ€è¦ç”¨æˆ·æ˜¾å¼ç®¡ç†æ•°æ®ç”Ÿå‘½å‘¨æœŸå’Œå‡½æ•°å…¥å‚æ‰“åŒ…ä¸¤ä¸ªå› ç´ ï¼Œæ‰€ä»¥ä½¿å¾—ä»£ç å®žçŽ°å¼‚å¸¸å¤æ‚。 #### ffrt_deps_t * C APIä¸å¯¹ä¾èµ–数组的抽象,逻辑上ç‰åŒäºŽC++ APIä¸çš„`std::vector<void*>` ##### 声明 ```{.c} typedef enum { ffrt_dependence_data, ffrt_dependence_task, } ffrt_dependence_type_t; typedef struct { ffrt_dependence_type_t type; const void* ptr; } ffrt_dependence_t; typedef struct { uint32_t len; const ffrt_dependence_t* items; } ffrt_deps_t; ``` ##### 傿•° `len` * 所ä¾èµ–çš„Signature的个数,å–值大于ç‰äºŽ0。 `item` * len个Signatureçš„èµ·å§‹åœ°å€æŒ‡é’ˆã€‚ `type` * 当å‰ä¾èµ–为数æ®ä¾èµ–还是任务ä¾èµ–。 `ptr` * 所ä¾èµ–对应Signature内容的实际地å€ã€‚ ##### 返回值 * 䏿¶‰åŠã€‚ ##### æè¿° * item为len个Signature的起始指针,该指针å¯ä»¥æŒ‡å‘å †ç©ºé—´ï¼Œä¹Ÿå¯ä»¥æŒ‡å‘æ ˆç©ºé—´ï¼Œä½†æ˜¯è¦æ±‚分é…的空间大于ç‰äºŽlen * sizeof(ffrt_dependence_t)。 ##### æ ·ä¾‹ * 创建数æ®ä¾èµ–或者任务ä¾èµ–: ```{.c} // 创建数æ®ä¾èµ–çš„ffrt_deps_t int x = 0; const std::vector<ffrt_dependence_t> in_deps = {{ffrt_dependence_data, &x}}; ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.data()}; // æäº¤æŸä¸ªè¿”回handle任务 ffrt_task_handle_t task = ffrt_submit_h_base( ffrt_create_function_wrapper(OnePlusForTest, NULL, &a), NULL, NULL, &attr); // 创建任务ä¾èµ–çš„ffrt_deps_t const std::vector<ffrt_dependence_t> wait_deps = {{ffrt_dependence_task, task}}; ffrt_deps_t wait{static_cast<uint32_t>(wait_deps.size()), wait_deps.data()}; ``` #### ffrt_task_attr_t <hr/> * 定义task 的属性的辅助类,与ffrt_submit_base é…åˆä½¿ç”¨ã€‚ ##### 声明 ```{.c} typedef enum { ffrt_qos_inherent = -1, ffrt_qos_background, ffrt_qos_utility, ffrt_qos_default, ffrt_qos_user_initiated, } ffrt_qos_default_t; typedef int ffrt_qos_t; typedef struct { uint32_t storage[(ffrt_task_attr_storage_size + sizeof(uint32_t) - 1) / sizeof(uint32_t)]; } ffrt_task_attr_t; typedef void* ffrt_task_handle_t; int ffrt_task_attr_init(ffrt_task_attr_t* attr); void ffrt_task_attr_destroy(ffrt_task_attr_t* attr); void ffrt_task_attr_set_qos(ffrt_task_attr_t* attr, ffrt_qos_t qos); ffrt_qos_t ffrt_task_attr_get_qos(const ffrt_task_attr_t* attr); void ffrt_task_attr_set_name(ffrt_task_attr_t* attr, const char* name); const char* ffrt_task_attr_get_name(const ffrt_task_attr_t* attr); void ffrt_task_attr_set_delay(ffrt_task_attr_t* attr, uint64_t delay_us); uint64_t ffrt_task_attr_get_delay(const ffrt_task_attr_t* attr); ``` ##### 傿•° `attr` * 创建的taskså±žæ€§çš„å¥æŸ„。 `qos` * qos 设定的枚举类型。 * inherent 是一个qos 设定ç–略,代表å³å°†ffrt_submit çš„task çš„qos 继承当å‰task çš„qos。 `delay_us` * 任务延迟执行的时间,å•ä½ä¸ºus。 ##### 返回值 * 䏿¶‰åŠã€‚ ##### æè¿° * `attr`æ‰€ä¼ é€’çš„å†…å®¹ä¼šåœ¨ffrt_submit内部完æˆå–å˜ï¼Œffrt_submit返回åŽç”¨æˆ·å³å¯é”€æ¯ã€‚ * 约定: * 在submit 时,如果ä¸é€šè¿‡task_attr 设定qos,那么默认该æäº¤çš„taskçš„qos 为`ffrt_qos_default`。 * 在submit 时,如果通过task_attr 设定qos 为`ffrt_qos_inherent`,表示将该æäº¤çš„task çš„qos 与当å‰task çš„qos 相åŒï¼Œåœ¨FFRT task 外部æäº¤çš„属性为`ffrt_qos_inherent` çš„task,其qos 为`ffrt_qos_default`。 * 其他情况下,该æäº¤çš„task çš„qos 被设定为指定的值。 * ffrt_task_attr_t对象的置空和销æ¯ç”±ç”¨æˆ·å®Œæˆï¼Œå¯¹åŒä¸€ä¸ªffrt_task_attr_t仅能调用一次`ffrt_task_attr_destroy`,é‡å¤å¯¹åŒä¸€ä¸ªffrt_task_attr_t调用`ffrt_task_attr_destroy`,其行为是未定义的。 * 在`ffrt_task_attr_destroy`之åŽå†å¯¹task_attr进行访问,其行为是未定义的。 ##### æ ·ä¾‹ * æäº¤ä¸€ä¸ªqos 级别为background 的任务: ```{.c} #include <stdio.h> #include "ffrt.h" void my_print(void* arg) { printf("hello ffrt\n"); } typedef struct { ffrt_function_header_t header; ffrt_function_t func; ffrt_function_t after_func; void* arg; } c_function; static void ffrt_exec_function_wrapper(void* t) { c_function* f = (c_function*)t; if (f->func) { f->func(f->arg); } } static void ffrt_destroy_function_wrapper(void* t) { c_function* f = (c_function*)t; if (f->after_func) { f->after_func(f->arg); } } #define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1]) static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func, const ffrt_function_t after_func, void* arg) { FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size, size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size); c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); f->header.exec = ffrt_exec_function_wrapper; f->header.destroy = ffrt_destroy_function_wrapper; f->func = func; f->after_func = after_func; f->arg = arg; return (ffrt_function_header_t*)f; } static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func, void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr) { ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr); } int main(int narg, char** argv) { ffrt_task_attr_t attr; ffrt_task_attr_init(&attr); ffrt_task_attr_set_qos(&attr, ffrt_qos_background); ffrt_task_attr_set_delay(&attr, 10000); ffrt_submit_c(my_print, NULL, NULL, NULL, NULL, &attr); ffrt_task_attr_destroy(&attr); ffrt_wait(); return 0; } ``` #### ffrt_submit_h_base <hr/> * å‘调度器æäº¤ä¸€ä¸ªtask,与ffrt_submit_base 的差别在于返回task çš„å¥æŸ„ï¼Œè¯¥å¥æŸ„å¯ä»¥ç”¨äºŽå»ºç«‹task 之间的ä¾èµ–,或用于在wait è¯å¥ä¸å®žçŽ°åŒæ¥ã€‚ ##### 声明 ```{.c} typedef void* ffrt_task_handle_t; 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); void ffrt_task_handle_destroy(ffrt_task_handle_t handle); ``` ##### 傿•° `func` * CPU Function的指针,该指针执行的数æ®ç»“构,按照`ffrt_function_header_t`定义的æè¿°äº†è¯¥CPU Task如何执行和销æ¯çš„函数指针,FFRT通过这两个函数指针完æˆTask的执行和销æ¯ã€‚ `in_deps` * è¯¥å‚æ•°æ˜¯å¯é€‰çš„。 * è¯¥å‚æ•°ç”¨äºŽæè¿°è¯¥ä»»åŠ¡çš„è¾“å…¥ä¾èµ–,FFRT 通过数æ®çš„虚拟地å€ä½œä¸ºæ•°æ®çš„Signature æ¥å»ºç«‹ä¾èµ–。 `out_deps` * è¯¥å‚æ•°æ˜¯å¯é€‰çš„。 * è¯¥å‚æ•°ç”¨äºŽæè¿°è¯¥ä»»åŠ¡çš„è¾“å‡ºä¾èµ–。 * `注æ„`:该ä¾èµ–值本质上是一个数值,ffrt没办法区分该值是åˆç†è¿˜æ˜¯ä¸åˆç†çš„,会å‡å®šè¾“入的值是åˆç†çš„进行处ç†ï¼›ä½†ä¸å»ºè®®é‡‡ç”¨NULL,1, 2 ç‰å€¼æ¥å»ºç«‹ä¾èµ–关系,建议采用实际的内å˜åœ°å€ï¼Œå› 为å‰è€…使用ä¸å½“会建立起ä¸å¿…è¦çš„ä¾èµ–,影å“å¹¶å‘。 `attr` * è¯¥å‚æ•°æ˜¯å¯é€‰çš„。 * è¯¥å‚æ•°ç”¨äºŽæè¿°Task 的属性,比如qos ç‰ï¼Œè¯¦è§ [ffrt_task_attr_t](#ffrt_task_attr_t)ç« èŠ‚ã€‚ ##### 返回值 * task çš„å¥æŸ„ï¼Œè¯¥å¥æŸ„å¯ä»¥ç”¨äºŽå»ºç«‹task 之间的ä¾èµ–,或用于在wait è¯å¥ä¸å®žçŽ°åŒæ¥ã€‚ ##### æè¿° * **C APIä¸çš„ffrt_task_handle_t需è¦ç”¨æˆ·è°ƒç”¨`ffrt_task_handle_destroy`显å¼é”€æ¯ã€‚** * C APIä¸çš„task_handle_t对象的置空和销æ¯ç”±ç”¨æˆ·å®Œæˆï¼Œå¯¹åŒä¸€ä¸ªffrt_task_handle_t仅能调用一次`ffrt_task_handle_destroy`,é‡å¤å¯¹åŒä¸€ä¸ªffrt_task_handle_t调用`ffrt_task_handle_destroy`,其行为是未定义的。 * 在`ffrt_task_handle_destroy`之åŽå†å¯¹ffrt_task_handle_t进行访问,其行为是未定义的。 ##### æ ·ä¾‹ ```{.c} #include <stdio.h> #include "ffrt.h" void func0(void* arg) { printf("hello "); } void func1(void* arg) { (*(int*)arg)++; } void func2(void* arg) { printf("world, x = %d\n", *(int*)arg); } void func3(void* arg) { printf("handle wait"); (*(int*)arg)++; } typedef struct { ffrt_function_header_t header; ffrt_function_t func; ffrt_function_t after_func; void* arg; } c_function; static void ffrt_exec_function_wrapper(void* t) { c_function* f = (c_function*)t; if (f->func) { f->func(f->arg); } } static void ffrt_destroy_function_wrapper(void* t) { c_function* f = (c_function*)t; if (f->after_func) { f->after_func(f->arg); } } #define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1]) static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func, const ffrt_function_t after_func, void* arg) { FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size, size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size); c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); f->header.exec = ffrt_exec_function_wrapper; f->header.destroy = ffrt_destroy_function_wrapper; f->func = func; f->after_func = after_func; f->arg = arg; return (ffrt_function_header_t*)f; } static inline ffrt_task_handle_t ffrt_submit_h_c(ffrt_function_t func, const ffrt_function_t after_func, void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr) { return ffrt_submit_h_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr); } static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func, void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr) { ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr); } int main(int narg, char** argv) { // handle work with submit ffrt_task_handle_t h = ffrt_submit_h_c(func0, NULL, NULL, NULL, NULL, NULL); // not need some data in this task int x = 1; const std::vector<ffrt_dependence_t> in_deps = {{ffrt_dependence_data, &x}}; ffrt_deps_t d2{static_cast<uint32_t>(in_deps.size()), in_deps.data()}; const std::vector<ffrt_dependence_t> out_deps = {{ffrt_dependence_data, &x}}; ffrt_deps_t d1{static_cast<uint32_t>(out_deps.size()), out_deps.data()}; ffrt_submit_c(func1, NULL, &x, NULL, &d1, NULL); ffrt_submit_c(func2, NULL, &x, &d2, NULL, NULL); // this task depend x and h ffrt_task_handle_destroy(h); // handle work with wait ffrt_task_handle_t h2 = ffrt_submit_h_c(func3, NULL, &x, NULL, NULL, NULL); const std::vector<ffrt_dependence_t> wait_deps = {{ffrt_dependence_task, h2}}; ffrt_deps_t d3{static_cast<uint32_t>(wait_deps.size()), wait_deps.data()}; ffrt_wait_deps(&d3); ffrt_task_handle_destroy(h2); printf("x = %d", x); ffrt_wait(); return 0; } ``` * 预期的输出为: ``` hello handle wait x = 2 world, x = 3 ``` #### ffrt_this_task_get_id <hr/> * 返回当å‰taskçš„idæ ‡è¯†ï¼Œæ›´å¤šä½¿ç”¨ç”¨äºŽç»´æµ‹ï¼ˆåŽŸå› æ˜¯task nameå¯èƒ½é‡å)。 ##### 声明 ```{.c} uint64_t ffrt_this_task_get_id(); ``` ##### 傿•° * 䏿¶‰åŠã€‚ ##### 返回值 * 当å‰taskçš„id。 ##### æè¿° * 该接å£åœ¨task内部调用将返回当å‰taskçš„idæ ‡è¯†ï¼Œåœ¨task外部调用将返回0。 * å¯ä»¥åŸºäºŽè¯¥æŽ¥å£åœ¨task外部调用返回0的特性æ¥åŒºåˆ†å‡½æ•°æ˜¯è¿è¡Œåœ¨FFRT 工作线程上还是éžFFRT工作线程上。 * task id为从1开始编ç ï¼Œæ¯æäº¤ä¸€ä¸ªtaskä¾¿å¢žåŠ 1,被设计æˆ64bit,å³ä¾¿æ˜¯æ¯ç§’百万次æäº¤ï¼Œä¹Ÿéœ€è¦292471.2å¹´æ‰ä¼šå‘生翻转。 ##### æ ·ä¾‹ * 忽略。 #### ffrt_this_task_update_qos <hr/> * æ›´æ–°å½“å‰æ£åœ¨æ‰§è¡Œçš„taskçš„qosç‰çº§ã€‚ ##### 声明 ```{.c} int ffrt_this_task_update_qos(ffrt_qos_t qos); ``` ##### 傿•° * `qos` æ–°çš„qosç‰çº§ã€‚ ##### 返回值 * 0表示æˆåŠŸï¼Œéž0表示失败。 ##### æè¿° * 该接å£å¯¹å½“å‰taskçš„qos调整会立å³ç”Ÿæ•ˆã€‚ * 如果新设定的qos与当å‰çš„qosä¸ä¸€è‡´ï¼Œåˆ™ä¼šblock当å‰taskçš„æ‰§è¡Œï¼Œå†æŒ‰ç…§æ–°çš„qosæ¢å¤æ‰§è¡Œã€‚ * 如果新设定的qos与当å‰çš„qos一致,则接å£ä¼šç«‹å³è¿”回0,ä¸åšä»»ä½•处ç†ã€‚ * **如果在éžtask内部调用该接å£ï¼Œåˆ™è¿”回éž0值,用户å¯ä»¥é€‰æ‹©å¿½ç•¥æˆ–其他处ç†ã€‚** ##### æ ·ä¾‹ * 忽略。 #### ffrt_this_task_get_qos <hr/> * 获å–当剿£åœ¨æ‰§è¡Œçš„taskçš„qosç‰çº§ã€‚ ##### 声明 ```{.c} ffrt_qos_t ffrt_this_task_get_qos(); ``` ##### 傿•° * NA ##### 返回值 * `qos` 任务qosç‰çº§ã€‚ ##### æè¿° * 获å–当剿£åœ¨æ‰§è¡Œçš„taskçš„qosç‰çº§ã€‚ ##### æ ·ä¾‹ ```{.c} #include "ffrt.h" int main(int narg, char** argv) { static int x = 0; int* xf = &x; void* data = xf; uint64_t timeout1 = 20; ffrt::submit([=]() { ffrt_qos_t taskQos = ffrt_this_task_get_qos(); ffrt_timer_cb cb; ffrt_timer_start(taskQos, timeout1, data, cb, false); ffrt_usleep(200); }, {}, {}); ffrt::wait(); return 0; } ``` ### 串行队列 <hr /> * 串行队列基于FFRTå程调度模型,实现了消æ¯é˜Ÿåˆ—功能。串行任务执行在FFRT Workersä¸Šï¼Œç”¨æˆ·æ— éœ€ç»´æŠ¤ä¸€ä¸ªä¸“ç”¨çš„çº¿ç¨‹ï¼Œæ‹¥æœ‰æ›´è½»é‡çº§çš„调度开销。 #### ffrt_queue_attr_t ##### 声明 ```{.c} typedef struct { uint32_t storage[(ffrt_queue_attr_storage_size + sizeof(uint32_t) - 1) / sizeof(uint32_t)]; } ffrt_queue_attr_t; int ffrt_queue_attr_init(ffrt_queue_attr_t* attr); void ffrt_queue_attr_destroy(ffrt_queue_attr_t* attr); ``` ##### 傿•° `attr` * è¯¥å‚æ•°æ˜¯æŒ‡å‘未åˆå§‹åŒ–çš„ffrt_queue_attr_t。 ##### 返回值 * è‹¥æˆåŠŸè¿”å›ž0,å¦åˆ™è¿”回-1。 ##### æè¿° * ffrt_queue_attr_t用于创建ffrt_queue_t且ä¸å•ç‹¬ä½¿ç”¨ï¼Œå› æ¤å¿…须在创建队列å‰å…ˆåˆ›å»ºå¥½é˜Ÿåˆ—属性。 * ffrt_queue_attr_t对象的置空和销æ¯ç”±ç”¨æˆ·å®Œæˆï¼Œå¯¹åŒä¸€ä¸ªffrt_queue_attr_t仅能调用一次`ffrt_queue_attr_destroy`,é‡å¤å¯¹åŒä¸€ä¸ªffrt_queue_attr_t调用`ffrt_queue_attr_destroy`,其行为是未定义的。 * 在`ffrt_queue_attr_destroy`之åŽå†å¯¹ffrt_queue_attr_t进行访问,其行为是未定义的。 ##### æ ·ä¾‹ å‚考ffrt_queue_tç« èŠ‚çš„æ ·ä¾‹ã€‚ #### ffrt_queue_t ##### 声明 ```{.c} typedef enum { ffrt_queue_serial, ffrt_queue_concurrent, ffrt_queue_max } ffrt_queue_type_t; typedef void* ffrt_queue_t; ffrt_queue_t ffrt_queue_create(ffrt_queue_type_t type, const char* name, const ffrt_queue_attr_t* attr) void ffrt_queue_destroy(ffrt_queue_t queue) ``` ##### 傿•° `type` * è¯¥å‚æ•°ç”¨äºŽæè¿°åˆ›å»ºçš„队列类型。 `name` * è¯¥å‚æ•°ç”¨äºŽæè¿°åˆ›å»ºé˜Ÿåˆ—çš„åå—。 `attr` * è¯¥å‚æ•°ç”¨äºŽæè¿°queue的属性,详è§ffrt_queue_attr_tç« èŠ‚ã€‚ ##### 返回值 * è‹¥æˆåŠŸåˆ™è¿”å›žæ–°åˆ›å»ºçš„é˜Ÿåˆ—ï¼Œå¦åˆ™è¿”回空指针。 ##### æè¿° * æäº¤è‡³è¯¥é˜Ÿåˆ—çš„ä»»åŠ¡å°†æŒ‰ç…§é¡ºåºæ‰§è¡Œï¼Œå¦‚æžœæŸä¸ªæäº¤çš„任务ä¸å‘ç”Ÿé˜»å¡žï¼Œåˆ™æ— æ³•ä¿è¯è¯¥ä»»åŠ¡çš„æ‰§è¡Œé¡ºåºã€‚ * ffrt_queue_t对象的置空和销æ¯ç”±ç”¨æˆ·å®Œæˆï¼Œå¯¹åŒä¸€ä¸ªffrt_queue_t仅能调用一次`ffrt_queue_destroy`,é‡å¤å¯¹åŒä¸€ä¸ªffrt_queue_t调用`ffrt_queue_destroy`,其行为是未定义的。 * 在`ffrt_queue_destroy`之åŽå†å¯¹ffrt_queue_t进行访问,其行为是未定义的。 ##### æ ·ä¾‹ ``` #include <stdio.h> #include "ffrt.h" using namespace std; template<class T> struct Function { ffrt_function_header_t header; T closure; }; template<class T> void ExecFunctionWrapper(void* t) { auto f = reinterpret_cast<Function<std::decay_t<T>>*>(t); f->closure(); } template<class T> void DestroyFunctionWrapper(void* t) { auto f = reinterpret_cast<Function<std::decay_t<T>>*>(t); f = nullptr; } template<class T> static inline ffrt_function_header_t* create_function_wrapper(T&& func, ffrt_function_kind_t kind = ffrt_function_kind_general) { using function_type = Function<std::decay_t<T>>; auto p = ffrt_alloc_auto_managed_function_storage_base(kind); auto f = new (p)function_type; f->header.exec = ExecFunctionWrapper<T>; f->header.destroy = DestroyFunctionWrapper<T>; f->closure = std::forward<T>(func); return reinterpret_cast<ffrt_function_header_t*>(f); } int main(int narg, char** argv) { ffrt_queue_attr_t queue_attr; (void)ffrt_queue_attr_init(&queue_attr); ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_serial, "test_queue", &queue_attr); std::function<void()>&& queueFunc = [] () {printf("Task done.\n");}; ffrt_function_header_t* queueFunc_t = create_function_wrapper((queueFunc), ffrt_function_kind_queue); ffrt_queue_submit(queue_handle, queueFunc_t, nullptr); ffrt_queue_attr_destroy(&queue_attr); ffrt_queue_destroy(queue_handle); } ``` #### ffrt_get_main_queue <hr/> 获å–主线程任务队列。 ##### 声明 ```{.c} ffrt_queue_t ffrt_get_main_queue(); ``` ##### 傿•° NA ##### 返回值 主线程队列。 ##### æè¿° 获å–主线程队列,用于FFRT线程与主线程通信。 ##### æ ·ä¾‹ ```{.c} 本用例需è¦åœ¨é¸¿è’™ç³»ç»Ÿä¸æ‰§è¡Œ #include "ffrt.h" inline void OnePlusForTest(void* data) { *(int*)data += 1; } int main(int narg, char** argv) { ffrt::queue *serialQueue = new ffrt::queue("ffrt_normal_queue", {}); ffrt_queue_t mainQueue = ffrt_get_main_queue(); ffrt_task_attr_t attr; ffrt_task_attr_init(&attr); ffrt_task_attr_set_qos(&attr, ffrt_qos_user_initiated); int result = 0; std::function<void()>&& basicFunc = [&result]() { OnePlusForTest(static_cast<void*>(&result)); OnePlusForTest(static_cast<void*>(&result)); ffrt_usleep(3000); }; ffrt::task_handle handle = serialQueue->submit_h( [&] { result = result + 1; ffrt_queue_submit(mainQueue, ffrt::create_function_wrapper(basicFunc, ffrt_function_kind_queue), &attr); }, ffrt::task_attr().qos(3).name("ffrt main_queue.")); serialQueue->wait(handle); return 0; } ``` #### ffrt_get_current_queue 获å–ArkTS Worker线程任务队列。 ##### 声明 ```{.c} ffrt_queue_t ffrt_get_current_queue(); ``` ##### 傿•° NA ##### 返回值 ArkTS Worker线程任务队列。 ##### æè¿° 获å–ArkTS Worker线程队列,用于FFRT线程与ArkTS Worker线程通信。 ##### æ ·ä¾‹ ```{.c} //本用例需è¦åœ¨é¸¿è’™ç³»ç»Ÿä¸æ‰§è¡Œ #include "ffrt.h" inline void OnePlusForTest(void* data) { *(int*)data += 1; } int main(int narg, char** argv) { ffrt::queue *serialQueue = new ffrt::queue("ffrt_normal_queue", {}); ffrt_queue_t currentQueue = ffrt_get_current_queue(); ffrt_task_attr_t attr; ffrt_task_attr_init(&attr); ffrt_task_attr_set_qos(&attr, ffrt_qos_user_initiated); int result = 0; std::function<void()>&& basicFunc = [&result]() { OnePlusForTest(static_cast<void*>(&result)); OnePlusForTest(static_cast<void*>(&result)); ffrt_usleep(3000); }; ffrt::task_handle handle = serialQueue->submit_h( [&] { result = result + 1; ffrt_queue_submit(currentQueue, ffrt::create_function_wrapper(basicFunc, ffrt_function_kind_queue), &attr); }, ffrt::task_attr().qos(3).name("ffrt current_queue.")); serialQueue->wait(handle); return 0; } ``` ### 并行队列 <hr /> FFRT支æŒå¹¶è¡Œé˜Ÿåˆ—,并支æŒè®¾ç½®å¹¶è¡Œé˜Ÿåˆ—的并å‘度和任务优先级。 #### ffrt_queue_attr_set_max_concurrency <hr/> FFRT并行队列设置最大并å‘度。 ##### 声明 ```{.c} void ffrt_queue_attr_set_max_concurrency(ffrt_queue_attr_t* attr, const int max_concurrency); ``` ##### 傿•° `attr` * è¯¥å‚æ•°ç”¨äºŽæè¿°queue的属性,详è§ffrt_queue_attr_tç« èŠ‚ã€‚ `max_concurrency` * 最大并å‘度,当用户设置å°äºŽç‰äºŽ0时,并å‘度是1。 ##### 返回值 NA ##### æè¿° FFRT并行队列设置最大并å‘åº¦ï¼Œéœ€è¦æ³¨æ„的是,当设置很大的并å‘度时,如100,å—é™äºŽç¡¬ä»¶èƒ½åŠ›ï¼Œæœ€ç»ˆçš„å¹¶å‘度ä¸ä¼šè¾¾åˆ°100。 ##### æ ·ä¾‹ ```{.c} #include "ffrt.h" int main(int narg, char** argv) { ffrt_queue_attr_t queue_attr; (void)ffrt_queue_attr_init(&queue_attr); uint64_t concurrency = 4; ffrt_queue_attr_set_max_concurrency(&queue_attr, concurrency); concurrency = ffrt_queue_attr_get_max_concurrency(&queue_attr); ffrt_queue_attr_destroy(&queue_attr); printf("concurrency=%lu\n", concurrency); return 0; } ``` 预期输出为: ``` concurrency=4 ``` #### ffrt_queue_attr_get_max_concurrency <hr/> 获å–FFRT并行队列设置的最大并å‘度。 ##### 声明 ```{.c} int ffrt_queue_attr_get_max_concurrency(const ffrt_queue_attr_t* attr); ``` ##### 傿•° `attr` * è¯¥å‚æ•°ç”¨äºŽæè¿°queue的属性,详è§ffrt_queue_attr_tç« èŠ‚ã€‚ ##### 返回值 用户设置的最大并å‘度。 ##### æè¿° 获å–FFRT并行队列设置的最大并å‘度。 ##### æ ·ä¾‹ ```{.c} #include "ffrt.h" int main(int narg, char** argv) { ffrt_queue_attr_t queue_attr; (void)ffrt_queue_attr_init(&queue_attr); uint64_t concurrency = 4; ffrt_queue_attr_set_max_concurrency(&queue_attr, concurrency); concurrency = ffrt_queue_attr_get_max_concurrency(&queue_attr); ffrt_queue_attr_destroy(&queue_attr); printf("concurrency=%lu\n", concurrency); return 0; } ``` 预期输出为: ``` concurrency=4 ``` #### ffrt_task_attr_set_queue_priority <hr/> 设置并行队列任务优先级。 ##### 声明 ```{.c} /* 任务优先级 */ typedef enum { ffrt_queue_priority_immediate = 0, ffrt_queue_priority_high, ffrt_queue_priority_low, ffrt_queue_priority_idle, } ffrt_queue_priority_t; void ffrt_task_attr_set_queue_priority(ffrt_task_attr_t* attr, ffrt_queue_priority_t priority); ``` ##### 傿•° `attr` * è¯¥å‚æ•°ç”¨äºŽæè¿°task的属性,详è§ffrt_task_attr_tç« èŠ‚ã€‚ `priority` * 任务优先级,支æŒå››ç§ä¼˜å…ˆçº§ï¼Œå®šä¹‰å‚考ffrt_queue_priority_t。 ##### 返回值 NA ##### æè¿° 设置并行队列任务优先级。 ##### æ ·ä¾‹ ```{.c} #include "ffrt.h" int main(int narg, char** argv) { ffrt_task_attr_t task_attr; (void)ffrt_task_attr_init(&task_attr); ffrt_queue_priority_t priority = ffrt_queue_priority_idle; ffrt_task_attr_set_queue_priority(&task_attr, priority); priority = ffrt_task_attr_get_queue_priority(&task_attr); ffrt_task_attr_destroy(&task_attr); printf("priority=%d\n", priority); return 0; } ``` 预期输出为: ``` priority=3 ``` #### ffrt_task_attr_get_queue_priority <hr/> 获å–å¼€å‘者设置的并行队列任务优先级。 ##### 声明 ```{.c} ffrt_queue_priority_t ffrt_task_attr_get_queue_priority(const ffrt_task_attr_t* attr); ``` ##### 傿•° `attr` * è¯¥å‚æ•°ç”¨äºŽæè¿°queue的属性,详è§ffrt_queue_attr_tç« èŠ‚ã€‚ ##### 返回值 任务优先级。 ##### æè¿° 获å–å¼€å‘者设置的并行队列任务优先级。 ##### æ ·ä¾‹ ```{.c} #include "ffrt.h" int main(int narg, char** argv) { ffrt_task_attr_t task_attr; (void)ffrt_task_attr_init(&task_attr); ffrt_queue_priority_t priority = ffrt_queue_priority_idle; ffrt_task_attr_set_queue_priority(&task_attr, priority); priority = ffrt_task_attr_get_queue_priority(&task_attr); ffrt_task_attr_destroy(&task_attr); printf("priority=%d\n", priority); return 0; } ``` 预期输出为: ``` priority=3 ``` ### åŒæ¥åŽŸè¯ #### ffrt_mutex_t <hr/> * FFRTæä¾›çš„类似pthread mutex 的性能实现。 ##### 声明 ```{.c} typedef enum { ffrt_error = -1, ffrt_success = 0, ffrt_error_nomem = ENOMEM, ffrt_error_timedout = ETIMEDOUT, ffrt_error_busy = EBUSY, ffrt_error_inval = EINVAL } ffrt_error_t; struct ffrt_mutex_t; int ffrt_mutex_init(ffrt_mutex_t* mutex, const ffrt_mutexattr_t* attr); int ffrt_mutex_lock(ffrt_mutex_t* mutex); int ffrt_mutex_unlock(ffrt_mutex_t* mutex); int ffrt_mutex_trylock(ffrt_mutex_t* mutex); int ffrt_mutex_destroy(ffrt_mutex_t* mutex); ``` ##### 傿•° `attr` * 当å‰FFRTåªæ”¯æŒåŸºç¡€ç±»åž‹çš„mutexï¼Œå› æ¤attr必须为空指针。 `mutex` * æŒ‡å‘æ‰€æ“作的互斥é”的指针。 ##### 返回值 * è‹¥æˆåŠŸåˆ™ä¸º ffrt_success ,å¦åˆ™å‘生错误。 ##### æè¿° * 该接å£åªèƒ½åœ¨FFRT task 内部调用,在FFRT task 外部调用å˜åœ¨æœªå®šä¹‰çš„行为。 * 该功能能够é¿å…pthreadä¼ ç»Ÿçš„pthread_mutex_t 在抢ä¸åˆ°é”æ—¶é™·å…¥å†…æ ¸çš„é—®é¢˜ï¼Œåœ¨ä½¿ç”¨å¾—å½“çš„æ¡ä»¶ä¸‹å°†ä¼šæœ‰æ›´å¥½çš„æ€§èƒ½ã€‚ * **注æ„ï¼šç›®å‰æš‚䏿”¯æŒé€’归和定时功能。** * **注æ„:C APIä¸çš„ffrt_mutex_t需è¦ç”¨æˆ·è°ƒç”¨`ffrt_mutex_init`å’Œ`ffrt_mutex_destroy`显å¼åˆ›å»ºå’Œé”€æ¯ã€‚** * **注æ„:C APIä¸çš„ffrt_mutex_t对象的置空和销æ¯ç”±ç”¨æˆ·å®Œæˆï¼Œå¯¹åŒä¸€ä¸ªffrt_mutex_t仅能调用一次`ffrt_mutex_destroy`,é‡å¤å¯¹åŒä¸€ä¸ªffrt_mutex_t调用`ffrt_mutex_destroy`,其行为是未定义的。** * **注æ„:在`ffrt_mutex_destroy`之åŽå†å¯¹ffrt_mutex_t进行访问,其行为是未定义的。** ##### æ ·ä¾‹ ```{.c} #include <stdio.h> #include "ffrt.h" typedef struct { int* sum; ffrt_mutex_t* mtx; } tuple; void func(void* arg) { tuple* t = (tuple*)arg; int ret = ffrt_mutex_lock(t->mtx); if (ret != ffrt_success) { printf("error\n"); } (*t->sum)++; ret = ffrt_mutex_unlock(t->mtx); if (ret != ffrt_success) { printf("error\n"); } } typedef struct { ffrt_function_header_t header; ffrt_function_t func; ffrt_function_t after_func; void* arg; } c_function; static void ffrt_exec_function_wrapper(void* t) { c_function* f = (c_function*)t; if (f->func) { f->func(f->arg); } } static void ffrt_destroy_function_wrapper(void* t) { c_function* f = (c_function*)t; if (f->after_func) { f->after_func(f->arg); } } #define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1]) static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func, const ffrt_function_t after_func, void* arg) { FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size, size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size); c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); f->header.exec = ffrt_exec_function_wrapper; f->header.destroy = ffrt_destroy_function_wrapper; f->func = func; f->after_func = after_func; f->arg = arg; return (ffrt_function_header_t*)f; } static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func, void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr) { ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr); } void ffrt_mutex_task(void *) { int sum = 0; ffrt_mutex_t mtx; tuple t = {&sum, &mtx}; int ret = ffrt_mutex_init(&mtx, NULL); if (ret != ffrt_success) { printf("error\n"); } for (int i = 0; i < 10; i++) { ffrt_submit_c(func, NULL, &t, NULL, NULL, NULL); } ffrt_mutex_destroy(&mtx); ffrt_wait(); printf("sum = %d\n", sum); } int main(int narg, char** argv) { int r; ffrt_submit_c(ffrt_mutex_task, NULL, NULL, NULL, NULL, NULL); ffrt_wait(); return 0; } ``` 预期输出为: ``` sum=10 ``` * 该例å为功能示例,实际ä¸å¹¶ä¸é¼“åŠ±è¿™æ ·ä½¿ç”¨ã€‚ #### ffrt_cond_t <hr/> * FFRTæä¾›çš„类似pthread ä¿¡å·é‡çš„æ€§èƒ½å®žçŽ°ã€‚ ##### 声明 ```{.c} typedef enum { ffrt_error = -1, ffrt_success = 0, ffrt_error_nomem = ENOMEM, ffrt_error_timedout = ETIMEDOUT, ffrt_error_busy = EBUSY, ffrt_error_inval = EINVAL } ffrt_error_t; struct ffrt_cond_t; int ffrt_cond_init(ffrt_cond_t* cond, const ffrt_condattr_t* attr); int ffrt_cond_signal(ffrt_cond_t* cond); int ffrt_cond_broadcast(ffrt_cond_t* cond); int ffrt_cond_wait(ffrt_cond_t*cond, ffrt_mutex_t* mutex); int ffrt_cond_timedwait(ffrt_cond_t* cond, ffrt_mutex_t* mutex, const struct timespec* time_point); int ffrt_cond_destroy(ffrt_cond_t* cond); ``` ##### 傿•° `cond` * æŒ‡å‘æ‰€æ“作的信å·é‡çš„æŒ‡é’ˆã€‚ `attr` * 属性设定,空指针表示使用默认属性。 `mutex` * 指å‘è¦åœ¨é˜»å¡žæœŸé—´è§£é”的互斥é”的指针。 `time_point` * æŒ‡å‘æŒ‡å®šç‰å¾…æ—¶é™æ—¶é—´çš„对象的指针。 ##### 返回值 * è‹¥æˆåŠŸåˆ™ä¸º ffrt_success,若在é”å®šäº’æ–¥å‰æŠµè¾¾æ—¶é™åˆ™ä¸º ffrt_error_timedout。 ##### æè¿° * 该接å£åªèƒ½åœ¨FFRT task 内部调用,在FFRT task 外部调用å˜åœ¨æœªå®šä¹‰çš„行为。 * 该功能能够é¿å…ä¼ ç»Ÿçš„pthread_cond_t在æ¡ä»¶ä¸æ»¡è¶³æ—¶é™·å…¥å†…æ ¸çš„é—®é¢˜ï¼Œåœ¨ä½¿ç”¨å¾—å½“çš„æ¡ä»¶ä¸‹å°†ä¼šæœ‰æ›´å¥½çš„æ€§èƒ½ã€‚ * **注æ„:C APIä¸çš„ffrt_cond_t需è¦ç”¨æˆ·è°ƒç”¨`ffrt_cond_init`å’Œ`ffrt_cond_destroy`显å¼åˆ›å»ºå’Œé”€æ¯ã€‚** * **注æ„:C APIä¸çš„ffrt_cond_t对象的置空和销æ¯ç”±ç”¨æˆ·å®Œæˆï¼Œå¯¹åŒä¸€ä¸ªffrt_cond_t仅能调用一次`ffrt_cond_destroy`,é‡å¤å¯¹åŒä¸€ä¸ªffrt_cond_t调用`ffrt_cond_destroy`,其行为是未定义的。** * **注æ„:在`ffrt_cond_destroy`之åŽå†å¯¹ffrt_cond_t进行访问,其行为是未定义的。** ##### æ ·ä¾‹ ```{.c} #include <stdio.h> #include "ffrt.h" typedef struct { ffrt_cond_t* cond; int* a; ffrt_mutex_t* lock_; } tuple; void func1(void* arg) { tuple* t = (tuple*)arg; int ret = ffrt_mutex_lock(t->lock_); if (ret != ffrt_success) { printf("error\n"); } while (*t->a != 1) { ret = ffrt_cond_wait(t->cond, t->lock_); if (ret != ffrt_success) { printf("error\n"); } } ret = ffrt_mutex_unlock(t->lock_); if (ret != ffrt_success) { printf("error\n"); } printf("a = %d\n", *(t->a)); } void func2(void* arg) { tuple* t = (tuple*)arg; int ret = ffrt_mutex_lock(t->lock_); if (ret != ffrt_success) { printf("error\n"); } *(t->a) = 1; ret = ffrt_cond_signal(t->cond); if (ret != ffrt_success) { printf("error\n"); } ret = ffrt_mutex_unlock(t->lock_); if (ret != ffrt_success) { printf("error\n"); } } typedef struct { ffrt_function_header_t header; ffrt_function_t func; ffrt_function_t after_func; void* arg; } c_function; static void ffrt_exec_function_wrapper(void* t) { c_function* f = (c_function*)t; if (f->func) { f->func(f->arg); } } static void ffrt_destroy_function_wrapper(void* t) { c_function* f = (c_function*)t; if (f->after_func) { f->after_func(f->arg); } } #define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1]) static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func, const ffrt_function_t after_func, void* arg) { FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size, size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size); c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); f->header.exec = ffrt_exec_function_wrapper; f->header.destroy = ffrt_destroy_function_wrapper; f->func = func; f->after_func = after_func; f->arg = arg; return (ffrt_function_header_t*)f; } static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func, void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr) { ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr); } void ffrt_cv_task(void *) { ffrt_cond_t cond; int ret = ffrt_cond_init(&cond, NULL); if (ret != ffrt_success) { printf("error\n"); } int a = 0; ffrt_mutex_t lock_; tuple t = {&cond, &a, &lock_}; ret = ffrt_mutex_init(&lock_, NULL); if (ret != ffrt_success) { printf("error\n"); } ffrt_submit_c(func1, NULL, &t, NULL, NULL, NULL); ffrt_submit_c(func2, NULL, &t, NULL, NULL, NULL); ffrt_wait(); ffrt_cond_destroy(&cond); ffrt_mutex_destroy(&lock_); } int main(int narg, char** argv) { ffrt_submit_c(ffrt_cv_task, NULL, NULL, NULL, NULL, NULL); ffrt_wait(); return 0; } ``` 预期输出为: ``` a=1 ``` * 该例å为功能示例,实际ä¸å¹¶ä¸é¼“åŠ±è¿™æ ·ä½¿ç”¨ã€‚ #### ffrt_usleep <hr/> * FFRTæä¾›çš„类似C11 sleepå’Œlinux usleep的性能实现。 ##### 声明 ```{.c} int ffrt_usleep(uint64_t usec); ``` ##### 傿•° `usec` * ç¡çœ çš„us数。 ##### 返回值 * 䏿¶‰åŠã€‚ ##### æè¿° * 该接å£åªèƒ½åœ¨FFRT task 内部调用,在FFRT task 外部调用å˜åœ¨æœªå®šä¹‰çš„行为。 * 该功能能够é¿å…ä¼ ç»Ÿçš„sleep ç¡çœ æ—¶é™·å…¥å†…æ ¸çš„é—®é¢˜ï¼Œåœ¨ä½¿ç”¨å¾—å½“çš„æ¡ä»¶ä¸‹å°†ä¼šæœ‰æ›´å¥½çš„æ€§èƒ½ã€‚ ##### æ ·ä¾‹ ```{.c} #include <time.h> #include <stdio.h> #include "ffrt.h" void func(void* arg) { time_t current_time = time(NULL); printf("Time: %s", ctime(¤t_time)); ffrt_usleep(2000000); // ç¡çœ 2 ç§’ current_time = time(NULL); printf("Time: %s", ctime(¤t_time)); } typedef struct { ffrt_function_header_t header; ffrt_function_t func; ffrt_function_t after_func; void* arg; } c_function; static void ffrt_exec_function_wrapper(void* t) { c_function* f = (c_function*)t; if (f->func) { f->func(f->arg); } } static void ffrt_destroy_function_wrapper(void* t) { c_function* f = (c_function*)t; if (f->after_func) { f->after_func(f->arg); } } #define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1]) static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func, const ffrt_function_t after_func, void* arg) { FFRT_STATIC_ASSERT(sizeof(c_function) <= ffrt_auto_managed_function_storage_size, size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size); c_function* f = (c_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); f->header.exec = ffrt_exec_function_wrapper; f->header.destroy = ffrt_destroy_function_wrapper; f->func = func; f->after_func = after_func; f->arg = arg; return (ffrt_function_header_t*)f; } static inline void ffrt_submit_c(ffrt_function_t func, const ffrt_function_t after_func, void* arg, const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr) { ffrt_submit_base(ffrt_create_function_wrapper(func, after_func, arg), in_deps, out_deps, attr); } int main(int narg, char** argv) { ffrt_submit_c(func, NULL, NULL, NULL, NULL, NULL); ffrt_wait(); return 0; } ``` 一ç§è¾“出情况为: ``` Time: Tue Aug 13 15:45:30 2024 Time: Tue Aug 13 15:45:32 2024 ``` #### ffrt_yield <hr/> * 当å‰task 主动让出CPU 执行资æºï¼Œè®©å…¶ä»–å¯ä»¥è¢«æ‰§è¡Œçš„task 先执行,如果没有其他å¯è¢«æ‰§è¡Œçš„task,yield æ— æ•ˆã€‚ ##### 声明 ```{.c} void ffrt_yield(); ``` ##### 傿•° * 䏿¶‰åŠã€‚ ##### 返回值 * 䏿¶‰åŠã€‚ ##### æè¿° * 该接å£åªèƒ½åœ¨FFRT task 内部调用,在FFRT task 外部调用å˜åœ¨æœªå®šä¹‰çš„行为。 * æ¤å‡½æ•°çš„确切行为å–决于实现,特别是使用ä¸çš„FFRT 调度程åºçš„æœºåˆ¶å’Œç³»ç»Ÿçжæ€ã€‚ ##### æ ·ä¾‹ * çœç•¥ã€‚ ### ffrt timer <hr /> FFRT支æŒå¯åŠ¨å’Œåœæ¢å®šæ—¶å™¨çš„能力。 #### ffrt_timer_start <hr/> å¯åЍtimer定时器。 ##### 声明 ```{.c} typedef int ffrt_timer_t; typedef void (*ffrt_timer_cb)(void* data); ffrt_timer_t ffrt_timer_start(ffrt_qos_t qos, uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat); ``` ##### 傿•° `qos` * qosç‰çº§ã€‚ `timeout` * 超时时间。 `data` * è¶…æ—¶åŽå›žè°ƒå‡½æ•°çš„å…¥å‚。 `cb` * è¶…æ—¶åŽå›žè°ƒå‡½æ•°ã€‚ `repeat` * 是å¦é‡å¤æ‰§è¡Œè¯¥å®šæ—¶å™¨ã€‚ ##### 返回值 è¿”å›žè¯¥å®šæ—¶å™¨å¥æŸ„。 ##### æè¿° å¯åЍtimer定时器。 ##### æ ·ä¾‹ ```{.c} #include <stdint.h> #include <unistd.h> #include "ffrt.h" static void testfun(void *data) { *(int *)data += 1; } void (*cb)(void *) = testfun; int main(int narg, char** argv) { static int x = 0; int *xf = &x; void *data = xf; uint64_t timeout = 200; int handle = ffrt_timer_start(ffrt_qos_default, timeout, data, cb, false); usleep(300000); ffrt_timer_stop(ffrt_qos_default, handle); printf("data: %d\n", x); return 0; } ``` 预期输出为: ``` data: 1 ``` #### ffrt_timer_stop <hr/> åœæ¢timer定时器。 ##### 声明 ```{.c} int ffrt_timer_stop(ffrt_qos_t qos, ffrt_timer_t handle); ``` ##### 傿•° `qos` * qosç‰çº§ã€‚ `handle` * å®šæ—¶å™¨å¥æŸ„。 ##### 返回值 返回0æˆåŠŸï¼Œè¿”å›ž-1失败。 ##### æè¿° åœæ¢timer定时器。 ##### æ ·ä¾‹ ```{.c} #include <stdint.h> #include <unistd.h> #include "ffrt.h" static void testfun(void *data) { *(int *)data += 1; } void (*cb)(void *) = testfun; int main(int narg, char** argv) { static int x = 0; int *xf = &x; void *data = xf; uint64_t timeout = 200; int handle = ffrt_timer_start(ffrt_qos_default, timeout, data, cb, false); usleep(300000); ffrt_timer_stop(ffrt_qos_default, handle); printf("data: %d\n", x); return 0; } ``` 预期输出为: ``` data: 1 ``` ### ffrt looper <hr /> FFRT æä¾›looper机制,looper支æŒä»»åŠ¡æäº¤ï¼Œäº‹ä»¶ç›‘å¬ï¼Œå®šæ—¶å™¨åŠŸèƒ½ï¼Œlooperè¿è¡Œåœ¨ç”¨æˆ·çº¿ç¨‹ã€‚ #### ffrt_loop_create <hr/> 创建loop对象。 ##### 声明 ```{.c} typedef void* ffrt_loop_t; ffrt_loop_t ffrt_loop_create(ffrt_queue_t queue); ``` ##### 傿•° `queue` * éœ€è¦æ˜¯å¹¶è¡Œé˜Ÿåˆ—。 ##### 返回值 loop对象。 ##### æè¿° 创建loop对象。 ##### æ ·ä¾‹ ```{.c} #include <stdint.h> #include <unistd.h> #include <stdio.h> #include "c/loop.h" int main(int narg, char** argv) { ffrt_queue_attr_t queue_attr; (void)ffrt_queue_attr_init(&queue_attr); ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_concurrent, "test_queue", &queue_attr); auto loop = ffrt_loop_create(queue_handle); if (loop != NULL) { printf("loop is not null.\n"); } int ret = ffrt_loop_destroy(loop); ffrt_queue_attr_destroy(&queue_attr); ffrt_queue_destroy(queue_handle); return 0; } ``` 预期输出为: ``` loop is not null. ``` #### ffrt_loop_destroy <hr/> 销æ¯loop对象。 ##### 声明 ```{.c} int ffrt_loop_destroy(ffrt_loop_t loop); ``` ##### 傿•° `loop` * loop对象。 ##### 返回值 返回0表示æˆåŠŸï¼Œ-1表示失败。 ##### æè¿° 销æ¯loop对象。 ##### æ ·ä¾‹ ```{.c} #include <stdint.h> #include <unistd.h> #include <stdio.h> #include "c/loop.h" int main(int narg, char** argv) { ffrt_queue_attr_t queue_attr; (void)ffrt_queue_attr_init(&queue_attr); ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_concurrent, "test_queue", &queue_attr); auto loop = ffrt_loop_create(queue_handle); int ret = ffrt_loop_destroy(loop); if (ret == 0) { printf("loop normal destruction."); } ffrt_queue_attr_destroy(&queue_attr); ffrt_queue_destroy(queue_handle); return 0; } ``` 预期输出为: ``` loop normal destruction. ``` #### ffrt_loop_run <hr/> å¯åЍloop循环。 ##### 声明 ```{.c} int ffrt_loop_run(ffrt_loop_t loop); ``` ##### 傿•° `loop` * loop对象。 ##### 返回值 返回0表示æˆåŠŸï¼Œ-1表示失败。 ##### æè¿° å¯åЍloop循环。 ##### æ ·ä¾‹ ```{.c} #include <pthread.h> #include <unistd.h> #include <stdio.h> #include "c/loop.h" void* ThreadFunc(void* p) { int ret = ffrt_loop_run(p); if (ret == 0) { printf("loop normal operation."); } return nullptr; } int main(int narg, char** argv) { ffrt_queue_attr_t queue_attr; (void)ffrt_queue_attr_init(&queue_attr); ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_concurrent, "test_queue", &queue_attr); auto loop = ffrt_loop_create(queue_handle); pthread_t thread; pthread_create(&thread, 0, ThreadFunc, loop); ffrt_loop_stop(loop); int ret = ffrt_loop_destroy(loop); ffrt_queue_attr_destroy(&queue_attr); ffrt_queue_destroy(queue_handle); return 0; } ``` 预期输出为: ``` loop normal operation. ``` #### ffrt_loop_stop <hr/> åœæ¢loop循环。 ##### 声明 ```{.c} void ffrt_loop_stop(ffrt_loop_t loop); ``` ##### 傿•° `loop` * loop对象。 ##### 返回值 NA。 ##### æè¿° åœæ¢loop循环。 ##### æ ·ä¾‹ ```{.c} #include <pthread.h> #include <unistd.h> #include <stdio.h> #include "c/loop.h" void* ThreadFunc(void* p) { int ret = ffrt_loop_run(p); return nullptr; } int main(int narg, char** argv) { ffrt_queue_attr_t queue_attr; (void)ffrt_queue_attr_init(&queue_attr); ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_concurrent, "test_queue", &queue_attr); auto loop = ffrt_loop_create(queue_handle); pthread_t thread; pthread_create(&thread, 0, ThreadFunc, loop); ffrt_loop_stop(loop); int ret = ffrt_loop_destroy(loop); ffrt_queue_attr_destroy(&queue_attr); ffrt_queue_destroy(queue_handle); return 0; } ``` 预期输出为: ``` æ£å¸¸åœæ¢loop对象,返回值是0。 ``` #### ffrt_loop_epoll_ctl <hr/> 管ç†loop上的监å¬äº‹ä»¶ã€‚ ##### 声明 ```{.c} int ffrt_loop_epoll_ctl(ffrt_loop_t loop, int op, int fd, uint32_t events, void *data, ffrt_poller_cb cb); ``` ##### 傿•° `loop` * loop对象。 `op` * fdæ“作符,如EPOLL_CTL_ADDå’ŒEPOLL_CLT_DEL。 `fd` * 事件æè¿°ç¬¦ã€‚ `events` * 事件。 `data` * 事件å˜åŒ–时触å‘的回调函数的入å‚。 `cb` * 事件å˜åŒ–时触å‘的回调函数。 ##### 返回值 返回0表示æˆåŠŸï¼Œ-1表示失败。 ##### æè¿° 管ç†loop上的监å¬äº‹ä»¶ã€‚ ##### æ ·ä¾‹ ```{.c} #include <pthread.h> #include <unistd.h> #include <stdio.h> #include <functional> #include <sys/epoll.h> #include <sys/eventfd.h> #include "c/loop.h" #include "ffrt.h" void* ThreadFunc(void* p) { int ret = ffrt_loop_run(p); return nullptr; } static void testfun(void* data) { *(int*)data += 1; } static void (*cb)(void*) = testfun; void testCallBack(void *data, unsigned int events) {} struct TestData { int fd; uint64_t expected; }; int main(int narg, char** argv) { ffrt_queue_attr_t queue_attr; (void)ffrt_queue_attr_init(&queue_attr); ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_concurrent, "test_queue", &queue_attr); auto loop = ffrt_loop_create(queue_handle); int result1 = 0; std::function<void()> &&basicFunc1 = [&result1]() {result1 += 10;}; ffrt_task_handle_t task1 = ffrt_queue_submit_h(queue_handle, ffrt::create_function_wrapper(basicFunc1, ffrt_function_kind_queue), nullptr); pthread_t thread; pthread_create(&thread, 0, ThreadFunc, loop); static int x = 0; int* xf = &x; void* data = xf; uint64_t timeout1 = 20; uint64_t timeout2 = 10; uint64_t expected = 0xabacadae; int testFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); struct TestData testData {.fd = testFd, .expected = expected}; ffrt_timer_t timeHandle = ffrt_loop_timer_start(loop, timeout1, data, cb, false); int ret = ffrt_loop_epoll_ctl(loop, EPOLL_CTL_ADD, testFd, EPOLLIN, (void*)(&testData), testCallBack); if (ret == 0) { printf("ffrt_loop_epoll_ctl执行æˆåŠŸã€‚\n"); } ssize_t n = write(testFd, &expected, sizeof(uint64_t)); usleep(25000); ffrt_loop_epoll_ctl(loop, EPOLL_CTL_DEL, testFd, 0, nullptr, nullptr); ffrt_loop_stop(loop); pthread_join(thread, nullptr); ffrt_loop_timer_stop(loop, timeHandle); ret = ffrt_loop_destroy(loop); ffrt_queue_attr_destroy(&queue_attr); ffrt_queue_destroy(queue_handle); return 0; } ``` 预期输出为: ``` ffrt_loop_epoll_ctl执行æˆåŠŸã€‚ ``` #### ffrt_loop_timer_start <hr/> 在loop上å¯åŠ¨å®šæ—¶å™¨ã€‚ ##### 声明 ```{.c} ffrt_timer_t ffrt_loop_timer_start(ffrt_loop_t loop, uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat); ``` ##### 傿•° `loop` * loop对象。 `timeout` * 超时时间。 `data` * 事件å˜åŒ–时触å‘的回调函数的入å‚。 `cb` * 事件å˜åŒ–时触å‘的回调函数。 `repeat` * 是å¦é‡å¤æ‰§è¡Œè¯¥å®šæ—¶å™¨ã€‚ ##### 返回值 å®šæ—¶å™¨å¥æŸ„。 ##### æè¿° 在loop上å¯åŠ¨å®šæ—¶å™¨ã€‚ ##### æ ·ä¾‹ å‚考ffrt_loop_epoll_ctlæŽ¥å£æ ·ä¾‹ã€‚ #### ffrt_loop_timer_stop <hr/> åœæ¢timer定时器。 ##### 声明 ```{.c} int ffrt_loop_timer_stop(ffrt_loop_t loop, ffrt_timer_t handle) ``` ##### 傿•° `loop` * loop对象。 `handle` * å®šæ—¶å™¨å¥æŸ„。 ##### 返回值 返回0表示æˆåŠŸï¼Œè¿”å›ž-1表示失败。 ##### æè¿° åœæ¢timer定时器。 ##### æ ·ä¾‹ å‚考ffrt_loop_epoll_ctlæŽ¥å£æ ·ä¾‹ã€‚ ## 长耗时任务监测 ### 机制 * 当任务执行时间超过一秒时,会触å‘ä¸€æ¬¡å †æ ˆæ‰“å°ï¼ŒåŽç»è¯¥ä»»åŠ¡å †æ ˆæ‰“å°é¢‘çŽ‡è°ƒæ•´ä¸ºä¸€åˆ†é’Ÿã€‚è¿žç»æ‰“å°å次åŽï¼Œæ‰“å°é¢‘率调整为å分钟。å†è§¦å‘忬¡æ‰“å°åŽï¼Œæ‰“å°é¢‘率固定为三å分钟。 * è¯¥æœºåˆ¶çš„å †æ ˆæ‰“å°è°ƒç”¨çš„æ˜¯DFXçš„ `GetBacktraceStringByTid` 接å£ï¼Œè¯¥æŽ¥å£ä¼šå‘阻塞线程å‘é€æŠ“æ ˆä¿¡å·ï¼Œè§¦å‘䏿–并抓å–è°ƒç”¨æ ˆè¿”å›žã€‚ ### æ ·ä¾‹ åœ¨å¯¹åº”è¿›ç¨‹æ—¥å¿—ä¸æœç´¢ `RecordSymbolAndBacktrace` 关键å—,对应的日志示例如下: ``` W C01719/ffrt: 60500:RecordSymbolAndBacktrace:159 Tid[16579] function occupies worker for more than [1]s. W C01719/ffrt: 60501:RecordSymbolAndBacktrace:164 Backtrace: W C01719/ffrt: #00 pc 00000000000075f0 /system/lib64/module/file/libhash.z.so W C01719/ffrt: #01 pc 0000000000008758 /system/lib64/module/file/libhash.z.so W C01719/ffrt: #02 pc 0000000000012b98 /system/lib64/module/file/libhash.z.so W C01719/ffrt: #03 pc 000000000002aaa0 /system/lib64/platformsdk/libfilemgmt_libn.z.so W C01719/ffrt: #04 pc 0000000000054b2c /system/lib64/platformsdk/libace_napi.z.so W C01719/ffrt: #05 pc 00000000000133a8 /system/lib64/platformsdk/libuv.so W C01719/ffrt: #06 pc 00000000000461a0 /system/lib64/chipset-sdk/libffrt.so W C01719/ffrt: #07 pc 0000000000046d44 /system/lib64/chipset-sdk/libffrt.so W C01719/ffrt: #08 pc 0000000000046a6c /system/lib64/chipset-sdk/libffrt.so W C01719/ffrt: #09 pc 00000000000467b0 /system/lib64/chipset-sdk/libffrt.so ``` 该维测会打å°å‡ºworkerä¸Šæ‰§è¡Œæ—¶é—´è¶…è¿‡é˜ˆå€¼çš„ä»»åŠ¡å †æ ˆã€worker线程å·ã€æ‰§è¡Œæ—¶é—´ï¼Œè¯·è‡ªè¡Œæ ¹æ®å †æ ˆæ‰¾å¯¹åº”ç»„ä»¶ç¡®è®¤é˜»å¡žåŽŸå› ã€‚ ### 注æ„事项 长耗时任务监测会å‘é€ä¸æ–ä¿¡å·ï¼Œå¦‚果用户的代ç ä¸å˜åœ¨ `sleep` ç‰ä¼šè¢«ä¸æ–å”¤é†’çš„é˜»å¡žï¼Œç”¨æˆ·éœ€ä¸»åŠ¨æŽ¥æ”¶è¯¥é˜»å¡žçš„è¿”å›žå€¼ï¼Œå¹¶é‡æ–°è°ƒç”¨ã€‚ 示例如下: ``` unsigned int leftTime = sleep(10); while (leftTime != 0) { leftTime = sleep(leftTime); } ``` ## 开呿¥éª¤ 以下æ¥éª¤æè¿°äº†å¦‚何使用`FFRT`æä¾›çš„Native API接å£ï¼Œåˆ›å»ºå¹¶è¡Œä»»åŠ¡å’Œä¸²è¡Œé˜Ÿåˆ—ä»»åŠ¡ä»¥åŠé”€æ¯ç›¸åº”资æºã€‚ **æ·»åŠ åŠ¨æ€é“¾æŽ¥åº“** CMakeLists.txt䏿·»åР以䏋lib: ```txt libffrt.z.so ``` **头文件** ```c++ #include "ffrt/task.h" #include "ffrt/type_def.h" #include "ffrt/condition_variable.h" #include "ffrt/mutex.h" #include "ffrt/queue.h" #include "ffrt/sleep.h" ``` 1. **首先需è¦å¯¹æ‰§è¡Œçš„函数进行å°è£…**。 ```c++ // 第一ç§ä½¿ç”¨æ¨¡æ¿ï¼Œæ”¯æŒC++ template<class T> struct Function { ffrt_function_header_t header; T closure; }; template<class T> void ExecFunctionWrapper(void* t) { auto f = reinterpret_cast<Function<std::decay_t<T>>*>(t); f->closure(); } template<class T> void DestroyFunctionWrapper(void* t) { auto f = reinterpret_cast<Function<std::decay_t<T>>*>(t); f->closure = nullptr; } template<class T> static inline ffrt_function_header_t* create_function_wrapper(T&& func, ffrt_function_kind_t kind = ffrt_function_kind_general) { using function_type = Function<std::decay_t<T>>; auto p = ffrt_alloc_auto_managed_function_storage_base(kind); auto f = new (p)function_type; f->header.exec = ExecFunctionWrapper<T>; f->header.destroy = DestroyFunctionWrapper<T>; f->closure = std::forward<T>(func); return reinterpret_cast<ffrt_function_header_t*>(f); } // 第二ç§åˆ›å»ºæ–¹å¼ typedef struct { ffrt_function_header_t header; ffrt_function_t func; ffrt_function_t after_func; void* arg; } CFunction; static void FfrtExecFunctionWrapper(void* t) { CFunction* f = static_cast<CFunction*>(t); if (f->func) { f->func(f->arg); } } static void FfrtDestroyFunctionWrapper(void* t) { CFunction* f = static_cast<CFunction*>(t); if (f->after_func) { f->after_func(f->arg); } } #define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1]) static inline ffrt_function_header_t* ffrt_create_function_wrapper(const ffrt_function_t func, const ffrt_function_t after_func, void* arg, ffrt_function_kind_t kind_t = ffrt_function_kind_general) { FFRT_STATIC_ASSERT(sizeof(CFunction) <= ffrt_auto_managed_function_storage_size, size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size); CFunction* f = static_cast<CFunction*>(ffrt_alloc_auto_managed_function_storage_base(kind_t)); f->header.exec = FfrtExecFunctionWrapper; f->header.destroy = FfrtDestroyFunctionWrapper; f->func = func; f->after_func = after_func; f->arg = arg; return reinterpret_cast<ffrt_function_header_t*>(f); } // æ ·ä¾‹ï¼šå¾…æäº¤æ‰§è¡Œçš„函数 void OnePlusForTest(void* arg) { (*static_cast<int*>(arg)) += 1; } ``` 2. **设置task属性值**。 用户æäº¤ä»»åŠ¡æ—¶å¯ä»¥è®¾ç½®ä»»åŠ¡å±žæ€§ï¼ŒåŒ…æ‹¬qosç‰çº§ï¼Œåç§°ç‰ï¼Œå…·ä½“å¯å‚è€ƒæŽ¥å£æ–‡æ¡£ã€‚ ```c++ // ******åˆå§‹åŒ–并行任务属性****** ffrt_task_attr_t attr; ffrt_task_attr_init(&attr); // ******创建串行队列****** // 创建串行队列的属性 ffrt_queue_attr_t queue_attr; // 创建串行队列的handle ffrt_queue_t queue_handle; // åˆå§‹åŒ–队列属性 (void)ffrt_queue_attr_init(&queue_attr); // 如有需è¦ï¼Œè®¾ç½®æŒ‡å®šqosç‰çº§ ffrt_queue_attr_set_qos(&queue_attr, static_cast<ffrt_qos_t>(ffrt_qos_inherit)); // 如有需è¦ï¼Œè®¾ç½®è¶…æ—¶æ—¶é—´(ms) ffrt_queue_attr_set_timeout(&queue_attr, 10000); // 如有需è¦ï¼Œè®¾ç½®è¶…时回调 int x = 0; ffrt_queue_attr_set_callback(&queue_attr, ffrt_create_function_wrapper(OnePlusForTest, NULL, &x, ffrt_function_kind_queue)); // 基于属性,åˆå§‹åŒ–队列 queue_handle = ffrt_queue_create(ffrt_queue_serial, "test_queue", &queue_attr); ``` 3. **æäº¤ä»»åŠ¡**。 ```c++ int a = 0; // ******并行任务****** // æäº¤ä¸å¸¦handle返回值的并行任务 ffrt_submit_base(ffrt_create_function_wrapper(OnePlusForTest, NULL, &a), NULL, NULL, &attr); // æäº¤å¸¦handle返回值的并行任务 ffrt_task_handle_t task = ffrt_submit_h_base( ffrt_create_function_wrapper(OnePlusForTest, NULL, &a), NULL, NULL, &attr); // ******串行任务****** // æäº¤ä¸è¿”回handle的串行队列任务 ffrt_queue_submit(queue_handle, ffrt_create_function_wrapper(OnePlusForTest, nullptr, &a, ffrt_function_kind_queue), nullptr); // æäº¤å¸¦handle的串行队列任务 ffrt_task_handle_t handle = ffrt_queue_submit_h(queue_handle, ffrt_create_function_wrapper(OnePlusForTest, nullptr, &a, ffrt_function_kind_queue), nullptr); // 如果需è¦ç‰å¾…执行结果,则调用wait const std::vector<ffrt_dependence_t> wait_deps = {{ffrt_dependence_task, task}}; ffrt_deps_t wait{static_cast<uint32_t>(wait_deps.size()), wait_deps.data()}; ffrt_wait_deps(&wait); ffrt_queue_wait(handle); ``` 4. **任务æäº¤å®ŒæˆåŽé”€æ¯ç›¸åº”资æº**。 ```c++ // ******销æ¯å¹¶è¡Œä»»åŠ¡****** ffrt_task_attr_destroy(&attr); ffrt_task_handle_destroy(task); // ******销æ¯ä¸²è¡Œé˜Ÿåˆ—任务****** // 先销æ¯ä»»åŠ¡handle,å†é”€æ¯é˜Ÿåˆ— ffrt_queue_attr_destroy(&queue_attr); ffrt_task_handle_destroy(handle); ffrt_queue_destroy(queue_handle); ``` ## 使用建议 ### 建议1: 函数化 **åŸºæœ¬æ€æƒ³ï¼šè®¡ç®—过程函数化** * 程åºè¿‡ç¨‹å„æ¥éª¤ä»¥å‡½æ•°å°è£…表达,函数满足类纯函数特性。 * æ— å…¨å±€æ•°æ®è®¿é—®ã€‚ * æ— å†…éƒ¨çŠ¶æ€ä¿ç•™ã€‚ * 通过ffrt_submit_base()接å£ä»¥å¼‚æ¥ä»»åŠ¡æ–¹å¼æäº¤å‡½æ•°æ‰§è¡Œã€‚ * 将函数访问的数æ®å¯¹è±¡ä»¥åŠè®¿é—®æ–¹å¼åœ¨ffrt_submit_base()接å£ä¸çš„in_deps/out_deps傿•°è¡¨è¾¾ã€‚ * 程åºå‘˜é€šè¿‡inDeps/outDeps傿•°è¡¨è¾¾ä»»åС间ä¾èµ–关系以ä¿è¯ç¨‹åºæ‰§è¡Œçš„æ£ç¡®æ€§ã€‚ > åšåˆ°çº¯å‡½æ•°çš„好处在于:1. 能够最大化挖掘并行度,2.é¿å…DataRaceå’Œé”的问题。 **在实际ä¸ï¼Œå¯ä»¥æ ¹æ®åœºæ™¯æ”¾æ¾çº¯å‡½æ•°çš„约æŸï¼Œä½†å‰ææ˜¯ï¼š** * ç¡®å®šæ·»åŠ çš„in_deps/out_depså¯ç¡®ä¿ç¨‹åºæ£ç¡®æ‰§è¡Œã€‚ * 通过FFRTæä¾›çš„锿œºåˆ¶ä¿æŠ¤å¯¹å…¨å±€å˜é‡çš„访问。 ### 建议2: 使用FFRTæä¾›çš„æ›¿ä»£API * ç¦æ¢åœ¨FFRT任务ä¸ä½¿ç”¨ç³»ç»Ÿçº¿ç¨‹åº“API创建线程,使用submitæäº¤ä»»åŠ¡ã€‚ * 使用FFRTæä¾›çš„é”,æ¡ä»¶å˜é‡ï¼Œç¡çœ ,IOç‰API代替系统线程库API。 * 使用系统线程库APIå¯èƒ½é€ æˆå·¥ä½œçº¿ç¨‹é˜»å¡žï¼Œå¼•èµ·é¢å¤–性能开销。 ### 建议3: Deadline机制 * **必须用于具备周期/é‡å¤æ‰§è¡Œç‰¹å¾çš„å¤„ç†æµç¨‹ã€‚** * 在有明确时间约æŸå’Œæ€§èƒ½å…³é”®çš„å¤„ç†æµç¨‹ä¸ä½¿ç”¨ï¼Œé¿å…滥用。 * åœ¨ç›¸å¯¹å¤§é¢—ç²’åº¦çš„å¤„ç†æµç¨‹ä¸ä½¿ç”¨ï¼Œä¾‹å¦‚具有16.6ms时间约æŸçš„å¸§å¤„ç†æµç¨‹ã€‚ ### 建议4: 从线程模型è¿ç§» * 创建线程替代为创建FFRT任务。 * çº¿ç¨‹ä»Žé€»è¾‘ä¸Šç±»ä¼¼æ— in_deps的任务。 * 识别线程间的ä¾èµ–关系,并将其表达在任务的ä¾èµ–关系in_deps/out_deps上。 * 线程内计算过程分解为异æ¥ä»»åŠ¡è°ƒç”¨ã€‚ * 通过任务ä¾èµ–å…³ç³»å’Œé”æœºåˆ¶é¿å…å¹¶å‘任务数æ®ç«žäº‰é—®é¢˜ã€‚ ### 建议5: 推è使用C++æŽ¥å£ * FFRTçš„C++æŽ¥å£æ˜¯åŸºäºŽC接å£å®žçŽ°ï¼Œåœ¨ä½¿ç”¨APIæŽ¥å£æ—¶å¯ä»¥æ‰‹åŠ¨æ·»åŠ C++相关头文件åŽé…套使用。 * 相关C++接å£ä¸‹è½½å‚考:[FFRT C++接å£](https://gitee.com/openharmony/resourceschedule_ffrt/tree/master/interfaces/kits) ## 已知é™åˆ¶ ### C APIä¸åˆå§‹åŒ–ffrt对象åŽï¼Œå¯¹è±¡çš„置空与销æ¯ç”±ç”¨æˆ·è´Ÿè´£ * 为ä¿è¯è¾ƒé«˜çš„æ€§èƒ½ï¼Œffrtçš„C APIä¸å†…部ä¸åŒ…å«å¯¹å¯¹è±¡çš„销æ¯çжæ€çš„æ ‡è®°ï¼Œç”¨æˆ·éœ€è¦åˆç†åœ°è¿›è¡Œèµ„æºçš„释放,é‡å¤è°ƒç”¨å„个对象的destroyæ“作,其结果是未定义的。 * 错误示例1,é‡å¤è°ƒç”¨destroyå¯èƒ½é€ æˆä¸å¯é¢„çŸ¥çš„æ•°æ®æŸå。 ```{.c} #include "ffrt.h" void abnormal_case_1() { ffrt_task_handle_t h = ffrt_submit_h_base([](){printf("Test task running...\n");}, NULL, NULL, NULL, NULL, NULL); ... ffrt_task_handle_destroy(h); ffrt_task_handle_destroy(h); // double free } ``` * 错误示例2,未调用destroyä¼šé€ æˆå†…å˜æ³„æ¼ ```{.c} #include "ffrt.h" void abnormal_case_2() { ffrt_task_handle_t h = ffrt_submit_h_base([](){printf("Test task running...\n");}, NULL, NULL, NULL, NULL, NULL); ... // memory leak } ``` * 建议示例,仅调用一次destroy,如有必è¦å¯è¿›è¡Œç½®ç©º ```{.c} #include "ffrt.h" void normal_case() { ffrt_task_handle_t h = ffrt_submit_h_base([](){printf("Test task running...\n");}, NULL, NULL, NULL, NULL, NULL); ... ffrt_task_handle_destroy(h); h = nullptr; // if necessary } ```