• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![image](figures/ffrt_figure7.png)
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-->