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