1# Function Flow Runtime Development 2 3## Overview 4 5Function Flow Runtime (FFRT) is a task-based and data-driven concurrent programming model that allows you to develop an application by creating tasks and describing their dependencies. 6Specifically, FFRT automatically and concurrently schedules and executes tasks of the application based on the task dependency status and available resources, so that you can focus on feature development. 7 8This document provides guidance for you to implement concurrent programming based on the FFRT programming model. 9 10## Maintenance and Test 11 12### Timeout Monitoring 13 14FFRT provides a queue-level and task-level timeout maintenance and test mechanism to monitor the end-to-end time for scheduling queues and tasks that carry important responsibilities in user services. 15 16- When a task in the queue times out, the FFRT prints alarm logs and notifies the service through the callback. 17- When a task times out, the FFRT prints alarm logs and calls the process-level callback function. 18 19> **NOTE** 20> 21> The callback function executed when a task times out must be unique in the process and should be configured in the FFRT by the service party before the task is submitted. The callback function cannot be configured during task submission or task timeout detection. 22 23The APIs are as follows: 24 25| C++ API | C API | Description | 26| ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | ---------------------- | 27| [queue_attr::timeout](https://gitee.com/openharmony/resourceschedule_ffrt/blob/master/docs/ffrt-api-guideline-cpp.md#set-queue-timeout) | [ffrt_queue_attr_set_timeout](ffrt-api-guideline-c.md#ffrt_queue_attr_set_timeout) | Sets the queue timeout. | 28| [queue_attr::callback](https://gitee.com/openharmony/resourceschedule_ffrt/blob/master/docs/ffrt-api-guideline-cpp.md#set-queue-callback) | [ffrt_queue_attr_set_callback](ffrt-api-guideline-c.md#ffrt_queue_attr_set_callback) | Sets the queue timeout callback.| 29 30### Long-Time Task Monitoring 31 32#### Mechanism 33 34- When the task execution reaches one second, stack printing is triggered. The stack printing interval is then changed to one minute. After 10 prints, the interval is changed to 10 minutes. After another 10 prints, the interval is changed to and fixed at 30 minutes. 35- The `GetBacktraceStringByTid` API of DFX is called for stack printing. This API sends stack capture signals to the blocked thread to trigger interrupts and capture the call stack return. 36 37#### Example 38 39Search for the keyword **RecordSymbolAndBacktrace** in the corresponding process log. The following is an example of the corresponding log: 40 41```txt 42W C01719/ffrt: 60500:RecordSymbolAndBacktrace:159 Tid[16579] function occupies worker for more than [1]s. 43W C01719/ffrt: 60501:RecordSymbolAndBacktrace:164 Backtrace: 44W C01719/ffrt: #00 pc 00000000000075f0 /system/lib64/module/file/libhash.z.so 45W C01719/ffrt: #01 pc 0000000000008758 /system/lib64/module/file/libhash.z.so 46W C01719/ffrt: #02 pc 0000000000012b98 /system/lib64/module/file/libhash.z.so 47W C01719/ffrt: #03 pc 000000000002aaa0 /system/lib64/platformsdk/libfilemgmt_libn.z.so 48W C01719/ffrt: #04 pc 0000000000054b2c /system/lib64/platformsdk/libace_napi.z.so 49W C01719/ffrt: #05 pc 00000000000133a8 /system/lib64/platformsdk/libuv.so 50W C01719/ffrt: #06 pc 00000000000461a0 /system/lib64/chipset-sdk/libffrt.so 51W C01719/ffrt: #07 pc 0000000000046d44 /system/lib64/chipset-sdk/libffrt.so 52W C01719/ffrt: #08 pc 0000000000046a6c /system/lib64/chipset-sdk/libffrt.so 53W C01719/ffrt: #09 pc 00000000000467b0 /system/lib64/chipset-sdk/libffrt.so 54``` 55 56The log prints the task stack, Worker thread ID, and execution time of the long-time task. Find the corresponding component based on the stack to determine the blocking cause. 57 58#### Precautions 59 60N/A 61 62### Running Information Dump 63 64#### Mechanism 65 66FFRT provides an external interface API `ffrt_dump` to dump the internal information about the running of the FFRT subsystem, including: 67 681. FFRT statistics: number of submitted tasks, number of running tasks, number of coroutine switching times, and number of completed tasks; 692. Worker thread information: number of Worker threads in each QoS, Worker ID, ID of the running task, task name, and task type. 703. Common task information: common tasks that are not released in the current process, dump task name and ID, and call stack information of each task. 714. Queue task information: queue tasks that are not released in the current process, dump task name and ID, and call stack information of each task. 72 73When the current process is frozen, the DFX module proactively calls the `ffrt_dump` API to dump the FFRT information to the freeze file and store the file in the `/data/log/faultlog/faultlogger/` directory. You can directly use the task call stack information in the file to locate the frame freezing of the corresponding task. 74 75#### Example 76 77```txt 78ready task ptr: qos 0 readptr 79 writeptr 79 79ready task ptr: qos 1 readptr 360 writeptr 360 80ready task ptr: qos 2 readptr 19 writeptr 19 81ready task ptr: qos 3 readptr 0 writeptr 0 82ready task ptr: qos 4 readptr 0 writeptr 0 83ready task ptr: qos 5 readptr 65 writeptr 65 84ready task ptr: qos 6 readptr 0 writeptr 0 85ready task ptr: qos 7 readptr 0 writeptr 0 86submit queue: readptr 24 writeptr 24 87intr wake: status 255 88proc status: taskCnt 23 vercnt 0sigCnt0 89 |-> worker count 90 qos 0: worker num:1 tid:31676 91 qos 2: worker num:3 tid:51349, 28769, 28565 92 qos 5: worker num:1 tid:30605 93 |-> worker status 94 qos 0: worker tid 31676 is running nothing 95 qos 2: worker tid 51349 is running nothing 96 qos 2: worker tid 28769 is running, task id 24591 name sq_CesSrvMain_12_PublishCommonEventDetailed_24591 fromTid 43928 createTime 2024-11-27 02:52:27.325248 executeTime 2024-11-27 02:52:27.326150 97 qos 2: worker tid 28565 is running, task id 24611 name sq_dfx_freeze_task_queue_16_NotifyAppFaultTask_24611 fromTid 43833 createTime 2024-11-27 02:52:38.114787 executeTime 2024-11-27 02:52:38.115424 98 qos 5: worker tid 30605 is running, task id 24595 name sq_AbilityManagerService_19_SubmitTaskInner_24595 fromTid 43610 createTime 2024-11-27 02:52:27.844237 executeTime 2024-11-27 02:52:27.844573 99 |-> ready queue status 100 |-> blocked by task dependence 101 <1/1>stack: task id 3,qos 2,name AgingTask fromTid 43417 createTime 2024-11-27 01:21:39.641673 executeTime 2024-11-27 01:21:39.642290 102#00 pc 0000000000065c5c /system/lib64/ndk/libffrt.so(CoYield()+560)(22be57f01a789a03813d26a19c3a4042) 103#01 pc 00000000000a3268 /system/lib64/ndk/libffrt.so(ffrt::this_task::SleepUntilImpl(std::__h::chrono::time_point<std::__h::chrono::steady_clock, std::__h::chrono::duration<long long, std::__h::ratio<1l, 1000000000l>>> const&)+356)(22be57f01a789a03813d26a19c3a4042) 104#02 pc 00000000000a39b4 /system/lib64/ndk/libffrt.so(ffrt_usleep+60)(22be57f01a789a03813d26a19c3a4042) 105#03 pc 0000000000420de0 /system/lib64/libbms.z.so(2eb52bd03af1b9a31e14ffe60bfc39da) 106#04 pc 00000000000a6a2c /system/lib64/ndk/libffrt.so(ffrt::CPUEUTask::Execute()+300)(22be57f01a789a03813d26a19c3a4042) 107#05 pc 0000000000066d18 /system/lib64/ndk/libffrt.so(22be57f01a789a03813d26a19c3a4042) 108``` 109 110#### Precautions 111 112The DFX module has requirements on the processing time during freeze, which has a low probability that the information collected by `ffrt_dump` is incomplete and the freeze processing time expires. In this case, the information flushed to the disk is missing. 113 114### Blackbox Logs 115 116#### Mechanism 117 118When a process crashes, the FFRT module receives signals (`SIGABRT`, `SIGBUS`, `SIGFPE`, `SIGILL`, `SIGSTKFLT`, `SIGSTOP`, `SIGSYS`, and `SIGTRAP`) and saves important running information to the faultlog, including the running task, running information and call stack information of the current Worker thread, common task information, and queue task information. You can use the information to locate the crashes. 119 120#### Example 121 122```txt 123C01719/CameraDaemon/ffrt: 9986:operator():254 <<<=== ffrt black box(BBOX) start ===>>> 124C01719/CameraDaemon/ffrt: 9987:SaveCurrent:63 <<<=== current status ===>>> 125C01719/CameraDaemon/ffrt: 9988:SaveCurrent:68 signal SIGABRT triggered: source tid 5962, task id 17, qos 2, name SvrWatchdog 126C01719/CameraDaemon/ffrt: 9989:SaveWorkerStatus:94 <<<=== worker status ===>>> 127C01719/CameraDaemon/ffrt: 9990:SaveWorkerStatus:100 qos 0: worker tid 6410 is running nothing 128C01719/CameraDaemon/ffrt: 9991:SaveWorkerStatus:100 qos 2: worker tid 5968 is running nothing 129C01719/CameraDaemon/ffrt: 9992:SaveWorkerStatus:100 qos 2: worker tid 5964 is running nothing 130C01719/CameraDaemon/ffrt: 9993:SaveWorkerStatus:100 qos 2: worker tid 5963 is running nothing 131C01719/CameraDaemon/ffrt: 9994:SaveWorkerStatus:105 qos 2: worker tid 5962 is running task id 17 name SvrWatchdog 132C01719/CameraDaemon/ffrt: 9995:SaveWorkerStatus:100 qos 2: worker tid 5967 is running nothing 133C01719/CameraDaemon/ffrt: 9996:SaveWorkerStatus:100 qos 2: worker tid 5965 is running nothing 134C01719/CameraDaemon/ffrt: 9997:SaveWorkerStatus:100 qos 2: worker tid 5961 is running nothing 135C01719/CameraDaemon/ffrt: 9998:SaveWorkerStatus:100 qos 2: worker tid 1146 is running nothing 136C01719/CameraDaemon/ffrt: 9999:SaveWorkerStatus:100 qos 2: worker tid 1145 is running nothing 137C01719/CameraDaemon/ffrt: 10000:SaveWorkerStatus:100 qos 2: worker tid 5966 is running nothing 138``` 139 140#### Precautions 141 142N/A 143 144### Tracing 145 146#### Mechanism 147 148During FFRT task scheduling and execution, the system traces the task status in the FFRT framework in real time. You can use the trace graphical tool to analyze whether the task behavior meets the expectation. 149 150#### Example 151 1521. Starting trace capture 153 154 ```shell 155 hdc shell "hitrace -t 10 -b 20480 -o /data/local/tmp/in_systrace.ftrace sched freq idle ffrt" 156 # -t: specifies the trace collection duration, during which all trace records are flushed to the disk. 157 # -b: specifies the size of the trace record cache. If the buffer is insufficient, some records may be overwritten and not flushed to disks. 158 # -o: specifies the path for storing trace files. 159 ``` 160 1612. Using a graphical tool 162 163 Obtain the trace file from the device and use a graphical tool, for example, [Perfetto](https://perfetto.dev/), to analyze the file. 164 165#### Precautions 166 167You can also add traces to your service code to locate the fault. Note that in the high-frequency call process, adding traces will cause system overhead and affect service performance. 168 169### Debug Logs 170 171#### Mechanism 172 173- By default, debug logs are disabled for the FFRT, but can be enabled by using commands to obtain more maintenance and test information for fault locating in the development. 174- Enable the FFRT debug log function: 175 176 ```shell 177 hdc shell hilog -b DEBUG -D 0xD001719 178 ``` 179 180- Restore the default FFRT INFO log level. 181 182 ```shell 183 hdc shell hilog -b INFO -D 0xD001719 184 ``` 185 186#### Example 187 188```txt 1894190 5631 D C01719/neboard:EngineServiceAbility:1/ffrt: 275337:Detach:147 qos 3 thread not joinable 1903257 6075 D C01719/com.ohos.sceneboard/ffrt: 513070:SetDefaultThreadAttr:148 qos apply tid[6075] level[3] 191``` 192 193#### Precautions 194 195The FFRT is the system base and supports the running of a large number of upper-layer services and frameworks. If the debug log function is enabled globally, the number of logs will exceed the threshold, which affects the log output of other modules. 196 197## How to Develop 198 199The following describes how to use the native APIs provided by FFRT to create parallel tasks and serial queue tasks and destroy corresponding resources. 200 2011. Add a dynamic link library to the `CMakeLists.txt` project. 202 203 ```txt 204 libffrt.z.so 205 ``` 206 2072. Include the following header files in the project. 208 209 ```cpp 210 #include "ffrt/task.h" 211 #include "ffrt/type_def.h" 212 #include "ffrt/condition_variable.h" 213 #include "ffrt/loop.h" 214 #include "ffrt/mutex.h" 215 #include "ffrt/queue.h" 216 #include "ffrt/sleep.h" 217 #include "ffrt/timer.h" 218 ``` 219 2203. Encapsulate the function to be executed. 221 222 ```cpp 223 // Method 1: Use the template. C++ is supported. 224 template<class T> 225 struct function { 226 ffrt_function_header_t header; 227 T closure; 228 }; 229 230 template<class T> 231 void exec_function_wrapper(void* t) 232 { 233 auto f = reinterpret_cast<function<std::decay_t<T>>*>(t); 234 f->closure(); 235 } 236 237 template<class T> 238 void destroy_function_wrapper(void* t) 239 { 240 auto f = reinterpret_cast<function<std::decay_t<T>>*>(t); 241 f->closure = nullptr; 242 } 243 244 template<class T> 245 inline ffrt_function_header_t* create_function_wrapper(T&& func, 246 ffrt_function_kind_t kind = ffrt_function_kind_general) 247 { 248 using function_type = function<std::decay_t<T>>; 249 static_assert(sizeof(function_type) <= ffrt_auto_managed_function_storage_size, 250 "size of function must be less than ffrt_auto_managed_function_storage_size"); 251 252 auto p = ffrt_alloc_auto_managed_function_storage_base(kind); 253 auto f = new (p)function_type; 254 f->header.exec = exec_function_wrapper<T>; 255 f->header.destroy = destroy_function_wrapper<T>; 256 f->closure = std::forward<T>(func); 257 return reinterpret_cast<ffrt_function_header_t*>(f); 258 } 259 260 // Method 2 261 typedef struct { 262 ffrt_function_header_t header; 263 ffrt_function_t func; 264 ffrt_function_t after_func; 265 void* arg; 266 } c_function_t; 267 268 static inline void ffrt_exec_function_wrapper(void* t) 269 { 270 c_function_t* f = (c_function_t *)t; 271 if (f->func) { 272 f->func(f->arg); 273 } 274 } 275 276 static inline void ffrt_destroy_function_wrapper(void* t) 277 { 278 c_function_t* f = (c_function_t *)t; 279 if (f->after_func) { 280 f->after_func(f->arg); 281 } 282 } 283 284 #define FFRT_STATIC_ASSERT(cond, msg) int x(int static_assertion_##msg[(cond) ? 1 : -1]) 285 static inline ffrt_function_header_t *ffrt_create_function_wrapper(const ffrt_function_t func, 286 const ffrt_function_t after_func, void *arg) 287 { 288 FFRT_STATIC_ASSERT(sizeof(c_function_t) <= ffrt_auto_managed_function_storage_size, 289 size_of_function_must_be_less_than_ffrt_auto_managed_function_storage_size); 290 291 c_function_t* f = (c_function_t *)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); 292 f->header.exec = ffrt_exec_function_wrapper; 293 f->header.destroy = ffrt_destroy_function_wrapper; 294 f->func = func; 295 f->after_func = after_func; 296 f->arg = arg; 297 return (ffrt_function_header_t *)f; 298 } 299 300 // Example: function to be submitted for execution. 301 void OnePlusForTest(void* arg) 302 { 303 (*static_cast<int*>(arg)) += 1; 304 } 305 ``` 306 3074. Set task attributes, including the QoS level and task name. 308 309 ```cpp 310 // ******Initialize the attributes of the parallel task****** 311 ffrt_task_attr_t attr; 312 ffrt_task_attr_init(&attr); 313 314 // ******Create a serial queue****** 315 316 // Create the attributes of the serial queue. 317 ffrt_queue_attr_t queue_attr; 318 // Create the handle to the serial queue. 319 ffrt_queue_t queue_handle; 320 321 // Initialize the queue attribute. 322 (void)ffrt_queue_attr_init(&queue_attr); 323 324 // Set the QoS if necessary. 325 ffrt_queue_attr_set_qos(&queue_attr, static_cast<ffrt_qos_t>(ffrt_qos_inherit)); 326 // Set the timeout period (ms) if necessary. 327 ffrt_queue_attr_set_timeout(&queue_attr, 10000); 328 // Set the timeout callback if necessary. 329 int x = 0; 330 ffrt_queue_attr_set_callback(&queue_attr, ffrt_create_function_wrapper(OnePlusForTest, NULL, &x, 331 ffrt_function_kind_queue)); 332 333 // Initialize the queue based on the attributes. 334 queue_handle = ffrt_queue_create(ffrt_queue_serial, "test_queue", &queue_attr); 335 ``` 336 3375. Submit the task. 338 339 ```cpp 340 int a = 0; 341 // ******Parallel task****** 342 // Submit the parallel task without obtaining a handle. 343 ffrt_submit_base(ffrt_create_function_wrapper(OnePlusForTest, NULL, &a), NULL, NULL, &attr); 344 // Submit the parallel task and obtain a handle. 345 ffrt_task_handle_t task = ffrt_submit_h_base( 346 ffrt_create_function_wrapper(OnePlusForTest, NULL, &a), NULL, NULL, &attr); 347 348 // ******Serial queue task****** 349 // Submit the serial queue task without obtaining a handle. 350 ffrt_queue_submit(queue_handle, ffrt_create_function_wrapper(OnePlusForTest, nullptr, &a, 351 ffrt_function_kind_queue), nullptr); 352 // Submit the serial queue task and obtain a handle. 353 ffrt_task_handle_t handle = ffrt_queue_submit_h(queue_handle, 354 ffrt_create_function_wrapper(OnePlusForTest, nullptr, &a, ffrt_function_kind_queue), nullptr); 355 356 // Call wait if you need to wait for the execution result. 357 const std::vector<ffrt_dependence_t> wait_deps = {{ffrt_dependence_task, task}}; 358 ffrt_deps_t wait{static_cast<uint32_t>(wait_deps.size()), wait_deps.data()}; 359 ffrt_wait_deps(&wait); 360 361 ffrt_queue_wait(handle); 362 ``` 363 3646. Destroy the resources after the task is submitted. 365 366 ```cpp 367 // ******Destroy the parallel task****** 368 ffrt_task_attr_destroy(&attr); 369 ffrt_task_handle_destroy(task); 370 371 // ******Destroy the serial queue task****** 372 // Destroy the task handle and then the queue. 373 ffrt_queue_attr_destroy(&queue_attr); 374 ffrt_task_handle_destroy(handle); 375 ffrt_queue_destroy(queue_handle); 376 ``` 377 378## Suggestions 379 380### Suggestion 1: Functional Programming 381 382- Use pure functions and encapsulate them to express each step of the process. 383- There is no global data access. 384- There is no internal state reserved. 385- Use `ffrt_submit_base()` to submit a function in asynchronous mode for execution. 386- Use `in_deps` and `out_deps` of `ffrt_submit_base()` to specify the data objects to be accessed by the function and the access mode. 387- Programmers use the `in_deps` and `out_deps` parameters to express task dependencies to ensure the correctness of program execution. 388 389> Using pure functions helps you maximize the parallelism and avoid data races and lock abuse. 390> 391> In practice, you may not use pure functions in certain scenarios, with the following prerequisites: 392> 393> - `in_deps` and `out_deps` can ensure the correctness of program execution. 394> - The lock mechanism provided by FFRT is used to protect access to global variables. 395 396### Suggestion 2: Using FFRT APIs 397 398- Do not use the APIs of the system thread library to create threads in FFRT tasks. Instead, use `submit` to submit tasks. 399- Use the lock, condition variable, sleep, and I/O APIs provided by FFRT to replace the APIs of the system thread library. 400 - Using the APIs of the system thread library may block worker threads and result in extra performance overhead. 401 402### Suggestion 3: Deadline Mechanism 403 404- Use FFRT APIs in processing flows that feature periodic/repeated execution. 405- Use FFRT APIs in processing flows with clear time constraints and is performance critical. 406- Use FFRT APIs in relatively large-granularity processing flows, such as the frame processing flow with the 16.6 ms time constraint. 407 408### Suggestion 4: Migration from the Thread Model 409 410- Create a thread instead of creating an FFRT task. 411 - A thread is logically similar to a task without `in_deps`. 412- Identify the dependency between threads and express the dependencies in `in_deps` and `out_deps` of the task. 413- Decompose an intra-thread computing process into asynchronous tasks for invoking. 414- Use the task dependency and lock mechanism to avoid data races of concurrent tasks. 415 416### Suggestion 5: C++ APIs Recommended 417 418- The FFRT C++ APIs are implemented based on the C APIs. Before using the APIs, you can manually add the C++ header file. 419 420## Constraints 421 422### Thread Local Variables 423 424Risks exist when thread local variables are used in FFRT tasks. The details are as follows: 425 426- Thread local variables include the variables defined by `thread_local` provided by C/C++ and the variables created by using `thread_local`. 427- FFRT supports task scheduling. The thread to which a task is scheduled is random. Therefore, there are risks to use thread local variables, which is consistent with all other frameworks that support concurrent task scheduling. 428- By default, an FFRT task runs in coroutine mode. During task execution, the coroutine may exit. When the task is resumed, the thread that executes the task may change. 429 430### Thread Binding 431 432- FFRT supports task scheduling. The thread to which a task is scheduled is random. Thread-bound behaviors, such as thread_idx, thread priority, and thread affinity, cannot be used in tasks. 433 434### Synchronization Primitives in the Standard Library 435 436A deadlock may occur when the mutex of the standard library is used in the FFRT task. You need to use the mutex provided by the FFRT. The details are as follows: 437 438- When `lock()` is successfully executed, the mutex records the execution stack of the caller as the owner of the lock. If the caller is the current execution stack, a success message is returned to support nested lock obtaining in the same execution stack. In implementation of the standard library, the "execution stack" is represented by a thread identifier. 439- When the mutex of the standard library is used in the FFRT task, if the task (coroutine) exits between the outer and inner lock and the task is resumed on the FFRT Worker thread that is different from the thread that calls `lock()` for the first time, the calling thread is not the owner and `lock()` fails to be called, the FFRT Worker thread is suspended, and `unlock()` is not executed. As a result, a deadlock occurs. 440 441### Support for the Process `fork()` Scenario 442 443- Create a child process in a process that does not use FFRT. FFRT can be used in the child process. 444- Create a child process using `fork()` in a process that uses FFRT. FFRT cannot be used in the child process. 445- Create a child process using `fork()` and `exec()` in a process that uses FFRT. FFRT can be used in the child process. 446 447### Dynamic FFRT Deployment 448 449- Static library deployment may cause multi-instance problems. For example, when multiple .so files loaded by the same process use FFRT in static library mode, FFRT is instantiated into multiple copies, and their behavior is unknown. 450 451### Limited Number of Input and Output Dependencies 452 453- For `ffrt_submit_base`, the total number of input dependencies and output dependencies of each task cannot exceed 8. 454- For `ffrt_submit_h_base`, the total number of input dependencies and output dependencies of each task cannot exceed 7. 455- When a parameter is used as both an input dependency and an output dependency, it is counted as one dependency. For example, if the input dependency is `{&x}` and the output dependency is also `{&x}`, then the number of dependencies is 1. 456 457### Restrictions on Process or Thread Exit 458 459- When a process exits, the shared resources in the process, such as the thread pool in the FFRT, have been released. **submit()** should not be called. 460- When a thread exits, the thread local resources in the FFRT have been released. **submit()** should not be called for the thread that is exiting. 461 462## Common Anti-Patterns 463 464### After an FFRT object is initialized in the C code, you are responsible for setting the object to null or destroying the object. 465 466- To ensure high performance, the C APIs of FFRT do not use a flag to indicate the object destruction status. You need to release resources properly. Repeatedly destroying an object will cause undefined behavior. 467- Noncompliant example 1: Repeated calling of destroy() may cause unpredictable data damage. 468 469 ```cpp 470 #include <stdio.h> 471 #include "ffrt/cpp/task.h" 472 473 void abnormal_case_1() 474 { 475 ffrt_task_handle_t h = ffrt_submit_h_base( 476 ffrt::create_function_wrapper(std::function<void()>([](){ printf("Test task running...\n"); })), 477 NULL, NULL, NULL); 478 // ... 479 ffrt_task_handle_destroy(h); 480 ffrt_task_handle_destroy(h); // Repeated release 481 } 482 ``` 483 484- Noncompliant example 2: No calling of destroy() may cause memory leak. 485 486 ```cpp 487 #include <stdio.h> 488 #include "ffrt/cpp/task.h" 489 490 void abnormal_case_2() 491 { 492 ffrt_task_handle_t h = ffrt_submit_h_base( 493 ffrt::create_function_wrapper(std::function<void()>([](){ printf("Test task running...\n"); })), 494 NULL, NULL, NULL); 495 // ... 496 // Memory leak 497 } 498 ``` 499 500- Recommended example: Call **destroy()** only once. You can leave it empty if necessary. 501 502 ```cpp 503 #include <stdio.h> 504 #include "ffrt/cpp/task.h" 505 506 void normal_case() 507 { 508 ffrt_task_handle_t h = ffrt_submit_h_base( 509 ffrt::create_function_wrapper(std::function<void()>([](){ printf("Test task running...\n"); })), 510 NULL, NULL, NULL); 511 // ... 512 ffrt_task_handle_destroy(h); 513 h = nullptr; // Set the task handle variable to null if necessary. 514 } 515 ``` 516 517### Incorrect Variable Lifecycle 518 519- When submitting an FFRT task, pay attention to the misuse of objects or resources during their lifecycle. These misuses may cause program breakdown, data damage, or difficult debugging. 520- Noncompliant example 1: Ended variable lifecycle causes a UAF problem. 521 522 ```cpp 523 #include <unistd.h> 524 #include "ffrt/cpp/task.h" 525 526 void abnormal_case_3() 527 { 528 int x = 0; 529 ffrt::submit([&] { 530 usleep(1000); // Simulate the service processing logic. 531 x++; // The variable lifecycle may have ended, and a UAF problem may occur when the variable is accessed. 532 }); 533 } 534 ``` 535 536- Noncompliant example 2: Ended mutex lifecycle causes function exceptions. 537 538 ```cpp 539 #include <unistd.h> 540 #include "ffrt/cpp/mutex.h" 541 #include "ffrt/cpp/task.h" 542 543 void abnormal_case_4() 544 { 545 ffrt::mutex lock; 546 ffrt::submit([&] { 547 lock.lock(); // When performing operations on the FFRT lock, ensure that the lifecycle of the FFRT lock is valid. 548 usleep(1000); // Simulate the service processing logic. 549 lock.unlock(); // When performing operations on the FFRT lock, ensure that the lifecycle of the FFRT lock is valid. 550 }); 551 } 552 ``` 553 554## Using FFRT in DevEco IDE 555 556### Using FFRT C API 557 558Native Development Kit (NDK) is a toolset provided by HarmonyOS SDK. It offers native APIs that allow you to implement key application functions using C or C++ code. 559 560The FFRT C APIs have been integrated into the NDK. You can directly use the corresponding API in DevEco IDE. 561 562```cpp 563#include "ffrt/type_def.h" 564#include "ffrt/task.h" 565#include "ffrt/queue.h" 566#include "ffrt/condition_variable.h" 567#include "ffrt/mutex.h" 568#include "ffrt/shared_mutex.h" 569#include "ffrt/sleep.h" 570#include "ffrt/loop.h" 571#include "ffrt/timer.h" 572``` 573 574### Using FFRT C++ API 575 576The FFRT deployment depends on the FFRT dynamic library `libffrt.so` and a group of header files. The dynamic library exports only C APIs, and C++ APIs call C APIs. In addition, C++ elements in APIs are compiled into the dynamic library based on the header files, ensuring ABI compatibility. 577 578 579 580To use FFRT C++ APIs, you need to use the FFRT third-party library [@ppd/ffrt](https://ohpm.openharmony.cn/#/en/detail/@ppd%2Fffrt), which is a C++ API library officially maintained by FFRT. 581 582Run the following command in the module directory to install the third-party library: 583 584```shell 585ohpm install @ppd/ffrt 586``` 587 588You can also configure the dependencies in the `oh-package.json5` file so that the third-party library can be automatically downloaded and installed through DevEco Studio. 589 590Add dependencies to the `CMakeLists.txt` file: 591 592```txt 593target_link_libraries(<target_name> PUBLIC libffrt.z.so ffrt::ffrtapi) 594``` 595 596Use the FFRT C++ API in the code. 597 598```cpp 599#include "ffrt/cpp/task.h" 600#include "ffrt/cpp/queue.h" 601#include "ffrt/cpp/condition_variable.h" 602#include "ffrt/cpp/mutex.h" 603#include "ffrt/cpp/shared_mutex.h" 604#include "ffrt/cpp/sleep.h" 605``` 606 607 <!--no_check-->