source: mainline/uspace/lib/cpp/include/__bits/thread/thread.hpp@ c6f23a7

Last change on this file since c6f23a7 was b57ba05, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 3 years ago

Update headers in C++ files

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/*
2 * SPDX-FileCopyrightText: 2018 Jaroslav Jindrak
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef LIBCPP_BITS_THREAD
8#define LIBCPP_BITS_THREAD
9
10#include <__bits/thread/threading.hpp>
11#include <chrono>
12#include <ostream>
13
14namespace std
15{
16 namespace aux
17 {
18 template<class Callable>
19 int thread_main(void*);
20
21 /**
22 * Fibrils in HelenOS are not joinable. They were
23 * in the past, but that functionality was removed from them
24 * so we created a workaround using a conditional variable that
25 * comprises the following two wrapper classes.
26 */
27 class joinable_wrapper
28 {
29 public:
30 joinable_wrapper()
31 : join_mtx_{}, join_cv_{},
32 finished_{false}, detached_{false}
33 {
34 aux::threading::mutex::init(join_mtx_);
35 aux::threading::condvar::init(join_cv_);
36 }
37
38 void join()
39 {
40 aux::threading::mutex::lock(join_mtx_);
41 while (!finished_)
42 aux::threading::condvar::wait(join_cv_, join_mtx_);
43 aux::threading::mutex::unlock(join_mtx_);
44 }
45
46 bool finished() const
47 {
48 return finished_;
49 }
50
51 void detach()
52 {
53 detached_ = true;
54 }
55
56 bool detached() const
57 {
58 return detached_;
59 }
60
61 protected:
62 aux::mutex_t join_mtx_;
63 aux::condvar_t join_cv_;
64 bool finished_;
65 bool detached_;
66 };
67
68 template<class Callable>
69 class callable_wrapper: public joinable_wrapper
70 {
71 public:
72 callable_wrapper(Callable&& clbl)
73 : joinable_wrapper{}, callable_{forward<Callable>(clbl)}
74 { /* DUMMY BODY */ }
75
76 void operator()()
77 {
78 callable_();
79
80 aux::threading::mutex::lock(join_mtx_);
81 finished_ = true;
82 aux::threading::mutex::unlock(join_mtx_);
83
84 aux::threading::condvar::broadcast(join_cv_);
85 }
86
87 private:
88 Callable callable_;
89 };
90 }
91
92 /**
93 * 30.3.1, class thread:
94 */
95
96 class thread
97 {
98 public:
99 class id;
100
101 using native_handle_type = aux::thread_t*;
102
103 /**
104 * 30.3.1.2, thread constructors:
105 * 30.3.1.3, thread destructor:
106 * 30.3.1.4, thread assignment:
107 */
108
109 thread() noexcept;
110
111 ~thread();
112
113 // TODO: check the remark in the standard
114 template<class F, class... Args>
115 explicit thread(F&& f, Args&&... args)
116 : id_{}
117 {
118 auto callable = [=](){
119 return f(forward<Args>(args)...);
120 };
121
122 auto callable_wrapper = new aux::callable_wrapper<decltype(callable)>{move(callable)};
123 joinable_wrapper_ = static_cast<aux::joinable_wrapper*>(callable_wrapper);
124
125 id_ = aux::threading::thread::create(
126 aux::thread_main<decltype(callable_wrapper)>,
127 *callable_wrapper
128 );
129
130 aux::threading::thread::start(id_);
131 // TODO: fibrils are weird here, 2 returns with same thread ids
132 }
133
134 thread(const thread&) = delete;
135 thread& operator=(const thread&) = delete;
136
137 thread(thread&& other) noexcept;
138 thread& operator=(thread&& other) noexcept;
139
140 /**
141 * 30.3.1.5, thread members:
142 */
143
144 void swap(thread& other) noexcept;
145
146 bool joinable() const noexcept;
147
148 void join();
149
150 void detach();
151
152 id get_id() const noexcept;
153
154 native_handle_type native_handle();
155
156 static unsigned hardware_concurrency() noexcept;
157
158 private:
159 aux::thread_t id_;
160 aux::joinable_wrapper* joinable_wrapper_{nullptr};
161
162 template<class Callable>
163 friend int aux::thread_main(void*);
164 };
165
166 namespace aux
167 {
168 template<class CallablePtr>
169 int thread_main(void* clbl)
170 {
171 if (!clbl)
172 return 1;
173
174 auto callable = static_cast<CallablePtr>(clbl);
175 (*callable)();
176
177 if (callable->detached())
178 delete callable;
179
180 return 0;
181 }
182 }
183
184 void swap(thread& x, thread& y) noexcept;
185
186 /**
187 * 30.3.2, namespace this_thread:
188 */
189
190 namespace this_thread
191 {
192 thread::id get_id() noexcept;
193
194 void yield() noexcept;
195
196 template<class Clock, class Duration>
197 void sleep_until(const chrono::time_point<Clock, Duration>& abs_time)
198 {
199 auto now = Clock::now();
200
201 auto time = aux::threading::time::convert(abs_time - now);
202 aux::threading::time::sleep(time);
203 }
204
205 template<class Rep, class Period>
206 void sleep_for(const chrono::duration<Rep, Period>& rel_time)
207 {
208 if (rel_time <= chrono::duration<Rep, Period>::zero())
209 return;
210
211 // TODO: timeouts?
212 auto time = aux::threading::time::convert(rel_time);
213 aux::threading::time::sleep(time);
214 }
215 }
216
217 template<class T>
218 struct hash;
219
220 class thread::id
221 {
222 public:
223 constexpr id() noexcept
224 : id_{}
225 { /* DUMMY BODY */ }
226
227 private:
228 aux::thread_t id_;
229
230 id(aux::thread_t id)
231 : id_{id}
232 { /* DUMMY BODY */ }
233
234 friend class thread;
235
236 friend bool operator==(thread::id, thread::id) noexcept;
237 friend bool operator!=(thread::id, thread::id) noexcept;
238 friend bool operator<(thread::id, thread::id) noexcept;
239 friend bool operator<=(thread::id, thread::id) noexcept;
240 friend bool operator>(thread::id, thread::id) noexcept;
241 friend bool operator>=(thread::id, thread::id) noexcept;
242
243 template<class Char, class Traits>
244 friend basic_ostream<Char, Traits>& operator<<(
245 basic_ostream<Char, Traits>&, thread::id);
246
247 friend struct hash<id>;
248
249 friend id this_thread::get_id() noexcept;
250 };
251
252 bool operator==(thread::id lhs, thread::id rhs) noexcept;
253 bool operator!=(thread::id lhs, thread::id rhs) noexcept;
254 bool operator<(thread::id lhs, thread::id rhs) noexcept;
255 bool operator<=(thread::id lhs, thread::id rhs) noexcept;
256 bool operator>(thread::id lhs, thread::id rhs) noexcept;
257 bool operator>=(thread::id lhs, thread::id rhs) noexcept;
258
259 template<class Char, class Traits>
260 basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& out, thread::id id)
261 {
262 out << id.id_;
263
264 return out;
265 }
266
267 template<> // TODO: implement
268 struct hash<thread::id>;
269}
270
271#endif
Note: See TracBrowser for help on using the repository browser.