source: mainline/uspace/lib/cpp/include/impl/thread.hpp@ a1c35cc

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a1c35cc was de53138, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: revamped c header wrappers, now only include standard symbols, others are in std::hel, fixed some bugs

  • Property mode set to 100644
File size: 8.5 KB
RevLine 
[ad403590]1/*
2 * Copyright (c) 2017 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_THREAD
30#define LIBCPP_THREAD
31
32#include <chrono>
33#include <internal/common.hpp>
[9283830]34#include <internal/thread.hpp>
[ad403590]35#include <ostream>
36
37namespace std
38{
[48d9187]39 namespace aux
40 {
41 template<class Callable>
42 int thread_main(void*);
43
44 /**
45 * Fibrils in HelenOS are not joinable. They were
46 * in the past, but that functionality was removed from them
47 * so we created a workaround using a conditional variable that
48 * comprises the following two wrapper classes.
49 */
50 class joinable_wrapper
51 {
52 public:
53 joinable_wrapper()
54 : join_mtx_{}, join_cv_{},
55 finished_{false}, detached_{false}
56 {
[9283830]57 aux::threading::mutex::init(join_mtx_);
58 aux::threading::condvar::init(join_cv_);
[48d9187]59 }
60
61 void join()
62 {
[9283830]63 aux::threading::mutex::lock(join_mtx_);
[48d9187]64 while (!finished_)
[9283830]65 aux::threading::condvar::wait(join_cv_, join_mtx_);
66 aux::threading::mutex::unlock(join_mtx_);
[48d9187]67 }
68
69 bool finished() const
70 {
71 return finished_;
72 }
73
74 void detach()
75 {
76 detached_ = true;
77 }
78
79 bool detached() const
80 {
81 return detached_;
82 }
83
84 protected:
[9283830]85 aux::mutex_t join_mtx_;
86 aux::condvar_t join_cv_;
[48d9187]87 bool finished_;
88 bool detached_;
89 };
90
91 template<class Callable>
92 class callable_wrapper: public joinable_wrapper
93 {
94 public:
95 callable_wrapper(Callable&& clbl)
96 : joinable_wrapper{}, callable_{forward<Callable>(clbl)}
97 { /* DUMMY BODY */ }
98
99 void operator()()
100 {
101 callable_();
102
[9283830]103 aux::threading::mutex::lock(join_mtx_);
[48d9187]104 finished_ = true;
[9283830]105 aux::threading::mutex::unlock(join_mtx_);
[48d9187]106
[9283830]107 aux::threading::condvar::broadcast(join_cv_);
[48d9187]108 }
109
110 private:
111 Callable callable_;
112 };
113 }
114
[ad403590]115 /**
116 * 30.3.1, class thread:
117 */
118
119 class thread
120 {
121 public:
122 class id;
123
[9283830]124 using native_handle_type = aux::thread_t*;
[ad403590]125
126 /**
127 * 30.3.1.2, thread constructors:
128 * 30.3.1.3, thread destructor:
129 * 30.3.1.4, thread assignment:
130 */
131
132 thread() noexcept;
133
134 ~thread();
135
136 // TODO: check the remark in the standard
137 template<class F, class... Args>
138 explicit thread(F&& f, Args&&... args)
[48d9187]139 : id_{}
[ad403590]140 {
[4e484b5]141 auto callable = [=](){
[48d9187]142 return f(forward<Args>(args)...);
143 };
144
145 auto callable_wrapper = new aux::callable_wrapper<decltype(callable)>{move(callable)};
146 joinable_wrapper_ = static_cast<aux::joinable_wrapper*>(callable_wrapper);
147
[9283830]148 id_ = aux::threading::thread::create(
149 aux::thread_main<decltype(callable_wrapper)>,
150 *callable_wrapper
[48d9187]151 );
[9283830]152
153 aux::threading::thread::start(id_);
154 // TODO: fibrils are weird here, 2 returns with same thread ids
[ad403590]155 }
156
157 thread(const thread&) = delete;
158 thread& operator=(const thread&) = delete;
159
160 thread(thread&& other) noexcept;
161 thread& operator=(thread&& other) noexcept;
162
163 /**
164 * 30.3.1.5, thread members:
165 */
166
167 void swap(thread& other) noexcept;
168
169 bool joinable() const noexcept;
170
171 void join();
172
173 void detach();
174
175 id get_id() const noexcept;
176
177 native_handle_type native_handle();
178
179 static unsigned hardware_concurrency() noexcept;
180
181 private:
[9283830]182 aux::thread_t id_;
[48d9187]183 aux::joinable_wrapper* joinable_wrapper_{nullptr};
184
185 template<class Callable>
186 friend int aux::thread_main(void*);
[ad403590]187 };
188
[48d9187]189 namespace aux
190 {
191 template<class CallablePtr>
192 int thread_main(void* clbl)
193 {
194 if (!clbl)
195 return 1;
196
197 auto callable = static_cast<CallablePtr>(clbl);
198 (*callable)();
199
[063e0626]200 if (callable->detached())
[48d9187]201 delete callable;
202
203 return 0;
204 }
205 }
206
[ad403590]207 void swap(thread& x, thread& y) noexcept;
208
209 /**
210 * 30.3.2, namespace this_thread:
211 */
212
213 namespace this_thread
214 {
215 thread::id get_id() noexcept;
216
217 void yield() noexcept;
218
219 template<class Clock, class Duration>
220 void sleep_until(const chrono::time_point<Clock, Duration>& abs_time)
221 {
222 auto now = Clock::now();
223
[9283830]224 auto time = aux::threading::time::convert(abs_time - now);
225 aux::threading::time::sleep(time);
[ad403590]226 }
227
228 template<class Rep, class Period>
229 void sleep_for(const chrono::duration<Rep, Period>& rel_time)
230 {
231 if (rel_time <= chrono::duration<Rep, Period>::zero())
232 return;
233
234 // TODO: timeouts?
[9283830]235 auto time = aux::threading::time::convert(rel_time);
236 aux::threading::time::sleep(time);
[ad403590]237 }
238 }
239
240 template<class T>
241 struct hash;
242
243 class thread::id
244 {
245 public:
[5e5498e]246 constexpr id() noexcept
[ad403590]247 : id_{}
248 { /* DUMMY BODY */ }
249
250 private:
[de53138]251 aux::thread_t id_;
252
253 id(aux::thread_t id)
[ad403590]254 : id_{id}
255 { /* DUMMY BODY */ }
256
257 friend class thread;
258
259 friend bool operator==(thread::id, thread::id) noexcept;
260 friend bool operator!=(thread::id, thread::id) noexcept;
261 friend bool operator<(thread::id, thread::id) noexcept;
262 friend bool operator<=(thread::id, thread::id) noexcept;
263 friend bool operator>(thread::id, thread::id) noexcept;
264 friend bool operator>=(thread::id, thread::id) noexcept;
265
266 template<class Char, class Traits>
267 friend basic_ostream<Char, Traits>& operator<<(
268 basic_ostream<Char, Traits>&, thread::id);
269
270 friend struct hash<id>;
271
272 friend id this_thread::get_id() noexcept;
273 };
274
275 bool operator==(thread::id lhs, thread::id rhs) noexcept;
276 bool operator!=(thread::id lhs, thread::id rhs) noexcept;
277 bool operator<(thread::id lhs, thread::id rhs) noexcept;
278 bool operator<=(thread::id lhs, thread::id rhs) noexcept;
279 bool operator>(thread::id lhs, thread::id rhs) noexcept;
280 bool operator>=(thread::id lhs, thread::id rhs) noexcept;
281
282 template<class Char, class Traits>
283 basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& out, thread::id id)
284 {
285 out << id.id_;
286
287 return out;
288 }
289
290 template<> // TODO: implement
291 struct hash<thread::id>;
292}
293
294#endif
Note: See TracBrowser for help on using the repository browser.