1# Function Flow Runtime C APIs 2 3## Task Management 4 5### ffrt_deps_t 6 7#### Declaration 8 9```c 10typedef enum { 11 ffrt_dependence_data, 12 ffrt_dependence_task, 13} ffrt_dependence_type_t; 14 15typedef struct { 16 ffrt_dependence_type_t type; 17 const void* ptr; 18} ffrt_dependence_t; 19 20typedef struct { 21 uint32_t len; 22 const ffrt_dependence_t* items; 23} ffrt_deps_t; 24``` 25 26#### Parameters 27 28- `len`: number of data dependencies. 29- `items`: data dependency array. The data length is equal to `len`. 30- `ptr`: data address. 31- `type`: data type. It is different from `task_handle`. 32 33#### Description 34 35The function of `ffrt_dependence_t` is the same as that of `dependence` in C++, and the function of `ffrt_deps_t` is the same as that of `std::vector<dependence>` in C++. 36 37#### Example 38 39```c 40// Create a data dependency. 41int x = 0; 42ffrt_dependence_t dependence[1]; 43dependence[0].type = ffrt_dependence_data; 44dependence[0].ptr = &x; 45ffrt_deps_t deps; 46deps.len = 1; 47deps.items = dependence; 48 49// Create a task dependency. 50ffrt_task_handle_t task = ffrt_submit_h_base(user_function_header, NULL, NULL, &attr); 51ffrt_dependence_t dependence[1]; 52dependence[0].type = ffrt_dependence_task; 53dependence[0].ptr = task; 54ffrt_deps_t deps; 55deps.len = 1; 56deps.items = dependence; 57``` 58 59### ffrt_task_attr_t 60 61#### Declaration 62 63```c 64typedef struct { 65 uint32_t storage[(ffrt_task_attr_storage_size + sizeof(uint32_t) - 1) / sizeof(uint32_t)]; 66} ffrt_task_attr_t; 67``` 68 69#### Description 70 71Describes the task attribute, which can be configured using `ffrt_task_attr_t` when submitting a common task or queue task. 72 73#### Methods 74 75##### ffrt_task_attr_init 76 77```c 78FFRT_C_API int ffrt_task_attr_init(ffrt_task_attr_t* attr); 79``` 80 81Parameters 82 83- `attr`: pointer to the `ffrt_task_attr_t` object. 84 85Return Values 86 87- The value **0** indicates success, and the value **-1** indicates failure. 88 89Description 90 91- Initializes an `ffrt_task_attr_t` object. 92 93##### ffrt_task_attr_destroy 94 95```c 96FFRT_C_API void ffrt_task_attr_destroy(ffrt_task_attr_t* attr); 97``` 98 99Parameters 100 101- `attr`: pointer to the `ffrt_task_attr_t` object. 102 103Description 104 105- Destroys an `ffrt_task_attr_t` object. 106 107##### ffrt_task_attr_set_name 108 109```c 110FFRT_C_API void ffrt_task_attr_set_name(ffrt_task_attr_t* attr, const char* name); 111``` 112 113Parameters 114 115- `attr`: pointer to the `ffrt_task_attr_t` object. 116- `name`: task name. 117 118Description 119 120- Sets the task name, which is valid for printing maintenance and test information. 121 122##### ffrt_task_attr_get_name 123 124```c 125FFRT_C_API const char* ffrt_task_attr_get_name(const ffrt_task_attr_t* attr); 126``` 127 128Parameters 129 130- `attr`: pointer to the `ffrt_task_attr_t` object. 131 132Return Values 133 134- Task name. 135 136Description 137 138- Obtains the task name. 139 140##### ffrt_task_attr_set_qos 141 142```c 143FFRT_C_API void ffrt_task_attr_set_qos(ffrt_task_attr_t* attr, ffrt_qos_t qos); 144``` 145 146Parameters 147 148- `attr`: pointer to the `ffrt_task_attr_t` object. 149- `qos`: QoS. 150 151Description 152 153- Sets the task QoS, which determines the system resource supply during task execution. If QoS is not set, the queue QoS is inherited by default. The default QoS of a common task is `ffrt_qos_default`. 154 155##### ffrt_task_attr_get_qos 156 157```c 158FFRT_C_API ffrt_qos_t ffrt_task_attr_get_qos(const ffrt_task_attr_t* attr); 159``` 160 161Parameters 162 163- `attr`: pointer to the `ffrt_task_attr_t` object. 164 165Return Values 166 167- QoS. 168 169Description 170 171- Obtains the configured QoS. 172 173##### ffrt_task_attr_set_delay 174 175```c 176FFRT_C_API void ffrt_task_attr_set_delay(ffrt_task_attr_t* attr, uint64_t delay_us); 177``` 178 179Parameters 180 181- `attr`: pointer to the `ffrt_task_attr_t` object. 182- `delay_us`: scheduling delay. The unit is μs. 183 184Description 185 186- Sets the scheduling delay of a task. The task is scheduled and executed after the delay interval. If delay is not set, the value is **0** by default. 187 188##### ffrt_task_attr_get_delay 189 190```c 191FFRT_C_API uint64_t ffrt_task_attr_get_delay(const ffrt_task_attr_t* attr); 192``` 193 194Parameters 195 196- `attr`: pointer to the `ffrt_task_attr_t` object. 197 198Return Values 199 200- Scheduling delay. 201 202Description 203 204- Obtains the configured scheduling delay. 205 206##### ffrt_task_attr_set_queue_priority 207 208```c 209FFRT_C_API void ffrt_task_attr_set_queue_priority(ffrt_task_attr_t* attr, ffrt_queue_priority_t priority); 210``` 211 212Parameters 213 214- `attr`: pointer to the `ffrt_task_attr_t` object. 215- `priority`: task priority. 216 217Description 218 219- Sets the task priority. Currently, only concurrent queue tasks support the priority function. Tasks in the same concurrent queue are scheduled based on their priorities. If the priority is not set, `ffrt_queue_priority_low` is used by default. 220 221##### ffrt_task_attr_get_queue_priority 222 223```c 224FFRT_C_API ffrt_queue_priority_t ffrt_task_attr_get_queue_priority(const ffrt_task_attr_t* attr); 225``` 226 227Parameters 228 229- `attr`: pointer to the `ffrt_task_attr_t` object. 230 231Return Values 232 233- Task priority. 234 235Description 236 237- Obtains the configured priority. 238 239##### ffrt_task_attr_set_stack_size 240 241```c 242FFRT_C_API void ffrt_task_attr_set_stack_size(ffrt_task_attr_t* attr, uint64_t size); 243``` 244 245Parameters 246 247- `attr`: pointer to the `ffrt_task_attr_t` object. 248- `size`: size of the coroutine stack, in bytes. 249 250Description 251 252- Sets the size of the coroutine stack, which affects the maximum space used by the call stack during task execution. If this parameter is not set, the default size of the coroutine stack is 1 MB. 253 254##### ffrt_task_attr_get_stack_size 255 256```c 257FFRT_C_API uint64_t ffrt_task_attr_get_stack_size(const ffrt_task_attr_t* attr); 258``` 259 260Parameters 261 262- `attr`: pointer to the `ffrt_task_attr_t` object. 263 264Return Values 265 266- Size of the coroutine stack. 267 268Description 269 270- Obtains the size of the coroutine stack. 271 272#### Example 273 274```c 275// Submit a common task. The task name is sample_task, the QoS is background, the scheduling delay is 1 ms, and the coroutine stack size is 2 MB. 276ffrt_task_attr_t attr; 277ffrt_task_attr_init(&attr); 278ffrt_task_attr_set_name(&attr, "sample_task"); 279ffrt_task_attr_set_qos(&attr, ffrt_qos_background); 280ffrt_task_attr_set_delay(&attr, 1000); 281ffrt_task_attr_set_stack_size(&attr, 2 * 1024 * 1024); 282ffrt_submit_base(user_function_header, NULL, NULL, &attr); 283ffrt_task_attr_destroy(&attr); 284``` 285 286### ffrt_alloc_auto_managed_function_storage_base 287 288#### Declaration 289 290```c 291typedef enum { 292 ffrt_function_kind_general, 293 ffrt_function_kind_queue, 294} ffrt_function_kind_t; 295 296typedef void(*ffrt_function_t)(void*); 297typedef struct { 298 ffrt_function_t exec; 299 ffrt_function_t destroy; 300 uint64_t reserve[2]; 301} ffrt_function_header_t; 302 303FFRT_C_API void *ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_t kind); 304``` 305 306#### Parameters 307 308- `kind`: `ffrt_function_kind_general` for submitting a common task; `ffrt_function_kind_queue` for submitting a queue task. 309- `exec`: function pointer invoked during task execution. 310- `destroy`: function pointer invoked after a task is complete. It can be used to destroy resources. 311- `reserve`: internal reserved space. It cannot be used by users. 312 313#### Return Values 314 315- Pointer to the executor of the user task. 316 317#### Description 318 319Allocates memory space. The header of the memory space is in the `ffrt_function_header_t` structure. The return pointer can be converted into the `ffrt_function_header_t*` pointer. A 64-byte space is reserved after the header for customizing the space for storing input parameters or return values. 320 321#### Example 322 323- Example 1: Generate a task executor without parameters and return values. 324 325 ```c 326 #include <stdio.h> 327 #include "ffrt/task.h" 328 329 void foo(void* data) 330 { 331 printf("foo\n"); 332 } 333 334 void after_foo(void* data) 335 { 336 printf("after_foo\n"); 337 } 338 339 int main() 340 { 341 ffrt_function_header_t* func = (ffrt_function_header_t*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); 342 343 func->exec = foo; 344 func->destroy = after_foo; 345 346 ffrt_submit_base(func, NULL, NULL, NULL); 347 ffrt_wait(); 348 349 return 0; 350 } 351 ``` 352 353- Example 2: Generate a task executor with parameters and return values. 354 355 ```c 356 #include <stdio.h> 357 #include "ffrt/task.h" 358 359 int foo(int x, int y) 360 { 361 printf("foo: x = %d, y = %d\n", x, y); 362 return x + y; 363 } 364 365 void after_foo(void* data) 366 { 367 printf("after_foo\n"); 368 } 369 370 // Custom task executor, which can carry parameters and return values. 371 typedef struct { 372 ffrt_function_header_t header; // The header space is ffrt_function_header_t. 373 int arg1; // Argument 1 374 int arg2; // Argument 2 375 int ret; // Return value 376 } user_defined_function; 377 378 // Wrap foo into the exec function type of void(*)(void*). 379 void exec_func_wrapper(void* header) 380 { 381 user_defined_function* func = (user_defined_function*)header; 382 func->ret = foo(func->arg1, func->arg2); // Expand the foo function, pass arguments, and obtain the return value. 383 } 384 385 int main() 386 { 387 user_defined_function* func = (user_defined_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); 388 389 func->header.exec = exec_func_wrapper; 390 func->header.destroy = after_foo; 391 func->arg1 = 1; 392 func->arg2 = 2; 393 394 ffrt_submit_base((ffrt_function_header_t*)func, NULL, NULL, NULL); 395 ffrt_wait(); 396 397 printf("ret = %d\n", func->ret); 398 return 0; 399 } 400 ``` 401 402### ffrt_submit_base 403 404#### Declaration 405 406```c 407FFRT_C_API void 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); 408``` 409 410#### Parameters 411 412- `f`: task executor of a user. The value can be of the native `ffrt_function_header_t` type or a custom extension type based on `ffrt_function_header_t`. 413- `in_deps`: input data dependency of a task. It is usually expressed as the actual data address. `ffrt_task_handle_t` can also be used as a special input dependency. 414- `out_deps`: output data dependency of a task. It is usually expressed as the actual data address. `ffrt_task_handle_t` is not supported. 415- `attr`: task attribute. 416 417#### Description 418 419Submits a common task that supports attribute settings. After the input dependency is removed, the task can be scheduled and executed. After the task is executed, the output dependency is removed. 420 421#### Example 422 423- Example 1: Submit a task with attributes. 424 425 ```c 426 #include <stdio.h> 427 #include "ffrt/task.h" 428 429 void foo(void* data) 430 { 431 printf("foo\n"); 432 } 433 434 void after_foo(void* data) 435 { 436 printf("after_foo\n"); 437 } 438 439 int main() 440 { 441 // Submit a task. 442 ffrt_function_header_t* func = (ffrt_function_header_t*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); 443 func->exec = foo; 444 func->destroy = after_foo; 445 ffrt_submit_base(func, NULL, NULL, NULL); 446 447 // Submit a task with attributes. 448 ffrt_task_attr_t attr; 449 ffrt_task_attr_init(&attr); 450 ffrt_task_attr_set_name(&attr, "sample_task"); 451 ffrt_task_attr_set_qos(&attr, ffrt_qos_background); 452 ffrt_submit_base(func, NULL, NULL, &attr); 453 454 return 0; 455 } 456 ``` 457 458- Example 2: Submit a task with data dependency. 459 460 ```c 461 // Submit two tasks with data dependency. The Read-After-Write dependency exists between tasks. 462 #include <math.h> 463 #include <stdio.h> 464 #include "ffrt/task.h" 465 466 void cos_func(float* x, float* y) 467 { 468 *y = cos(*x); 469 } 470 471 void tan_func(float* y, float* z) 472 { 473 *z = tan(*y); 474 } 475 476 typedef struct { 477 ffrt_function_header_t header; 478 float* arg1; // Argument 1 479 float* arg2; // Argument 2 480 } user_defined_function; 481 482 void cos_func_wrapper(void* header) 483 { 484 user_defined_function* func = (user_defined_function*)header; 485 cos_func(func->arg1, func->arg2); 486 } 487 488 void tan_func_wrapper(void* header) 489 { 490 user_defined_function* func = (user_defined_function*)header; 491 tan_func(func->arg1, func->arg2); 492 } 493 494 void destroy(void* header) {} 495 496 int main() 497 { 498 float x = 0.5f, y, z; 499 500 user_defined_function* func1 = (user_defined_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); 501 func1->header.exec = cos_func_wrapper; 502 func1->header.destroy = destroy; 503 func1->arg1 = &x; 504 func1->arg2 = &y; 505 506 user_defined_function* func2 = (user_defined_function*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); 507 func2->header.exec = tan_func_wrapper; 508 func2->header.destroy = destroy; 509 func2->arg1 = &y; 510 func2->arg2 = &z; 511 512 ffrt_dependence_t dependence_x[1]; 513 dependence_x[0].type = ffrt_dependence_data; 514 dependence_x[0].ptr = &x; 515 ffrt_deps_t deps_x; 516 deps_x.len = 1; 517 deps_x.items = dependence_x; 518 ffrt_dependence_t dependence_y[1]; 519 dependence_y[0].type = ffrt_dependence_data; 520 dependence_y[0].ptr = &y; 521 ffrt_deps_t deps_y; 522 deps_y.len = 1; 523 deps_y.items = dependence_y; 524 ffrt_dependence_t dependence_z[1]; 525 dependence_z[0].type = ffrt_dependence_data; 526 dependence_z[0].ptr = &z; 527 ffrt_deps_t deps_z; 528 deps_z.len = 1; 529 deps_z.items = dependence_z; 530 531 ffrt_submit_base((ffrt_function_header_t*)func1, &deps_x, &deps_y, NULL); 532 ffrt_submit_base((ffrt_function_header_t*)func2, &deps_y, &deps_z, NULL); 533 534 ffrt_wait(); 535 printf("x = %f, y = %f, z = %f\n", x, y, z); 536 return 0; 537 } 538 ``` 539 540### ffrt_submit_h_base 541 542#### Declaration 543 544```c 545typedef void* ffrt_task_handle_t; 546 547FFRT_C_API ffrt_task_handle_t 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); 548``` 549 550#### Parameters 551 552- `f`: task executor of a user. The value can be of the native `ffrt_function_header_t` type or a custom extension type based on `ffrt_function_header_t`. 553- `in_deps`: input data dependency of a task. It is usually expressed as the actual data address. `ffrt_task_handle_t` can also be used as a special input dependency. 554- `out_deps`: output data dependency of a task. It is usually expressed as the actual data address. `ffrt_task_handle_t` is not supported. 555- `attr`: task attribute. 556 557#### Return Values 558 559- `ffrt_task_handle_t` task handle. 560 561#### Description 562 563Compared with the `ffrt_submit_base` API, the return value of the task handle is added. 564 565#### Example 566 567```c 568// Submit a task and obtain the task handle. 569ffrt_function_header_t* func = (ffrt_function_header_t*)ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_general); 570func->exec = foo; 571func->destroy = after_foo; 572ffrt_task_handle_t t = ffrt_submit_h_base(func, NULL, NULL, NULL); 573// Note that ffrt_task_handle_t of the C API needs to be explicitly destroyed by calling ffrt_task_handle_destroy. 574ffrt_task_handle_destroy(t); 575``` 576 577### ffrt_task_handle_inc_ref 578 579#### Declaration 580 581```c 582FFRT_C_API uint32_t ffrt_task_handle_inc_ref(ffrt_task_handle_t handle); 583``` 584 585#### Parameters 586 587- `handle`: task handle. 588 589#### Return Values 590 591- Reference count of a task. 592 593#### Description 594 595Increases the reference count of the task through the task handle by one each time the task handle is invoked. It is used to control the task lifecycle. When the reference count is not 0, the corresponding task resources are not released. Note that `ffrt_task_handle_t` returned by `ffrt_submit_h_base` has a reference count by default. By default, you can subtract a reference count when using `ffrt_task_handle_destroy` to destroy `ffrt_task_handle_t`. 596 597### ffrt_task_handle_dec_ref 598 599#### Declaration 600 601```c 602FFRT_C_API uint32_t ffrt_task_handle_dec_ref(ffrt_task_handle_t handle); 603``` 604 605#### Parameters 606 607- `handle`: task handle. 608 609#### Return Values 610 611- Reference count of a task. 612 613#### Description 614 615Subtracts the reference count of the task through the task handle by one each time the task handle is invoked. 616 617### ffrt_task_handle_destroy 618 619#### Declaration 620 621```c 622FFRT_C_API void ffrt_task_handle_destroy(ffrt_task_handle_t handle); 623``` 624 625#### Parameters 626 627- `handle`: task handle. 628 629#### Description 630 631Destroys a task handle and subtracts a task reference count by default. 632 633### ffrt_wait 634 635#### Declaration 636 637```c 638FFRT_C_API void ffrt_wait(void); 639``` 640 641#### Description 642 643Waits until all tasks of the same level submitted earlier are complete. 644 645#### Example 646 647```c 648// Wait until three tasks are complete. 649ffrt_submit_base(func1, NULL, NULL, NULL); 650ffrt_submit_base(func2, NULL, NULL, NULL); 651ffrt_submit_base(func3, NULL, NULL, NULL); 652ffrt_wait(); 653``` 654 655### ffrt_wait_deps 656 657#### Declaration 658 659```c 660FFRT_C_API void ffrt_wait_deps(const ffrt_deps_t* deps); 661``` 662 663#### Parameters 664 665- `deps`: data dependency to be synchronized. 666 667#### Description 668 669Waits until the data dependency is removed. 670 671#### Example 672 673```c 674// Build the data dependency of x. 675int x = 0; 676ffrt_dependence_t dependence[1]; 677dependence[0].type = ffrt_dependence_data; 678dependence[0].ptr = &x; 679ffrt_deps_t deps; 680deps.len = 1; 681deps.items = dependence; 682 683// Submit a write task. 684ffrt_submit_base(func, NULL, &deps, NULL); 685 686// Wait until the data dependency of the write task is removed. 687ffrt_wait_deps(&deps); 688``` 689 690### ffrt_this_task_update_qos 691 692#### Declaration 693 694```c 695FFRT_C_API int ffrt_this_task_update_qos(ffrt_qos_t qos); 696``` 697 698#### Parameters 699 700- `qos`: QoS. 701 702#### Return Values 703 704- The value **0** indicates success, and the value **1** indicates failure. 705 706#### Description 707 708Updates the task QoS dynamically during task execution. Note that this API is used in the function closure of a task to update the QoS of the task that is being executed. If this API is invoked, the task is suspended and then resumed. 709 710#### Example 711 712```c 713// Dynamically update the QoS during the execution of a qos_background task. 714ffrt::submit([]() { 715 // ... 716 int ret = ffrt_this_task_update_qos(ffrt_qos_user_initiated); 717 // ... 718}, ffrt::task_attr().qos(ffrt::qos_background)); 719``` 720 721### ffrt_this_task_get_qos 722 723#### Declaration 724 725```c 726FFRT_C_API ffrt_qos_t ffrt_this_task_get_qos(void); 727``` 728 729#### Return Values 730 731- QoS. 732 733#### Description 734 735Obtains the QoS of the task that is being executed. 736 737#### Example 738 739```c 740// Dynamically obtain the QoS during the execution of a task. 741ffrt::submit([]() { 742 // ... 743 // The obtained QoS is ffrt_qos_background. 744 ffrt_qos_t qos = ffrt_this_task_get_qos(); 745 // ... 746}, ffrt::task_attr().qos(ffrt::qos_background)); 747``` 748 749### ffrt_this_task_get_id 750 751#### Declaration 752 753```c 754FFRT_C_API uint64_t ffrt_this_task_get_id(void); 755``` 756 757#### Return Values 758 759- Task ID. 760 761#### Description 762 763Obtains the ID of the task that is being executed. 764 765#### Example 766 767```c 768// Dynamically obtain the task ID during task execution. 769ffrt::submit([]() { 770 // ... 771 // Obtain the unique task ID. 772 uint64_t task_id = ffrt_this_task_get_id(); 773 // ... 774}, ffrt::task_attr().qos(ffrt::qos_background)); 775``` 776 777## Task Queue 778 779### ffrt_queue_attr_t 780 781#### Declaration 782 783```c 784typedef struct { 785 uint32_t storage[(ffrt_queue_attr_storage_size + sizeof(uint32_t) - 1) / sizeof(uint32_t)]; 786} ffrt_queue_attr_t; 787``` 788 789#### Description 790 791Configures queue attributes, such as the QoS, timeout, callback function, and maximum concurrency. 792 793#### Methods 794 795##### ffrt_queue_attr_init 796 797```c 798int ffrt_queue_attr_init(ffrt_queue_attr_t* attr) 799``` 800 801Parameters 802 803- `attr`: pointer to the queue attribute. 804 805Return Values 806 807- The value **0** indicates success while other values indicate failure. 808 809Description 810 811- Initializes a queue attribute object. 812 813##### ffrt_queue_attr_destroy 814 815```c 816void ffrt_queue_attr_destroy(ffrt_queue_attr_t* attr) 817``` 818 819Parameters 820 821- `attr`: pointer to the queue attribute. 822 823Description 824 825- Destroys a queue attribute object. 826 827##### ffrt_queue_attr_set_qos 828 829```c 830void ffrt_queue_attr_set_qos(ffrt_queue_attr_t* attr, ffrt_qos_t qos) 831``` 832 833Parameters 834 835- `attr`: pointer to the queue attribute. 836- `qos`: QoS. 837 838Description 839 840- Sets the queue QoS. 841 842##### ffrt_queue_attr_get_qos 843 844```c 845ffrt_qos_t ffrt_queue_attr_get_qos(const ffrt_queue_attr_t* attr) 846``` 847 848Parameters 849 850- `attr`: pointer to the queue attribute. 851 852Return Values 853 854- Current QoS. 855 856Description 857 858- Obtains the QoS set in the current attribute. 859 860##### ffrt_queue_attr_set_timeout 861 862```c 863void ffrt_queue_attr_set_timeout(ffrt_queue_attr_t* attr, uint64_t timeout_us) 864``` 865 866Parameters 867 868- `attr`: pointer to the queue attribute. 869- `timeout_us`: timeout (μs). 870 871Description 872 873- Sets the queue timeout (unit: μs). 874 875##### ffrt_queue_attr_get_timeout 876 877```c 878uint64_t ffrt_queue_attr_get_timeout(const ffrt_queue_attr_t* attr) 879``` 880 881Parameters 882 883- `attr`: pointer to the queue attribute. 884 885Return Values 886 887- Current timeout threshold (μs). 888 889Description 890 891- Obtains the timeout set in the current attribute. 892 893##### ffrt_queue_attr_set_callback 894 895```c 896void ffrt_queue_attr_set_callback(ffrt_queue_attr_t* attr, ffrt_function_header_t* f) 897``` 898 899Parameters 900 901- `attr`: pointer to the queue attribute. 902- `f`: pointer to the task executor, which describes how to execute and destroy the CPU task. 903 904Description 905 906- Sets the callback function to be executed after a queue task times out. 907 908##### ffrt_queue_attr_get_callback 909 910```c 911ffrt_function_header_t* ffrt_queue_attr_get_callback(const ffrt_queue_attr_t* attr) 912``` 913 914Parameters 915 916- `attr`: pointer to the queue attribute. 917 918Return Values 919 920- Pointer to the task executor, which describes how to execute and destroy the CPU task. 921 922Description 923 924- Obtains the timeout callback function set in the current attribute. 925 926##### ffrt_queue_attr_set_max_concurrency 927 928```c 929void ffrt_queue_attr_set_max_concurrency(ffrt_queue_attr_t* attr, const int max_concurrency) 930``` 931 932Parameters 933 934- `attr`: pointer to the queue attribute. 935- `max_concurrency`: maximum concurrency. 936 937Description 938 939- Sets the maximum queue concurrency. (Only concurrent queues are supported.) 940 941##### ffrt_queue_attr_get_max_concurrency 942 943```c 944int ffrt_queue_attr_get_max_concurrency(const ffrt_queue_attr_t* attr) 945``` 946 947Parameters 948 949- `attr`: pointer to the queue attribute. 950 951Return Values 952 953- Maximum concurrency. 954 955Description 956 957- Obtains the maximum concurrency set in the current attribute. (Only concurrent queues are supported). 958 959#### Example 960 961```cpp 962#include <functional> 963#include "ffrt/queue.h" 964#include "ffrt/cpp/task.h" 965 966int main() 967{ 968 ffrt_queue_attr_t queue_attr; 969 // (Mandatory) Initialize the queue attribute. 970 ffrt_queue_attr_init(&queue_attr); 971 972 ffrt_queue_attr_set_qos(&queue_attr, static_cast<int>(ffrt_qos_utility)); 973 974 ffrt_queue_attr_set_timeout(&queue_attr, 10000); 975 976 977 int x = 0; 978 std::function<void()>&& basicFunc = [&x]() { x += 1; }; 979 ffrt_function_header_t* func = ffrt_queue_attr_get_callback(&queue_attr); 980 981 ffrt_queue_attr_set_callback(&queue_attr, ffrt::create_function_wrapper(basicFunc, ffrt_function_kind_queue)); 982 // Destroy the queue attribute. This is mandatory. 983 ffrt_queue_attr_destroy(&queue_attr); 984 return 0; 985} 986``` 987 988### ffrt_queue_t 989 990#### Declaration 991 992```c 993typedef void* ffrt_queue_t; 994``` 995 996#### Description 997 998Pointer to queues. It provides a series of C APIs for submitting, canceling, and waiting queue tasks and querying the number of queuing tasks. 999 1000#### Methods 1001 1002##### ffrt_queue_create 1003 1004```c 1005ffrt_queue_t ffrt_queue_create(ffrt_queue_type_t type, const char* name, const ffrt_queue_attr_t* attr) 1006``` 1007 1008Parameters 1009 1010- `type`: queue type, for example, `ffrt_queue_serial` or `ffrt_queue_concurrent`. 1011- `name`: queue name. 1012- `attr`: pointer to the queue attribute. 1013 1014Return Values 1015 1016- `ffrt_queue_t`: If the function is called successfully, a non-null queue handle is returned. Otherwise, a null pointer is returned. 1017 1018Description 1019 1020- Creates a queue with a specified type and name. 1021 1022##### ffrt_queue_destroy 1023 1024```c 1025void ffrt_queue_destroy(ffrt_queue_t queue) 1026``` 1027 1028Parameters 1029 1030- `queue`: queue handle. 1031 1032Description 1033 1034- Destroys a queue. 1035 1036##### ffrt_queue_submit 1037 1038```c 1039void ffrt_queue_submit(ffrt_queue_t queue, ffrt_function_header_t* f, const ffrt_task_attr_t* attr) 1040``` 1041 1042Parameters 1043 1044- `queue`: queue handle. 1045- `f`: pointer to the task executor, which describes how to execute and destroy the CPU task. 1046- `attr`: task attribute. 1047 1048Description 1049 1050- Submits a task to a queue. 1051 1052##### ffrt_queue_submit_h 1053 1054```c 1055ffrt_task_handle_t ffrt_queue_submit_h(ffrt_queue_t queue, ffrt_function_header_t* f, const ffrt_task_attr_t* attr) 1056``` 1057 1058Parameters 1059 1060- `queue`: queue handle. 1061- `f`: pointer to the task executor, which describes how to execute and destroy the CPU task. 1062- `attr`: task attribute. 1063 1064Return Values 1065 1066- `ffrt_task_handle_t`: If the function is called successfully, a non-null task handle is returned. Otherwise, a null pointer is returned. 1067 1068Description 1069 1070- Submits a task to a queue and returns a task handle. 1071 1072##### ffrt_queue_wait 1073 1074```c 1075void ffrt_queue_wait(ffrt_task_handle_t handle) 1076``` 1077 1078Parameters 1079 1080- `ffrt_task_handle_t`: task handle. 1081 1082Description 1083 1084- Waits for a queue task to complete. 1085 1086##### ffrt_queue_cancel 1087 1088```c 1089int ffrt_queue_cancel(ffrt_task_handle_t handle) 1090``` 1091 1092Parameters 1093 1094- `ffrt_task_handle_t`: task handle. 1095 1096Return Values 1097 1098- The value **0** indicates success while other values indicate failure. 1099 1100Description 1101 1102- Cancels a queue task. 1103 1104##### ffrt_get_main_queue 1105 1106```c 1107ffrt_queue_t ffrt_get_main_queue(); 1108``` 1109 1110Return Values 1111 1112- Main thread queue. 1113 1114Description 1115 1116- Obtains the main thread queue for the FFRT thread to communicate with the main thread. 1117 1118##### ffrt_get_current_queue 1119 1120```c 1121ffrt_queue_t ffrt_get_current_queue(); 1122``` 1123 1124Return Values 1125 1126- ArkTS Worker thread queue. 1127 1128Description 1129 1130- This API has been deprecated since API version 18. You are not advised to use it. 1131- Obtains the ArkTS Worker thread queue for the FFRT thread to communicate with the ArkTS Worker thread. 1132 1133#### Example 1134 1135```cpp 1136#include "ffrt/queue.h" 1137#include "ffrt/cpp/task.h" 1138 1139int main() 1140{ 1141 ffrt_queue_attr_t queue_attr; 1142 // 1. Initialize the queue attribute. This is mandatory. 1143 (void)ffrt_queue_attr_init(&queue_attr); 1144 1145 // 2. Create a serial queue and return queue_handle. 1146 ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_serial, "test_queue", &queue_attr); 1147 1148 int result = 0; 1149 std::function<void()>&& basicFunc = [&result]() { result += 1; }; 1150 1151 // 3. Submit a serial task. 1152 ffrt_queue_submit(queue_handle, ffrt::create_function_wrapper(basicFunc, ffrt_function_kind_queue), nullptr); 1153 1154 // 4. Submit the serial task and return the task handle. 1155 ffrt_task_handle_t t1 = ffrt_queue_submit_h(queue_handle, ffrt::create_function_wrapper(basicFunc, ffrt_function_kind_queue), nullptr); 1156 // 5. Wait until the specified task is complete. 1157 ffrt_queue_wait(t1); 1158 1159 ffrt_task_handle_t t2 = ffrt_queue_submit_h(queue_handle, ffrt::create_function_wrapper(basicFunc, ffrt_function_kind_queue), nullptr); 1160 // 6. Cancel the task with handle t2. 1161 ffrt_queue_cancel(t2); 1162 1163 // 7. Destroy the handles t1 and t2 submitted to the serial queue task. This is mandatory. 1164 ffrt_task_handle_destroy(t1); 1165 ffrt_task_handle_destroy(t2); 1166 // 8. Destroy the queue attribute. This is mandatory. 1167 ffrt_queue_attr_destroy(&queue_attr); 1168 // 9. Destroy the queue handle. This is mandatory. 1169 ffrt_queue_destroy(queue_handle); 1170 return 0; 1171} 1172``` 1173 1174## Synchronization Primitive 1175 1176### ffrt_mutexattr_t 1177 1178#### Declaration 1179 1180```c 1181typedef enum { 1182 ffrt_error = -1, 1183 ffrt_success = 0, 1184 ffrt_error_nomem = ENOMEM, 1185 ffrt_error_timedout = ETIMEDOUT, 1186 ffrt_error_busy = EBUSY, 1187 ffrt_error_inval = EINVAL 1188} ffrt_error_t; 1189 1190typedef enum { 1191 ffrt_mutex_normal = 0, 1192 ffrt_mutex_recursive = 2, 1193 ffrt_mutex_default = ffrt_mutex_normal 1194} ffrt_mutex_type; 1195 1196struct ffrt_mutexattr_t; 1197 1198int ffrt_mutexattr_init(ffrt_mutexattr_t* attr); 1199int ffrt_mutexattr_settype(ffrt_mutexattr_t* attr, int type); 1200int ffrt_mutexattr_gettype(ffrt_mutexattr_t* attr, int* type); 1201int ffrt_mutexattr_destroy(ffrt_mutexattr_t* attr); 1202``` 1203 1204#### Description 1205 1206- Provides performance implementation similar to pthread mutex. 1207 1208#### Methods 1209 1210##### ffrt_mutexattr_init 1211 1212```c 1213FFRT_C_API int ffrt_mutexattr_init(ffrt_mutexattr_t* attr); 1214``` 1215 1216Parameters 1217 1218- `attr`: FFRT mutex attribute. 1219 1220Return Values 1221 1222- `ffrt_success` is returned if `attr` is not empty. Otherwise, `ffrt_error_inval` is returned. 1223 1224Description 1225 1226- Initializes `mutexattr`. 1227 1228##### ffrt_mutexattr_destroy 1229 1230```c 1231FFRT_C_API int ffrt_mutexattr_destroy(ffrt_mutexattr_t* attr); 1232``` 1233 1234Parameters 1235 1236- `attr`: FFRT mutex attribute. 1237 1238Return Values 1239 1240- `ffrt_success` is returned if `attr` is not empty. Otherwise, `ffrt_error_inval` is returned. 1241 1242Description 1243 1244- Destroys `mutexattr`. 1245 1246##### ffrt_mutexattr_settype 1247 1248```c 1249FFRT_C_API int ffrt_mutexattr_settype(ffrt_mutexattr_t* attr, int type); 1250``` 1251 1252Parameters 1253 1254- `attr`: FFRT mutex attribute. 1255- `type`: FFRT mutex type. Currently, only `ffrt_mutex_normal` and `ffrt_mutex_recursive` are supported. 1256 1257Return Values 1258 1259- `ffrt_success` is returned if `attr` is not empty and `type` is valid. Otherwise, `ffrt_error_inval` is returned. 1260 1261Description 1262 1263- Sets the FFRT mutex attribute. 1264 1265##### ffrt_mutexattr_gettype 1266 1267```c 1268FFRT_C_API int ffrt_mutexattr_gettype(ffrt_mutexattr_t* attr, int* type); 1269``` 1270 1271Parameters 1272 1273- `attr`: FFRT mutex attribute. 1274- `type`: pointer to the FFRT mutex type. 1275 1276Return Values 1277 1278- `ffrt_success` is returned if neither `attr` nor `type` is empty. Otherwise, `ffrt_error_inval` is returned. 1279 1280Description 1281 1282- Obtains the FFRT mutex attribute. 1283 1284#### Example 1285 1286```c 1287ffrt_mutexattr_t attr; 1288// Initialize the mutex attribute. 1289ffrt_mutexattr_init(&attr); 1290// Set a mutex. 1291ffrt_mutexattr_settype(&attr, ffrt_mutex_normal); 1292// Set a recursive lock. 1293ffrt_mutexattr_settype(&attr, ffrt_mutex_recursive); 1294// Obtain the mutex type. 1295int type = ffrt_mutex_default; 1296ffrt_mutexattr_gettype(&attr, &type); 1297// Destroy the mutex attribute. 1298ffrt_mutexattr_destroy(&attr); 1299``` 1300 1301### ffrt_mutex_t 1302 1303- Implements `pthread_mutex_t`, but does not supports initialization of `PTHREAD_MUTEX_INITIALIZER`. 1304 1305#### Declaration 1306 1307```c 1308struct ffrt_mutex_t; 1309struct ffrt_mutexattr_t; 1310 1311int ffrt_mutex_init(ffrt_mutex_t* mutex, const ffrt_mutexattr_t* attr); 1312int ffrt_mutex_lock(ffrt_mutex_t* mutex); 1313int ffrt_mutex_unlock(ffrt_mutex_t* mutex); 1314int ffrt_mutex_trylock(ffrt_mutex_t* mutex); 1315int ffrt_mutex_destroy(ffrt_mutex_t* mutex); 1316``` 1317 1318#### Description 1319 1320- This API can be called inside or outside an FFRT task. 1321- The traditional function `pthread_mutex_t` may cause unexpected kernel mode trap when it fails to lock a mutex. **ffrt_mutex_t** solves this problem and therefore provides better performance if used properly. 1322- `ffrt_mutexattr_t` in the C API needs to be created and destroyed by calling `ffrt_mutexattr_init` and `ffrt_mutexattr_destroy`. Otherwise, undefined behavior may occur. 1323- `ffrt_mutex_t` in the C API needs to be explicitly created and destroyed by calling `ffrt_mutex_init` and `ffrt_mutex_destroy`. Otherwise, undefined behavior may occur. 1324- You need to set the `ffrt_mutex_t` object in the C code to null or destroy the object. For the same `ffrt_mutex_t` object, `ffrt_mutex_destroy` can be called only once. Otherwise, undefined behavior may occur. 1325- The same `ffrt_mutexattr_t` in the C API can call `ffrt_mutexattr_init` and `ffrt_mutexattr_destroy` only once. Repeated calling may cause undefined behavior. 1326- You need to explicitly call `ffrt_mutex_destroy` after `ffrt_mutex_init` and before `ffrt_mutexattr_destroy`. 1327- If `ffrt_mutex_t` is accessed after `ffrt_mutex_destroy`, undefined behavior may occur. 1328 1329#### Methods 1330 1331##### ffrt_mutex_init 1332 1333```c 1334FFRT_C_API int ffrt_mutex_init(ffrt_mutex_t* mutex, const ffrt_mutexattr_t* attr); 1335``` 1336 1337Parameters 1338 1339- `mutex`: pointer to the operated mutex. 1340- `attr`: FFRT mutex attribute. Its valid value can be a null pointer, `ffrt_mutex_normal`, or `ffrt_mutex_recursive`. 1341 1342Return Values 1343 1344- `ffrt_success` is returned if `mutex` is not empty and `attr` is within the valid value range. Otherwise, `ffrt_error_inval` is returned. 1345 1346Description 1347 1348- Initializes the FFRT mutex. 1349 1350##### ffrt_mutex_destroy 1351 1352```c 1353FFRT_C_API int ffrt_mutex_destroy(ffrt_mutex_t* mutex); 1354``` 1355 1356Parameters 1357 1358- `mutex`: pointer to the operated mutex. 1359 1360Return Values 1361 1362- `ffrt_success` is returned if `mutex` is not empty. Otherwise, `ffrt_error_inval` is returned. 1363 1364Description 1365 1366- Destroys a specified mutex or recursive lock. 1367 1368##### ffrt_mutex_lock 1369 1370```c 1371FFRT_C_API int ffrt_mutex_lock(ffrt_mutex_t* mutex); 1372``` 1373 1374Parameters 1375 1376- `mutex`: pointer to the operated mutex. 1377 1378Return Values 1379 1380- `ffrt_success` is returned if `mutex` is not empty. Otherwise, `ffrt_error_inval` is returned. 1381 1382Description 1383 1384- Locks a specified mutex or recursive lock. This method blocks the current task until the mutex is successfully obtained. 1385 1386##### ffrt_mutex_unlock 1387 1388```c 1389FFRT_C_API int ffrt_mutex_unlock(ffrt_mutex_t* mutex); 1390``` 1391 1392Parameters 1393 1394- `mutex`: pointer to the operated mutex. 1395 1396Return Values 1397 1398- `ffrt_success` is returned if `mutex` is not empty. Otherwise, `ffrt_error_inval` is returned. 1399 1400Description 1401 1402- Unlocks a specified mutex or recursive lock. 1403 1404##### ffrt_mutex_trylock 1405 1406```c 1407FFRT_C_API int ffrt_mutex_trylock(ffrt_mutex_t* mutex); 1408``` 1409 1410Parameters 1411 1412- `mutex`: pointer to the operated mutex. 1413 1414Return Values 1415 1416- **ffrt_error_inval** is returned if `mutex` is empty. `ffrt_success` is returned if `mutex` is not empty and the mutex is successfully held. `ffrt_error_busy` is returned if `mutex` is not empty and the mutex fails to be held. 1417 1418Description 1419 1420- Locks a specified mutex or recursive lock. 1421 1422#### Example 1423 1424```cpp 1425#include "ffrt/mutex.h" 1426#include "ffrt/cpp/task.h" 1427 1428int main() 1429{ 1430 ffrt_mutexattr_t attr; 1431 ffrt_mutex_t lock; 1432 int sum = 0; 1433 int type = ffrt_mutex_default; 1434 ffrt_mutexattr_init(&attr); 1435 ffrt_mutexattr_settype(&attr, ffrt_mutex_recursive); 1436 ffrt_mutexattr_gettype(&attr, &type); 1437 ffrt_mutex_init(&lock, &attr); 1438 ffrt::submit([&]() { 1439 ffrt_mutex_lock(&lock); 1440 ffrt_mutex_trylock(&lock); 1441 sum++; 1442 ffrt_mutex_lock(&lock); 1443 ffrt_mutex_trylock(&lock); 1444 sum++; 1445 ffrt_mutex_unlock(&lock); 1446 ffrt_mutex_unlock(&lock); 1447 ffrt_mutex_unlock(&lock); 1448 ffrt_mutex_unlock(&lock); 1449 }, {}, {}); 1450 1451 ffrt::wait(); 1452 1453 ffrt_mutexattr_destroy(&attr); 1454 ffrt_mutex_destroy(&lock); 1455 return 0; 1456} 1457``` 1458 1459### ffrt_rwlock_t 1460 1461- Implements `pthread_rwlock_t`. 1462 1463#### Declaration 1464 1465```c 1466struct ffrt_rwlock_t; 1467struct ffrt_rwlockattr_t; 1468 1469int ffrt_rwlock_init(ffrt_rwlock_t* rwlock, const ffrt_rwlockattr_t* attr); 1470int ffrt_rwlock_wrlock(ffrt_rwlock_t* rwlock); 1471int ffrt_rwlock_rdlock(ffrt_rwlock_t* rwlock); 1472int ffrt_rwlock_trywrlock(ffrt_rwlock_t* rwlock); 1473int ffrt_rwlock_tryrdlock(ffrt_rwlock_t* rwlock); 1474int ffrt_rwlock_unlock(ffrt_rwlock_t* rwlock); 1475int ffrt_rwlock_destroy(ffrt_rwlock_t* rwlock); 1476``` 1477 1478#### Description 1479 1480- This API can be called inside or outside an FFRT task. 1481- This API can avoid the issue that `pthread_rwlock_t` sleeps without releasing threads. The performance is better when the API is properly used. 1482- `ffrt_rwlock_t` in the C API needs to be explicitly created and destroyed by calling `ffrt_rwlock_init` and `ffrt_rwlock_destroy`. Otherwise, undefined behavior may occur. 1483- When `ffrt_rwlockattr_t` is called, the input parameter of `ffrt_rwlockattr_t` must be a null pointer. 1484- You need to set the `ffrt_rwlock_t` object in the C code to null or destroy the object. For the same `ffrt_rwlock_t` object, `ffrt_rwlock_destroy` can be called only once. Otherwise, undefined behavior may occur. 1485- If `ffrt_rwlock_t` is accessed after `ffrt_rwlock_destroy` is called, undefined behavior may occur. 1486 1487#### Methods 1488 1489##### ffrt_rwlock_init 1490 1491```c 1492FFRT_C_API int ffrt_rwlock_init(ffrt_rwlock_t* rwlock, const ffrt_rwlockattr_t* attr); 1493``` 1494 1495Parameters 1496 1497- `rwlock`: pointer to the operated RW lock. 1498- `attr`: pointer to the RW lock attribute. 1499 1500Return Values 1501 1502- `ffrt_success` is returned if neither `rwlock` nor `attr` is empty. Otherwise, `ffrt_error_inval` is returned or the current task is blocked. 1503 1504Description 1505 1506- Initializes the RW lock. 1507 1508##### ffrt_rwlock_wrlock 1509 1510```c 1511FFRT_C_API int ffrt_rwlock_wrlock(ffrt_rwlock_t* rwlock); 1512``` 1513 1514Parameters 1515 1516- `rwlock`: pointer to the operated RW lock. 1517 1518Return Values 1519 1520- `ffrt_success` is returned if `rwlock` is not empty. Otherwise, `ffrt_error_inval` is returned. 1521 1522Description 1523 1524- Adds a write lock to the specified RW lock. 1525 1526##### ffrt_rwlock_rdlock 1527 1528```c 1529FFRT_C_API int ffrt_rwlock_rdlock(ffrt_rwlock_t* rwlock); 1530``` 1531 1532Parameters 1533 1534- `rwlock`: pointer to the operated RW lock. 1535 1536Return Values 1537 1538- `ffrt_success` is returned if `rwlock` is not empty. Otherwise, **ffrt_error_inval** is returned. 1539 1540Description 1541 1542- Adds a read lock to the specified RW lock. 1543 1544##### ffrt_rwlock_trywrlock 1545 1546```c 1547FFRT_C_API int ffrt_rwlock_trywrlock(ffrt_rwlock_t* rwlock); 1548``` 1549 1550Parameters 1551 1552- `rwlock`: pointer to the operated RW lock. 1553 1554Return Values 1555 1556- `ffrt_success` is returned if `rwlock` is not empty and no other thread holds the RW lock. Otherwise, `ffrt_error_inval` is returned. 1557 1558Description 1559 1560- Adds a write lock to the specified RW lock. 1561 1562##### ffrt_rwlock_tryrdlock 1563 1564```c 1565FFRT_C_API int ffrt_rwlock_tryrdlock(ffrt_rwlock_t* rwlock); 1566``` 1567 1568Parameters 1569 1570- `rwlock`: pointer to the operated RW lock. 1571 1572Return Values 1573 1574- `ffrt_success` is returned if `rwlock` is not empty and no other thread holds the write lock. Otherwise, `ffrt_error_inval` is returned. 1575 1576Description 1577 1578- Adds a read lock to the specified RW lock. 1579 1580##### ffrt_rwlock_unlock 1581 1582```c 1583FFRT_C_API int ffrt_rwlock_unlock(ffrt_rwlock_t* rwlock); 1584``` 1585 1586Parameters 1587 1588- `rwlock`: pointer to the operated RW lock. 1589 1590Return Values 1591 1592- `ffrt_success` is returned if `rwlock` is not empty. Otherwise, `ffrt_error_inval` is returned. 1593 1594Description 1595 1596- Unlocks the specified RW lock. 1597 1598##### ffrt_rwlock_destroy 1599 1600```c 1601FFRT_C_API int ffrt_rwlock_destroy(ffrt_rwlock_t* rwlock); 1602``` 1603 1604Parameters 1605 1606- `rwlock`: pointer to the operated RW lock. 1607 1608Return Values 1609 1610- `ffrt_success` is returned if `rwlock` is not empty. Otherwise, `ffrt_error_inval` is returned. 1611 1612Description 1613 1614- Destroys a specified RW lock. 1615 1616#### Example 1617 1618```cpp 1619#include "ffrt/shared_mutex.h" 1620#include "ffrt/sleep.h" 1621#include "ffrt/cpp/task.h" 1622 1623int main() 1624{ 1625 ffrt_rwlock_t rwlock; 1626 int x = 0; 1627 ffrt_rwlock_init(&rwlock, nullptr); 1628 ffrt::submit([&]() { 1629 ffrt_rwlock_wrlock(&rwlock); 1630 ffrt_usleep(10); 1631 x++; 1632 ffrt_rwlock_unlock(&rwlock); 1633 },{},{}); 1634 1635 ffrt::submit([&]() { 1636 ffrt_usleep(2); 1637 ffrt_rwlock_rdlock(&rwlock); 1638 ffrt_rwlock_unlock(&rwlock); 1639 },{},{}); 1640 1641 ffrt::submit([&]() { 1642 ffrt_usleep(2); 1643 if(ffrt_rwlock_trywrlock(&rwlock)){ 1644 x++; 1645 ffrt_rwlock_unlock(&rwlock); 1646 } 1647 },{},{}); 1648 1649 ffrt::submit([&]() { 1650 ffrt_usleep(2); 1651 if(ffrt_rwlock_tryrdlock(&rwlock)){ 1652 ffrt_rwlock_unlock(&rwlock); 1653 } 1654 },{},{}); 1655 1656 ffrt::wait(); 1657 1658 ffrt_rwlock_destroy(&rwlock); 1659 return 0; 1660} 1661``` 1662 1663### ffrt_cond_t 1664 1665- Implements the pthread semaphore function, but does not supports initialization of `PTHREAD_COND_INITIALIZER`. 1666 1667#### Declaration 1668 1669```c 1670typedef enum { 1671 ffrt_error = -1, 1672 ffrt_success = 0, 1673 ffrt_error_nomem = ENOMEM, 1674 ffrt_error_timedout = ETIMEDOUT, 1675 ffrt_error_busy = EBUSY, 1676 ffrt_error_inval = EINVAL 1677} ffrt_error_t; 1678 1679typedef struct { 1680 uint32_t storage[(ffrt_cond_storage_size + sizeof(uint32_t) - 1) / sizeof(uint32_t)]; 1681} ffrt_cond_t; 1682 1683int ffrt_cond_init(ffrt_cond_t* cond, const ffrt_condattr_t* attr); 1684int ffrt_cond_signal(ffrt_cond_t* cond); 1685int ffrt_cond_broadcast(ffrt_cond_t* cond); 1686int ffrt_cond_wait(ffrt_cond_t*cond, ffrt_mutex_t* mutex); 1687int ffrt_cond_timedwait(ffrt_cond_t* cond, ffrt_mutex_t* mutex, const struct timespec* time_point); 1688int ffrt_cond_destroy(ffrt_cond_t* cond); 1689``` 1690 1691#### Description 1692 1693- This API can be called inside or outside an FFRT task. 1694- The traditional function `pthread_cond_t` may cause unexpected kernel mode trap when the conditions are not met. **ffrt_cond_t** solves this problem and therefore provides better performance if being used properly. 1695- Note that `ffrt_cond_t` in the C API needs to be explicitly created and destroyed by calling `ffrt_cond_init` and `ffrt_cond_destroy`. However, in the C++ API, the dependency construction and destruction are automatically completed. 1696- You need to set the `ffrt_cond_t` object in the C code to null or destroy the object. For the same `ffrt_cond_t` object, `ffrt_cond_destroy` can be called only once. Otherwise, undefined behavior may occur. 1697- If `ffrt_cond_t` is accessed after `ffrt_cond_destroy` is called, undefined behavior may occur. 1698 1699#### Methods 1700 1701##### ffrt_cond_init 1702 1703```c 1704FFRT_C_API int ffrt_cond_init(ffrt_cond_t* cond, const ffrt_condattr_t* attr); 1705``` 1706 1707Parameters 1708 1709- `cond`: pointer to the target semaphore. 1710- `attr`: pointer to the attribute. A null pointer indicates that the default attribute is used. 1711 1712Return Values 1713 1714- `ffrt_success` is returned if `cond` is not empty. Otherwise, `ffrt_error_inval` is returned. 1715 1716Description 1717 1718- Initializes the FFRT condition variable. 1719 1720##### ffrt_cond_destroy 1721 1722```c 1723FFRT_C_API int ffrt_cond_destroy(ffrt_cond_t* cond); 1724``` 1725 1726Parameters 1727 1728- `cond`: pointer to the target semaphore. 1729 1730Return Values 1731 1732- `ffrt_success` is returned if `cond` is not empty. Otherwise, `ffrt_error_inval` is returned. 1733 1734Description 1735 1736- Destroys an FFRT condition variable. 1737 1738##### ffrt_cond_signal 1739 1740```c 1741FFRT_C_API int ffrt_cond_signal(ffrt_cond_t* cond); 1742``` 1743 1744Parameters 1745 1746- `cond`: pointer to the target semaphore. 1747 1748Return Values 1749 1750- `ffrt_success` is returned if `cond` is not empty. Otherwise, `ffrt_error_inval` is returned. 1751 1752Description 1753 1754- Unblocks at least one of the threads that are blocked on a condition variable. 1755 1756##### ffrt_cond_broadcast 1757 1758```c 1759FFRT_C_API int ffrt_cond_broadcast(ffrt_cond_t* cond); 1760``` 1761 1762Parameters 1763 1764- `cond`: pointer to the target semaphore. 1765 1766Return Values 1767 1768- `ffrt_success` is returned if `cond` is not empty. Otherwise, `ffrt_error_inval` is returned. 1769 1770Description 1771 1772- Unblocks all threads currently blocked on a condition variable. 1773 1774##### ffrt_cond_wait 1775 1776```c 1777FFRT_C_API int ffrt_cond_wait(ffrt_cond_t* cond, ffrt_mutex_t* mutex); 1778``` 1779 1780Parameters 1781 1782- `cond`: pointer to the target semaphore. 1783- `mutex`: pointer to the target mutex. 1784 1785Return Values 1786 1787- `ffrt_success` is returned if neither `cond` nor `mutex` is empty. Otherwise, `ffrt_error_inval` is returned. 1788 1789Description 1790 1791- Blocks a task on a condition variable. When using this method, a task releases the input mutex and enters the waiting state. The task obtains the mutex again and continues to execute until another task notifies the condition variable. 1792- This method is usually used together with `ffrt_mutex_lock` or `ffrt_mutex_trylock` to ensure that the mutex is held before entering the wait state. 1793 1794##### ffrt_cond_timedwait 1795 1796```c 1797FFRT_C_API int ffrt_cond_timedwait(ffrt_cond_t* cond, ffrt_mutex_t* mutex, const struct timespec* time_point); 1798``` 1799 1800Parameters 1801 1802- `cond`: pointer to the target semaphore. 1803- `mutex`: pointer to the target mutex. 1804- `time_point`: pointer to the maximum duration during which the thread is blocked. 1805 1806Return Values 1807 1808- `ffrt_success` is returned if `cond`, `mutex`, and `time_point` are not empty. Otherwise, `ffrt_error_inval` is returned. 1809 1810Description 1811 1812- Blocks a task on a condition variable until the specified timeout is reached. 1813- Unlike `ffrt_cond_wait`, the `ffrt_cond_timedwait` method allows a task to wait for a period of time on a condition variable. If no notification is received within the specified period of time, the task is woken up and the function returns. 1814 1815#### Example 1816 1817```cpp 1818#include <iostream> 1819#include "ffrt/condition_variable.h" 1820#include "ffrt/mutex.h" 1821#include "ffrt/sleep.h" 1822#include "ffrt/cpp/task.h" 1823 1824struct timespec timeoutms_to_tm(int timeout_ms) { 1825 struct timespec ts; 1826 clock_gettime(CLOCK_REALTIME, &ts); 1827 ts.tv_sec += timeout_ms / 1000; 1828 ts.tv_nsec += (timeout_ms % 1000) * 1000000; 1829 if (ts.tv_nsec >= 1000000000) { 1830 ts.tv_sec += 1; 1831 ts.tv_nsec -= 1000000000; 1832 } 1833 return ts; 1834} 1835 1836int main() 1837{ 1838 int a = 0; 1839 ffrt_cond_t cond; 1840 ffrt_mutex_t lock_; 1841 ffrt_cond_init(&cond, nullptr); 1842 ffrt_mutex_init(&lock_, nullptr); 1843 1844 for (int i = 0; i < 3; i++) { 1845 ffrt::submit([&]() { 1846 int timeout = 2000; 1847 struct timespec tm = timeoutms_to_tm(timeout); 1848 ffrt_mutex_lock(&lock_); 1849 auto start = std::chrono::high_resolution_clock::now(); 1850 ffrt_cond_timedwait(&cond, &lock_, &tm); 1851 auto end = std::chrono::high_resolution_clock::now(); 1852 a = 123; 1853 ffrt_mutex_unlock(&lock_); 1854 std::chrono::duration<double, std::milli> elapsed = end - start; 1855 double t = elapsed.count(); 1856 std::cout << "ffrt_cond_timedwait " << t << " ms" << std::endl; 1857 }, {}, {}); 1858 } 1859 1860 ffrt::submit([&]() { 1861 ffrt_usleep(1000 * 1000); 1862 ffrt_mutex_lock(&lock_); 1863 a = 5; 1864 ffrt_cond_broadcast(&cond); 1865 ffrt_mutex_unlock(&lock_); 1866 }, {}, {}); 1867 ffrt::wait(); 1868 ffrt_cond_destroy(&cond); 1869 ffrt_mutex_destroy(&lock_); 1870 return 0; 1871} 1872``` 1873 1874## Blocking Primitive 1875 1876### ffrt_usleep 1877 1878#### Declaration 1879 1880```c 1881FFRT_C_API int ffrt_usleep(uint64_t usec); 1882``` 1883 1884#### Parameters 1885 1886- `usec`: sleep duration, in μs. 1887 1888#### Description 1889 1890- Provides performance implementation similar to C11 sleep and Linux usleep. 1891- This API can be called only inside an FFRT task. If it is called outside an FFRT task, undefined behavior may occur. 1892- The sleep precision of this API is μs. 1893- The traditional function `sleep` may cause unexpected kernel mode trap. **ffrt_usleep** solves this problem and therefore provides better performance if used properly. 1894 1895#### Example 1896 1897```cpp 1898#include "ffrt/sleep.h" 1899#include "ffrt/cpp/task.h" 1900 1901int main() 1902{ 1903 ffrt::submit([=]() { ffrt_usleep(10); }, {}, {}); 1904 ffrt::wait(); 1905 return 0; 1906} 1907``` 1908 1909## Cooperative Primitive 1910 1911### ffrt_yield 1912 1913#### Declaration 1914 1915```c 1916FFRT_C_API void ffrt_yield(); 1917``` 1918 1919#### Description 1920 1921- Yields CPU execution resources for other executable tasks. If there is no other executable task, `yield` is invalid. 1922- This API can be called only inside an FFRT task. If it is called outside an FFRT task, undefined behavior may occur. 1923- The exact behavior of this API depends on the implementation, especially the mechanism and system state of the FFRT scheduler in use. 1924 1925#### Example 1926 1927```cpp 1928#include <iostream> 1929#include "ffrt/sleep.h" 1930#include "ffrt/cpp/task.h" 1931 1932int main() 1933{ 1934 int count = 12; 1935 for (int i = 0; i < count; i++) { 1936 ffrt::submit([&]() { 1937 ffrt_usleep(100); 1938 std::cout << "test" << std::endl; 1939 ffrt_yield(); 1940 }, {}, {}); 1941 } 1942 ffrt::wait(); 1943 return 0; 1944} 1945``` 1946 1947## Timer 1948 1949### ffrt_timer_t 1950 1951#### Declaration 1952 1953```c 1954typedef int ffrt_timer_t; 1955typedef void (*ffrt_timer_cb)(void* data); 1956``` 1957 1958#### Description 1959 1960Provides timer-related functions. 1961 1962#### Methods 1963 1964##### ffrt_timer_start 1965 1966Declaration 1967 1968```c 1969FFRT_C_API ffrt_timer_t ffrt_timer_start(ffrt_qos_t qos, uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat); 1970``` 1971 1972Parameters 1973 1974- `qos`: QoS. 1975- `timeout`: timer timeout, in ms. 1976- `cb`: callback function after expiration. 1977- `data`: input parameter of the callback function. 1978- `repeat`: whether the timer is triggered repeatedly. 1979 1980Return Values 1981 1982- `ffrt_timer_t`, which indicates the timer handle. 1983 1984Description 1985 1986- Starts a timer. If the timer expires and is not stopped, the callback function is executed. If `repeat` is set to `repeat`, the timer is set again after it expires. 1987 1988##### ffrt_timer_stop 1989 1990Declaration 1991 1992```c 1993FFRT_C_API int ffrt_timer_stop(ffrt_qos_t qos, ffrt_timer_t handle); 1994``` 1995 1996Parameters 1997 1998- `qos`: QoS. 1999- `handle`: timer handle. 2000 2001Return Values 2002 2003- The value **0** indicates success, and the value **-1** indicates failure. 2004 2005Description 2006 2007- Stops a timer. It is used with `ffrt_timer_start`. 2008 2009#### Example 2010 2011- Example 1: Use a one-shot timer. 2012 2013 ```c 2014 #include <stdio.h> 2015 #include <unistd.h> 2016 #include "ffrt/timer.h" 2017 2018 static void test_fun(void *data) 2019 { 2020 *(int *)data += 1; 2021 } 2022 2023 void (*cb)(void *) = test_fun; 2024 2025 int main() 2026 { 2027 static int x = 0; 2028 void *data = &x; 2029 uint64_t timeout = 200; 2030 // Start a timer and execute the callback function after 200 ms. 2031 int handle = ffrt_timer_start(ffrt_qos_default, timeout, data, cb, false); 2032 usleep(300000); 2033 // The timer has been executed and cannot be stopped. 2034 ffrt_timer_stop(ffrt_qos_default, handle); 2035 printf("data: %d\n", x); // Set the value of x to 1. 2036 return 0; 2037 } 2038 ``` 2039 2040- Example 2: Use a repeating timer. 2041 2042 ```c 2043 #include <stdio.h> 2044 #include <unistd.h> 2045 #include "ffrt/timer.h" 2046 2047 static void test_fun(void *data) 2048 { 2049 *(int *)data += 1; 2050 } 2051 2052 void (*cb)(void *) = test_fun; 2053 2054 int main() 2055 { 2056 static int x = 0; 2057 void *data = &x; 2058 uint64_t timeout = 200; 2059 // Start a repeating timer and execute the callback function every 200 ms. 2060 int handle = ffrt_timer_start(ffrt_qos_default, timeout, data, cb, true); 2061 usleep(500000); 2062 // Stops the repeating timer. 2063 ffrt_timer_stop(ffrt_qos_default, handle); 2064 printf("data: %d\n", x); // Set the value of x to 2. 2065 return 0; 2066 } 2067 ``` 2068 2069## Loop 2070 2071### ffrt_loop_t 2072 2073#### Declaration 2074 2075```c 2076typedef void* ffrt_loop_t; 2077``` 2078 2079#### Description 2080 2081Provides loop-related functions. 2082 2083#### Methods 2084 2085##### ffrt_loop_create 2086 2087Declaration 2088 2089```c 2090FFRT_C_API ffrt_loop_t ffrt_loop_create(ffrt_queue_t queue); 2091``` 2092 2093Parameters 2094 2095- `queue`: a concurrent queue that needs to be bound with a loop. 2096 2097Return Values 2098 2099- `ffrt_loop_t` object. 2100 2101Description 2102 2103- Creates a loop and bind a concurrent queue for storing tasks. You can submit a task to the queue so that the task can be executed in the loop. 2104 2105##### ffrt_loop_destroy 2106 2107Declaration 2108 2109```c 2110FFRT_C_API int ffrt_loop_destroy(ffrt_loop_t loop); 2111``` 2112 2113Parameters 2114 2115- `loop`: loop object. 2116 2117Return Values 2118 2119- The value **0** indicates success, and the value **-1** indicates failure. 2120 2121Description 2122 2123- Destroys a loop and unbinds it from the queue. 2124 2125##### ffrt_loop_run 2126 2127Declaration 2128 2129```c 2130FFRT_C_API int ffrt_loop_run(ffrt_loop_t loop); 2131``` 2132 2133Parameters 2134 2135- `loop`: loop object. 2136 2137Return Values 2138 2139- The value **0** indicates success, and the value **-1** indicates failure. 2140 2141Description 2142 2143- Runs a loop. The thread that invokes this method executes the loop at the same time, executes queue tasks, and listens for the poller and timer. 2144 2145##### ffrt_loop_stop 2146 2147Declaration 2148 2149```c 2150FFRT_C_API void ffrt_loop_stop(ffrt_loop_t loop); 2151``` 2152 2153Parameters 2154 2155- `loop`: loop object. 2156 2157Description 2158 2159- Stops a loop. This method is invoked to enable the thread that executes the loop to exit the loop. 2160 2161##### ffrt_loop_epoll_ctl 2162 2163Declaration 2164 2165```c 2166int ffrt_loop_epoll_ctl(ffrt_loop_t loop, int op, int fd, uint32_t events, void *data, ffrt_poller_cb cb) 2167``` 2168 2169Parameters 2170 2171- `loop`: loop object. 2172- `op`: FD operator. For details, see the operation type of **epoll_ctl**. 2173- `fd`: event descriptor. 2174- `events`: event. For details, see the event type of **epoll_ctl**. 2175- `data`: input parameter of the callback function. 2176- `cb`: callback function. 2177 2178Return Values 2179 2180- The value **0** indicates success, and the value **-1** indicates failure. 2181 2182Description 2183 2184- Manages FD listening on the loop. Event listening and callback are processed on the loop thread. 2185 2186##### ffrt_loop_timer_start 2187 2188Declaration 2189 2190```c 2191FFRT_C_API ffrt_timer_t ffrt_loop_timer_start(ffrt_loop_t loop, uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat); 2192``` 2193 2194Parameters 2195 2196- `loop`: loop object. 2197- `timeout`: timer timeout, in ms. 2198- `cb`: callback function after expiration. 2199- `data`: input parameter of the callback function. 2200- `repeat`: whether the timer is triggered repeatedly. 2201 2202Return Values 2203 2204- `ffrt_timer_t`, which indicates the timer handle. 2205 2206Description 2207 2208- Starts a timer on the loop. The usage is the same as that of `ffrt_timer_start`. The only difference is that the listening and callback execution of the timer are processed on the loop thread. 2209 2210##### ffrt_loop_timer_stop 2211 2212Declaration 2213 2214```c 2215FFRT_C_API int ffrt_loop_timer_stop(ffrt_loop_t loop, ffrt_timer_t handle); 2216``` 2217 2218Parameters 2219 2220- `loop`: loop object. 2221- `handle`: timer handle. 2222 2223Return Values 2224 2225- The value **0** indicates success, and the value **-1** indicates failure. 2226 2227Description 2228 2229- Stops a timer. The usage is the same as that of `ffrt_timer_stop`. 2230 2231#### Example 2232 2233- Example 1: loop and concurrent queue. 2234 2235 ```c 2236 #include <pthread.h> 2237 #include <stdio.h> 2238 #include "ffrt/loop.h" 2239 2240 void* ThreadFunc(void* p) 2241 { 2242 int ret = ffrt_loop_run(p); 2243 if (ret == 0) { 2244 printf("loop normal operation."); 2245 } 2246 return NULL; 2247 } 2248 2249 int main() 2250 { 2251 // Create a concurrent queue. 2252 ffrt_queue_attr_t queue_attr; 2253 (void)ffrt_queue_attr_init(&queue_attr); 2254 ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_concurrent, "test_queue", &queue_attr); 2255 2256 // Create a loop. 2257 ffrt_loop_t loop = ffrt_loop_create(queue_handle); 2258 2259 // Create a separate thread to perform the loop. 2260 pthread_t thread; 2261 pthread_create(&thread, 0, ThreadFunc, loop); 2262 2263 // Stop and destroy the loop. 2264 ffrt_loop_stop(loop); 2265 ffrt_loop_destroy(loop); 2266 2267 // Destroy the concurrent queue. 2268 ffrt_queue_attr_destroy(&queue_attr); 2269 ffrt_queue_destroy(queue_handle); 2270 return 0; 2271 } 2272 ``` 2273 2274- Example 2: loop, concurrent queue, and timer. 2275 2276 ```cpp 2277 #include <pthread.h> 2278 #include <unistd.h> 2279 #include <stdio.h> 2280 #include <functional> 2281 #include <sys/epoll.h> 2282 #include <sys/eventfd.h> 2283 #include "ffrt/loop.h" 2284 #include "ffrt/cpp/task.h" 2285 2286 void* ThreadFunc(void* p) 2287 { 2288 ffrt_loop_run(p); 2289 return nullptr; 2290 } 2291 2292 static void test_fun(void* data) 2293 { 2294 *(int*)data += 1; 2295 } 2296 2297 static void (*cb)(void*) = test_fun; 2298 2299 void testCallBack(void *data, unsigned int events) {} 2300 2301 struct TestData { 2302 int fd; 2303 uint64_t expected; 2304 }; 2305 2306 int main() 2307 { 2308 // Create a concurrent queue. 2309 ffrt_queue_attr_t queue_attr; 2310 (void)ffrt_queue_attr_init(&queue_attr); 2311 ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_concurrent, "test_queue", &queue_attr); 2312 2313 // Create a loop. 2314 auto loop = ffrt_loop_create(queue_handle); 2315 int result1 = 0; 2316 2317 // Submit a task to the loop queue. 2318 std::function<void()> &&basicFunc1 = [&result1]() { result1 += 10; }; 2319 ffrt_task_handle_t task = ffrt_queue_submit_h(queue_handle, ffrt::create_function_wrapper(basicFunc1, ffrt_function_kind_queue), nullptr); 2320 2321 // Create a separate thread to perform the loop. 2322 pthread_t thread; 2323 pthread_create(&thread, 0, ThreadFunc, loop); 2324 2325 static int x = 0; 2326 int* xf = &x; 2327 void* data = xf; 2328 uint64_t timeout1 = 20; 2329 uint64_t timeout2 = 10; 2330 uint64_t expected = 0xabacadae; 2331 2332 int testFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); 2333 struct TestData testData {.fd = testFd, .expected = expected}; 2334 2335 // Register a timer with the loop. 2336 ffrt_timer_t timeHandle = ffrt_loop_timer_start(loop, timeout1, data, cb, false); 2337 2338 // Register an FD listener with the loop. 2339 int ret = ffrt_loop_epoll_ctl(loop, EPOLL_CTL_ADD, testFd, EPOLLIN, (void*)(&testData), testCallBack); 2340 if (ret == 0) { 2341 printf("ffrt_loop_epoll_ctl executed successfully.\n"); 2342 } 2343 ssize_t n = write(testFd, &expected, sizeof(uint64_t)); 2344 usleep(25000); 2345 // Delete the FD listener. 2346 ffrt_loop_epoll_ctl(loop, EPOLL_CTL_DEL, testFd, 0, nullptr, nullptr); 2347 2348 // Stop the loop. 2349 ffrt_loop_stop(loop); 2350 pthread_join(thread, nullptr); 2351 2352 // Delete the timer. 2353 ffrt_loop_timer_stop(loop, timeHandle); 2354 2355 // Destroy the loop. 2356 ret = ffrt_loop_destroy(loop); 2357 2358 // Destroy the concurrent queue. 2359 ffrt_queue_attr_destroy(&queue_attr); 2360 ffrt_queue_destroy(queue_handle); 2361 return 0; 2362 } 2363 ``` 2364