1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 /** 17 * @file task.h 18 * 19 * @brief Declares the task interfaces in C++. 20 * 21 * @since 10 22 * @version 1.0 23 */ 24#ifndef FFRT_API_CPP_TASK_H 25#define FFRT_API_CPP_TASK_H 26#include <string> 27#include <vector> 28#include <functional> 29#include "c/task.h" 30 31namespace ffrt { 32class task_attr : public ffrt_task_attr_t { 33public: 34#if __has_builtin(__builtin_FUNCTION) 35 task_attr(const char* func = __builtin_FUNCTION()) 36 { 37 ffrt_task_attr_init(this); 38 ffrt_task_attr_set_name(this, func); 39 } 40#else 41 task_attr() 42 { 43 ffrt_task_attr_init(this); 44 } 45#endif 46 47 ~task_attr() 48 { 49 ffrt_task_attr_destroy(this); 50 } 51 52 task_attr(const task_attr&) = delete; 53 task_attr& operator=(const task_attr&) = delete; 54 55 /** 56 * @brief Sets a task name. 57 * 58 * @param name Indicates a pointer to the task name. 59 * @since 10 60 * @version 1.0 61 */ 62 inline task_attr& name(const char* name) 63 { 64 ffrt_task_attr_set_name(this, name); 65 return *this; 66 } 67 68 /** 69 * @brief Obtains the task name. 70 * 71 * @return Returns a pointer to the task name. 72 * @since 10 73 * @version 1.0 74 */ 75 inline const char* name() const 76 { 77 return ffrt_task_attr_get_name(this); 78 } 79 80 /** 81 * @brief Sets the QoS for this task. 82 * 83 * @param qos Indicates the QoS. 84 * @since 10 85 * @version 1.0 86 */ 87 inline task_attr& qos(qos qos_) 88 { 89 ffrt_task_attr_set_qos(this, qos_); 90 return *this; 91 } 92 93 /** 94 * @brief Obtains the QoS of this task. 95 * 96 * @return Returns the QoS. 97 * @since 10 98 * @version 1.0 99 */ 100 inline int qos() const 101 { 102 return ffrt_task_attr_get_qos(this); 103 } 104 105 /** 106 * @brief Sets the delay time for this task. 107 * 108 * @param delay_us Indicates the delay time, in microseconds. 109 * @since 10 110 * @version 1.0 111 */ 112 inline task_attr& delay(uint64_t delay_us) 113 { 114 ffrt_task_attr_set_delay(this, delay_us); 115 return *this; 116 } 117 118 /** 119 * @brief Obtains the delay time of this task. 120 * 121 * @return Returns the delay time. 122 * @since 10 123 * @version 1.0 124 */ 125 inline uint64_t delay() const 126 { 127 return ffrt_task_attr_get_delay(this); 128 } 129 130 /** 131 * @brief Sets the priority for this task. 132 * 133 * @param priority Indicates the execute priority of concurrent queue task. 134 * @since 12 135 * @version 1.0 136 */ 137 inline task_attr& priority(ffrt_queue_priority_t prio) 138 { 139 ffrt_task_attr_set_queue_priority(this, prio); 140 return *this; 141 } 142 143 /** 144 * @brief Obtains the priority of this task. 145 * 146 * @return Returns the priority of concurrent queue task. 147 * @since 12 148 * @version 1.0 149 */ 150 inline ffrt_queue_priority_t priority() const 151 { 152 return ffrt_task_attr_get_queue_priority(this); 153 } 154 155 /** 156 * @brief Sets the stack size for this task. 157 * 158 * @param size Indicates the task stack size, unit is byte. 159 * @since 12 160 * @version 1.0 161 */ 162 inline task_attr& stack_size(uint64_t size) 163 { 164 ffrt_task_attr_set_stack_size(this, size); 165 return *this; 166 } 167 168 /** 169 * @brief Obtains the stack size of this task. 170 * 171 * @return Returns task stack size, unit is byte. 172 * @since 12 173 * @version 1.0 174 */ 175 inline uint64_t stack_size() const 176 { 177 return ffrt_task_attr_get_stack_size(this); 178 } 179}; 180 181class task_handle { 182public: 183 task_handle() : p(nullptr) 184 { 185 } 186 task_handle(ffrt_task_handle_t p) : p(p) 187 { 188 } 189 190 ~task_handle() 191 { 192 if (p) { 193 ffrt_task_handle_destroy(p); 194 } 195 } 196 197 task_handle(task_handle const&) = delete; 198 task_handle& operator=(task_handle const&) = delete; 199 200 inline task_handle(task_handle&& h) 201 { 202 *this = std::move(h); 203 } 204 205 inline task_handle& operator=(task_handle&& h) 206 { 207 if (this != &h) { 208 if (p) { 209 ffrt_task_handle_destroy(p); 210 } 211 p = h.p; 212 h.p = nullptr; 213 } 214 return *this; 215 } 216 217 inline operator void* () const 218 { 219 return p; 220 } 221 222private: 223 ffrt_task_handle_t p = nullptr; 224}; 225 226struct dependence : ffrt_dependence_t { 227 dependence(const void* d) 228 { 229 type = ffrt_dependence_data; 230 ptr = d; 231 } 232 dependence(const task_handle& h) 233 { 234 type = ffrt_dependence_task; 235 ptr = h; 236 ffrt_task_handle_inc_ref(const_cast<ffrt_task_handle_t>(ptr)); 237 } 238 239 dependence(const dependence& other) 240 { 241 (*this) = other; 242 } 243 244 dependence(dependence&& other) 245 { 246 (*this) = std::move(other); 247 } 248 249 dependence& operator=(const dependence& other) 250 { 251 if (this != &other) { 252 type = other.type; 253 ptr = other.ptr; 254 if (type == ffrt_dependence_task) { 255 ffrt_task_handle_inc_ref(const_cast<ffrt_task_handle_t>(ptr)); 256 } 257 } 258 return *this; 259 } 260 261 dependence& operator=(dependence&& other) 262 { 263 if (this != &other) { 264 type = other.type; 265 ptr = other.ptr; 266 other.ptr = nullptr; 267 } 268 return *this; 269 } 270 271 ~dependence() 272 { 273 if (type == ffrt_dependence_task && ptr) { 274 ffrt_task_handle_dec_ref(const_cast<ffrt_task_handle_t>(ptr)); 275 } 276 } 277}; 278 279template<class T> 280struct function { 281 ffrt_function_header_t header; 282 T closure; 283}; 284 285template<class T> 286void exec_function_wrapper(void* t) 287{ 288 auto f = reinterpret_cast<function<std::decay_t<T>>*>(t); 289 f->closure(); 290} 291 292template<class T> 293void destroy_function_wrapper(void* t) 294{ 295 auto f = reinterpret_cast<function<std::decay_t<T>>*>(t); 296 f->closure = nullptr; 297} 298 299template<class T> 300inline ffrt_function_header_t* create_function_wrapper(T&& func, 301 ffrt_function_kind_t kind = ffrt_function_kind_general) 302{ 303 using function_type = function<std::decay_t<T>>; 304 static_assert(sizeof(function_type) <= ffrt_auto_managed_function_storage_size, 305 "size of function must be less than ffrt_auto_managed_function_storage_size"); 306 307 auto p = ffrt_alloc_auto_managed_function_storage_base(kind); 308 auto f = new (p)function_type; 309 f->header.exec = exec_function_wrapper<T>; 310 f->header.destroy = destroy_function_wrapper<T>; 311 f->closure = std::forward<T>(func); 312 return reinterpret_cast<ffrt_function_header_t*>(f); 313} 314 315/** 316 * @brief Submits a task without input and output dependencies. 317 * 318 * @param func Indicates a task executor function closure. 319 * @param attr Indicates a task attribute. 320 * @since 10 321 * @version 1.0 322 */ 323static inline void submit(std::function<void()>&& func, const task_attr& attr = {}) 324{ 325 return ffrt_submit_base(create_function_wrapper(std::move(func)), nullptr, nullptr, &attr); 326} 327 328/** 329 * @brief Submits a task with input dependencies only. 330 * 331 * @param func Indicates a task executor function closure. 332 * @param in_deps Indicates a pointer to the input dependencies. 333 * @param attr Indicates a task attribute. 334 * @since 10 335 * @version 1.0 336 */ 337static inline void submit(std::function<void()>&& func, std::initializer_list<dependence> in_deps, 338 const task_attr& attr = {}) 339{ 340 ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.begin()}; 341 return ffrt_submit_base(create_function_wrapper(std::move(func)), &in, nullptr, &attr); 342} 343 344/** 345 * @brief Submits a task with input and output dependencies. 346 * 347 * @param func Indicates a task executor function closure. 348 * @param in_deps Indicates a pointer to the input dependencies. 349 * @param out_deps Indicates a pointer to the output dependencies. 350 * @param attr Indicates a task attribute. 351 * @since 10 352 * @version 1.0 353 */ 354static inline void submit(std::function<void()>&& func, std::initializer_list<dependence> in_deps, 355 std::initializer_list<dependence> out_deps, const task_attr& attr = {}) 356{ 357 ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.begin()}; 358 ffrt_deps_t out{static_cast<uint32_t>(out_deps.size()), out_deps.begin()}; 359 return ffrt_submit_base(create_function_wrapper(std::move(func)), &in, &out, &attr); 360} 361 362/** 363 * @brief Submits a task with input dependencies only. 364 * 365 * @param func Indicates a task executor function closure. 366 * @param in_deps Indicates a pointer to the input dependencies. 367 * @param attr Indicates a task attribute. 368 * @since 10 369 * @version 1.0 370 */ 371static inline void submit(std::function<void()>&& func, const std::vector<dependence>& in_deps, 372 const task_attr& attr = {}) 373{ 374 ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.data()}; 375 return ffrt_submit_base(create_function_wrapper(std::move(func)), &in, nullptr, &attr); 376} 377 378/** 379 * @brief Submits a task with input and output dependencies. 380 * 381 * @param func Indicates a task executor function closure. 382 * @param in_deps Indicates a pointer to the input dependencies. 383 * @param out_deps Indicates a pointer to the output dependencies. 384 * @param attr Indicates a task attribute. 385 * @since 10 386 * @version 1.0 387 */ 388static inline void submit(std::function<void()>&& func, const std::vector<dependence>& in_deps, 389 const std::vector<dependence>& out_deps, const task_attr& attr = {}) 390{ 391 ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.data()}; 392 ffrt_deps_t out{static_cast<uint32_t>(out_deps.size()), out_deps.data()}; 393 return ffrt_submit_base(create_function_wrapper(std::move(func)), &in, &out, &attr); 394} 395 396/** 397 * @brief Submits a task without input and output dependencies. 398 * 399 * @param func Indicates a task executor function closure. 400 * @param attr Indicates a task attribute. 401 * @since 10 402 * @version 1.0 403 */ 404static inline void submit(const std::function<void()>& func, const task_attr& attr = {}) 405{ 406 return ffrt_submit_base(create_function_wrapper(func), nullptr, nullptr, &attr); 407} 408 409/** 410 * @brief Submits a task with input dependencies only. 411 * 412 * @param func Indicates a task executor function closure. 413 * @param in_deps Indicates a pointer to the input dependencies. 414 * @param attr Indicates a task attribute. 415 * @since 10 416 * @version 1.0 417 */ 418static inline void submit(const std::function<void()>& func, std::initializer_list<dependence> in_deps, 419 const task_attr& attr = {}) 420{ 421 ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.begin()}; 422 return ffrt_submit_base(create_function_wrapper(func), &in, nullptr, &attr); 423} 424 425/** 426 * @brief Submits a task with input and output dependencies. 427 * 428 * @param func Indicates a task executor function closure. 429 * @param in_deps Indicates a pointer to the input dependencies. 430 * @param out_deps Indicates a pointer to the output dependencies. 431 * @param attr Indicates a task attribute. 432 * @since 10 433 * @version 1.0 434 */ 435static inline void submit(const std::function<void()>& func, std::initializer_list<dependence> in_deps, 436 std::initializer_list<dependence> out_deps, const task_attr& attr = {}) 437{ 438 ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.begin()}; 439 ffrt_deps_t out{static_cast<uint32_t>(out_deps.size()), out_deps.begin()}; 440 return ffrt_submit_base(create_function_wrapper(func), &in, &out, &attr); 441} 442 443/** 444 * @brief Submits a task with input dependencies only. 445 * 446 * @param func Indicates a task executor function closure. 447 * @param in_deps Indicates a pointer to the input dependencies. 448 * @param attr Indicates a task attribute. 449 * @since 10 450 * @version 1.0 451 */ 452static inline void submit(const std::function<void()>& func, const std::vector<dependence>& in_deps, 453 const task_attr& attr = {}) 454{ 455 ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.data()}; 456 return ffrt_submit_base(create_function_wrapper(func), &in, nullptr, &attr); 457} 458 459/** 460 * @brief Submits a task with input and output dependencies. 461 * 462 * @param func Indicates a task executor function closure. 463 * @param in_deps Indicates a pointer to the input dependencies. 464 * @param out_deps Indicates a pointer to the output dependencies. 465 * @param attr Indicates a task attribute. 466 * @since 10 467 * @version 1.0 468 */ 469static inline void submit(const std::function<void()>& func, const std::vector<dependence>& in_deps, 470 const std::vector<dependence>& out_deps, const task_attr& attr = {}) 471{ 472 ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.data()}; 473 ffrt_deps_t out{static_cast<uint32_t>(out_deps.size()), out_deps.data()}; 474 return ffrt_submit_base(create_function_wrapper(func), &in, &out, &attr); 475} 476 477/** 478 * @brief Submits a task without input and output dependencies, and obtains a task handle. 479 * 480 * @param func Indicates a task executor function closure. 481 * @param attr Indicates a task attribute. 482 * @return Returns a non-null task handle if the task is submitted; 483 returns a null pointer otherwise. 484 * @since 10 485 * @version 1.0 486 */ 487static inline task_handle submit_h(std::function<void()>&& func, const task_attr& attr = {}) 488{ 489 return ffrt_submit_h_base(create_function_wrapper(std::move(func)), nullptr, nullptr, &attr); 490} 491 492/** 493 * @brief Submits a task with input dependencies only, and obtains a task handle. 494 * 495 * @param func Indicates a task executor function closure. 496 * @param in_deps Indicates a pointer to the input dependencies. 497 * @param attr Indicates a task attribute. 498 * @return Returns a non-null task handle if the task is submitted; 499 returns a null pointer otherwise. 500 * @since 10 501 * @version 1.0 502 */ 503static inline task_handle submit_h(std::function<void()>&& func, std::initializer_list<dependence> in_deps, 504 const task_attr& attr = {}) 505{ 506 ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.begin()}; 507 return ffrt_submit_h_base(create_function_wrapper(std::move(func)), &in, nullptr, &attr); 508} 509 510/** 511 * @brief Submits a task with input and output dependencies, and obtains a task handle. 512 * 513 * @param func Indicates a task executor function closure. 514 * @param in_deps Indicates a pointer to the input dependencies. 515 * @param out_deps Indicates a pointer to the output dependencies. 516 * @param attr Indicates a task attribute. 517 * @return Returns a non-null task handle if the task is submitted; 518 returns a null pointer otherwise. 519 * @since 10 520 * @version 1.0 521 */ 522static inline task_handle submit_h(std::function<void()>&& func, std::initializer_list<dependence> in_deps, 523 std::initializer_list<dependence> out_deps, const task_attr& attr = {}) 524{ 525 ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.begin()}; 526 ffrt_deps_t out{static_cast<uint32_t>(out_deps.size()), out_deps.begin()}; 527 return ffrt_submit_h_base(create_function_wrapper(std::move(func)), &in, &out, &attr); 528} 529 530/** 531 * @brief Submits a task with input dependencies only, and obtains a task handle. 532 * 533 * @param func Indicates a task executor function closure. 534 * @param in_deps Indicates a pointer to the input dependencies. 535 * @param attr Indicates a task attribute. 536 * @return Returns a non-null task handle if the task is submitted; 537 returns a null pointer otherwise. 538 * @since 10 539 * @version 1.0 540 */ 541static inline task_handle submit_h(std::function<void()>&& func, const std::vector<dependence>& in_deps, 542 const task_attr& attr = {}) 543{ 544 ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.data()}; 545 return ffrt_submit_h_base(create_function_wrapper(std::move(func)), &in, nullptr, &attr); 546} 547 548/** 549 * @brief Submits a task with input and output dependencies, and obtains a task handle. 550 * 551 * @param func Indicates a task executor function closure. 552 * @param in_deps Indicates a pointer to the input dependencies. 553 * @param out_deps Indicates a pointer to the output dependencies. 554 * @param attr Indicates a task attribute. 555 * @return Returns a non-null task handle if the task is submitted; 556 returns a null pointer otherwise. 557 * @since 10 558 * @version 1.0 559 */ 560static inline task_handle submit_h(std::function<void()>&& func, const std::vector<dependence>& in_deps, 561 const std::vector<dependence>& out_deps, const task_attr& attr = {}) 562{ 563 ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.data()}; 564 ffrt_deps_t out{static_cast<uint32_t>(out_deps.size()), out_deps.data()}; 565 return ffrt_submit_h_base(create_function_wrapper(std::move(func)), &in, &out, &attr); 566} 567 568/** 569 * @brief Submits a task without input and output dependencies, and obtains a task handle. 570 * 571 * @param func Indicates a task executor function closure. 572 * @param attr Indicates a task attribute. 573 * @return Returns a non-null task handle if the task is submitted; 574 returns a null pointer otherwise. 575 * @since 10 576 * @version 1.0 577 */ 578static inline task_handle submit_h(const std::function<void()>& func, const task_attr& attr = {}) 579{ 580 return ffrt_submit_h_base(create_function_wrapper(func), nullptr, nullptr, &attr); 581} 582 583/** 584 * @brief Submits a task with input dependencies only, and obtains a task handle. 585 * 586 * @param func Indicates a task executor function closure. 587 * @param in_deps Indicates a pointer to the input dependencies. 588 * @param attr Indicates a task attribute. 589 * @return Returns a non-null task handle if the task is submitted; 590 returns a null pointer otherwise. 591 * @since 10 592 * @version 1.0 593 */ 594static inline task_handle submit_h(const std::function<void()>& func, std::initializer_list<dependence> in_deps, 595 const task_attr& attr = {}) 596{ 597 ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.begin()}; 598 return ffrt_submit_h_base(create_function_wrapper(func), &in, nullptr, &attr); 599} 600 601/** 602 * @brief Submits a task with input and output dependencies, and obtains a task handle. 603 * 604 * @param func Indicates a task executor function closure. 605 * @param in_deps Indicates a pointer to the input dependencies. 606 * @param out_deps Indicates a pointer to the output dependencies. 607 * @param attr Indicates a task attribute. 608 * @return Returns a non-null task handle if the task is submitted; 609 returns a null pointer otherwise. 610 * @since 10 611 * @version 1.0 612 */ 613static inline task_handle submit_h(const std::function<void()>& func, std::initializer_list<dependence> in_deps, 614 std::initializer_list<dependence> out_deps, const task_attr& attr = {}) 615{ 616 ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.begin()}; 617 ffrt_deps_t out{static_cast<uint32_t>(out_deps.size()), out_deps.begin()}; 618 return ffrt_submit_h_base(create_function_wrapper(func), &in, &out, &attr); 619} 620 621/** 622 * @brief Submits a task with input dependencies only, and obtains a task handle. 623 * 624 * @param func Indicates a task executor function closure. 625 * @param in_deps Indicates a pointer to the input dependencies. 626 * @param attr Indicates a task attribute. 627 * @return Returns a non-null task handle if the task is submitted; 628 returns a null pointer otherwise. 629 * @since 10 630 * @version 1.0 631 */ 632static inline task_handle submit_h(const std::function<void()>& func, const std::vector<dependence>& in_deps, 633 const task_attr& attr = {}) 634{ 635 ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.data()}; 636 return ffrt_submit_h_base(create_function_wrapper(func), &in, nullptr, &attr); 637} 638 639/** 640 * @brief Submits a task with input and output dependencies, and obtains a task handle. 641 * 642 * @param func Indicates a task executor function closure. 643 * @param in_deps Indicates a pointer to the input dependencies. 644 * @param out_deps Indicates a pointer to the output dependencies. 645 * @param attr Indicates a task attribute. 646 * @return Returns a non-null task handle if the task is submitted; 647 returns a null pointer otherwise. 648 * @since 10 649 * @version 1.0 650 */ 651static inline task_handle submit_h(const std::function<void()>& func, const std::vector<dependence>& in_deps, 652 const std::vector<dependence>& out_deps, const task_attr& attr = {}) 653{ 654 ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.data()}; 655 ffrt_deps_t out{static_cast<uint32_t>(out_deps.size()), out_deps.data()}; 656 return ffrt_submit_h_base(create_function_wrapper(func), &in, &out, &attr); 657} 658 659/** 660 * @brief Waits until all submitted tasks are complete. 661 * 662 * @since 10 663 * @version 1.0 664 */ 665static inline void wait() 666{ 667 ffrt_wait(); 668} 669 670/** 671 * @brief Waits until dependent tasks are complete. 672 * 673 * @param deps Indicates a pointer to the dependent tasks. 674 * @since 10 675 * @version 1.0 676 */ 677static inline void wait(std::initializer_list<dependence> deps) 678{ 679 ffrt_deps_t d{static_cast<uint32_t>(deps.size()), deps.begin()}; 680 ffrt_wait_deps(&d); 681} 682 683/** 684 * @brief Waits until dependent tasks are complete. 685 * 686 * @param deps Indicates a pointer to the dependent tasks. 687 * @since 10 688 * @version 1.0 689 */ 690static inline void wait(const std::vector<dependence>& deps) 691{ 692 ffrt_deps_t d{static_cast<uint32_t>(deps.size()), deps.data()}; 693 ffrt_wait_deps(&d); 694} 695 696/** 697 * @brief Sets the thread stack size of a specified QoS level. 698 * 699 * @param qos_ Indicates the QoS. 700 * @param stack_size Indicates the thread stack size. 701 * @return Returns ffrt_success if the stack size set success; 702 returns ffrt_error_inval if qos_ or stack_size invalid; 703 returns ffrt_error otherwise. 704 * @since 10 705 * @version 1.0 706 */ 707static inline ffrt_error_t set_worker_stack_size(qos qos_, size_t stack_size) 708{ 709 return ffrt_set_worker_stack_size(qos_, stack_size); 710} 711 712namespace this_task { 713static inline int update_qos(qos qos_) 714{ 715 return ffrt_this_task_update_qos(qos_); 716} 717 718/** 719 * @brief Obtains the ID of this task. 720 * 721 * @return Returns the task ID. 722 * @since 10 723 * @version 1.0 724 */ 725static inline uint64_t get_id() 726{ 727 return ffrt_this_task_get_id(); 728} 729} // namespace this_task 730} // namespace ffrt 731#endif 732