• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "../../kits/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<bool>(true);
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         ffrt::submit([tup]() {
35             execute(*tup, std::make_index_sequence<std::tuple_size_v<Target>>());
36             delete tup;
37             }, {}, {is_joinable.get()}, 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<bool>(true);
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         ffrt::submit([tup]() {
48             execute(*tup, std::make_index_sequence<std::tuple_size_v<Target>>());
49             delete tup;
50             }, {}, {is_joinable.get()}, 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>>>
thread(Fn && fn,Args &&...args)57     explicit thread(Fn&& fn, Args&& ... args)
58     {
59         is_joinable = std::make_unique<bool>(true);
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         ffrt::submit([tup]() {
63             execute(*tup, std::make_index_sequence<std::tuple_size_v<Target>>());
64             delete tup;
65             }, {}, {is_joinable.get()});
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         ffrt::wait({is_joinable.get()});
98         *is_joinable = false;
99     }
100 
~thread()101     ~thread()
102     {
103         if (joinable()) {
104             std::terminate();
105         }
106     }
107 
108 private:
109     template<class Target, size_t... Idxs>
execute(Target & tup,std::index_sequence<Idxs...>)110     static inline void execute(Target& tup,
111         std::index_sequence<Idxs...>)
112     {
113         std::invoke(std::move(std::get<Idxs>(tup))...);
114     }
115 
swap(thread & other)116     void swap(thread& other) noexcept
117     {
118         is_joinable.swap(other.is_joinable);
119     };
120     std::unique_ptr<bool> is_joinable = nullptr;
121 };
122 } // namespace ffrt
123 #endif
124