• 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 <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