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 #ifndef FFRT_API_CPP_THREAD_H 16 #define FFRT_API_CPP_THREAD_H 17 #include <memory> 18 #include "cpp/task.h" 19 20 namespace ffrt { 21 class thread { 22 public: thread()23 thread() noexcept 24 { 25 } 26 27 template <typename Fn, typename... Args, 28 class = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Fn>>, thread>>> thread(const char * name,qos qos_,Fn && fn,Args &&...args)29 explicit thread(const char* name, qos qos_, Fn&& fn, Args&&... args) 30 { 31 is_joinable = std::make_unique<task_handle>(); 32 using Target = std::tuple<std::decay_t<Fn>, std::decay_t<Args>...>; 33 auto tup = new Target(std::forward<Fn>(fn), std::forward<Args>(args)...); 34 *is_joinable = ffrt::submit_h([tup]() { 35 execute(*tup, std::make_index_sequence<std::tuple_size_v<Target>>()); 36 delete tup; 37 }, {}, {}, ffrt::task_attr().name(name).qos(qos_)); 38 } 39 40 template <typename Fn, typename... Args, 41 class = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Fn>>, thread>>> thread(qos qos_,Fn && fn,Args &&...args)42 explicit thread(qos qos_, Fn&& fn, Args&&... args) 43 { 44 is_joinable = std::make_unique<task_handle>(); 45 using Target = std::tuple<std::decay_t<Fn>, std::decay_t<Args>...>; 46 auto tup = new Target(std::forward<Fn>(fn), std::forward<Args>(args)...); 47 *is_joinable = ffrt::submit_h([tup]() { 48 execute(*tup, std::make_index_sequence<std::tuple_size_v<Target>>()); 49 delete tup; 50 }, {}, {}, ffrt::task_attr().qos(qos_)); 51 } 52 53 template <class Fn, class... Args, 54 class = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Fn>>, thread>>, 55 class = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Fn>>, char*>>, 56 class = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Fn>>, qos>>> 57 explicit thread(Fn&& fn, Args&& ... args) 58 { 59 is_joinable = std::make_unique<task_handle>(); 60 using Target = std::tuple<std::decay_t<Fn>, std::decay_t<Args>...>; 61 auto tup = new Target (std::forward<Fn>(fn), std::forward<Args>(args)...); 62 *is_joinable = ffrt::submit_h([tup]() { 63 execute(*tup, std::make_index_sequence<std::tuple_size_v<Target>>()); 64 delete tup; 65 }); 66 } 67 68 thread(const thread&) = delete; 69 thread& operator=(const thread&) = delete; 70 thread(thread && th)71 thread(thread&& th) noexcept 72 { 73 swap(th); 74 } 75 76 thread& operator=(thread&& th) noexcept 77 { 78 if (this != &th) { 79 thread tmp(std::move(th)); 80 swap(tmp); 81 } 82 return *this; 83 } 84 joinable()85 bool joinable() const noexcept 86 { 87 return is_joinable.get() && *is_joinable; 88 } 89 detach()90 void detach() noexcept 91 { 92 is_joinable = nullptr; 93 } 94 join()95 void join() noexcept 96 { 97 if (joinable()) { 98 ffrt::wait({*is_joinable}); 99 is_joinable = nullptr; 100 } 101 } 102 ~thread()103 ~thread() 104 { 105 if (joinable()) { 106 std::terminate(); 107 } 108 } 109 110 private: 111 template<class Target, size_t... Idxs> execute(Target & tup,std::index_sequence<Idxs...>)112 static inline void execute(Target& tup, 113 std::index_sequence<Idxs...>) 114 { 115 std::invoke(std::move(std::get<Idxs>(tup))...); 116 } 117 swap(thread & other)118 void swap(thread& other) noexcept 119 { 120 is_joinable.swap(other.is_joinable); 121 }; 122 std::unique_ptr<task_handle> is_joinable; 123 }; 124 } // namespace ffrt 125 #endif 126