RTEMS 7.0-rc1
Loading...
Searching...
No Matches
thread.hpp
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-2-Clause */
2
17/*
18 * Copyright (C) 2020 Chris Johns <chris@contemporary.software>
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
30 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
33 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.
40 */
41
42#if !defined(RTEMS_THREAD_HPP)
43#define RTEMS_THREAD_HPP
44
45#include <functional>
46#include <iostream>
47#include <string>
48#include <thread>
49#include <utility>
50
51namespace rtems
52{
53 namespace thread
54 {
59 {
60 public:
69 };
70
79 };
80
86 attributes();
87
88 /*
89 * Copy construct the thread attributes.
90 *
91 * @param attr The attributes to copy.
92 */
93 attributes(const attributes& attr);
94
101 void set_name(const std::string& name);
102
109 void set_name(const char* name);
110
116 const std::string& get_name() const;
117
123 void set_priority(int priority);
124
130 int get_priority() const;
131
138 void set_stack_size(size_t size);
139
145 size_t get_stack_size() const;
146
152 void set_scheduler(const std::string& scheduler);
153
157 void set_scheduler(const char* scheduler);
158
162 const std::string& get_scheduler();
163
170
178
183
190 void commit();
191
200 void update();
201
205 attributes& operator=(const attributes& attr);
206
211 bool operator==(const attributes& attr) const;
212
213 private:
214 std::string name;
215 int priority;
216 size_t stack_size;
217 std::string scheduler;
218 sched_attr attr;
219 sched_policy policy;
220 /* affinity, cpu set size is? */
221 };
222
223 template <class T>
224 inline typename std::decay<T>::type
225 decay_copy(T&& t) {
226 return std::forward<T>(t);
227 }
228
250 class thread
251 {
252 friend void* thread_generic_entry(void* arg);
253
258 struct state_base
259 {
260 virtual ~state_base();
261 virtual const attributes get_attributes() = 0;
262 virtual void run() = 0;
263 };
264
269 using state_ptr = std::unique_ptr<state_base>;
270
271 public:
272
277 template <typename A, class DecayA = typename std::decay<A>::type>
278 using enable_if_attributes = typename std::enable_if
279 <std::is_same<DecayA, attributes>::value>::type;
280
285 class id {
286 public:
287 id() noexcept : id_(0) { }
288 explicit id(pthread_t id_) : id_(id_) { }
289 private:
290 pthread_t id_;
291
292 friend class thread;
293 friend bool operator==(thread::id l, thread::id r) noexcept;
294
295 template<class CharT, class Traits>
296 friend std::basic_ostream<CharT, Traits>&
297 operator<<(std::basic_ostream<CharT, Traits>& out, thread::id id_);
298 };
299
303 thread() noexcept = default;
304
310 template<typename F, typename... Args>
311 explicit thread(F&& func, Args&&... args);
312
317 template <typename A, typename F, typename ...Args,
318 class = enable_if_attributes<A>>
319 explicit thread(A&& attr, F&& func, Args&&... args)
320 : id_(0) {
321 start_thread(
322 make_state(attr,
323 make_invoker(decay_copy(std::forward<F>(func)),
324 decay_copy(std::forward<Args>(args))...))
325 );
326 }
327
331 thread& operator=(thread&& thread_);
332
333 void swap(thread& thread_) noexcept;
334
335 bool joinable() const noexcept;
336
337 void join();
338
339 void detach();
340
341 /*
342 * Constrain use. These are not available.
343 */
344 thread(thread&) = delete;
345 thread(const thread&) = delete;
346 thread(const thread&&) = delete;
347 thread& operator=(const thread&) = delete;
348
349 std::thread::id get_id() const noexcept;
350
351 private:
352
353 id id_;
354
360 template<typename Parms>
361 struct invoker {
362 Parms p;
363
364 template<size_t Index>
365 static std::tuple_element_t<Index, Parms>&& declval();
366
367 template<size_t... _Indexes> struct _Index_tuple { };
368
369 template<size_t _Num>
371 {
372#if __has_builtin(__make_integer_seq)
373 template<typename, size_t... _Indices>
374 using _IdxTuple = _Index_tuple<_Indices...>;
375
376 // Clang defines __make_integer_seq for this purpose.
377 using __type = __make_integer_seq<_IdxTuple, size_t, _Num>;
378#else
379 // For GCC and other compilers, use __integer_pack instead.
380 using __type = _Index_tuple<__integer_pack(_Num)...>;
381#endif
382 };
383
384 template<size_t... Ind>
385 auto invoke(_Index_tuple<Ind...>)
386 noexcept(noexcept(std::invoke(declval<Ind>()...)))
387 -> decltype(std::invoke(declval<Ind>()...)) {
388 return std::invoke(std::get<Ind>(std::move(p))...);
389 }
390
391 using indices =
392 typename _Build_index_tuple<std::tuple_size<Parms>::value>::__type;
393
394 void run() {
395 invoke(indices());
396 }
397 };
398
404 template<typename Invoker>
405 struct state : state_base {
406 const attributes attr;
407 Invoker i;
408
409 state(const attributes& attr, Invoker&& i)
410 : attr(attr),
411 i(std::forward<Invoker>(i)) {
412 }
413
414 const attributes get_attributes() override {
415 return attr;
416 }
417
418 void run() override {
419 i.run();
420 }
421 };
422
427 template<typename Invoker>
428 static state_ptr
429 make_state(const attributes& attr, Invoker&& i) {
430 using state_impl = state<Invoker>;
431 return state_ptr{ new state_impl(attr, std::forward<Invoker>(i)) };
432 }
433
438 template<typename... T>
439 using decayed_tuple = std::tuple<typename std::decay<T>::type...>;
440
444 template<typename F, typename... Args>
445 static invoker<decayed_tuple<F, Args...>>
446 make_invoker(F&& func, Args&&... args)
447 {
448 return {
449 decayed_tuple<F, Args...> {
450 std::forward<F>(func), std::forward<Args>(args)...
451 }
452 };
453 }
454
458 void start_thread(state_ptr s);
459 };
460
461 template<typename F, typename... Args>
462 thread::thread(F&& func, Args&&... args)
463 : id_(0) {
464 attributes attr;
465 start_thread(
466 make_state(attr,
467 make_invoker(decay_copy(std::forward<F>(func)),
468 decay_copy(std::forward<Args>(args))...))
469 );
470 }
471
472 inline std::thread::id thread::get_id() const noexcept {
473#ifdef __clang__
474 /* clang does not allow construction of std::thread::id with
475 an id so fail this call */
476 return std::thread::id();
477#else
478 return std::thread::id(id_.id_);
479#endif
480 }
481
482 inline bool
483 operator==(thread::id l, thread::id r) noexcept {
484 return l.id_ == r.id_;
485 }
486
487 inline bool
488 operator!=(thread::id l, thread::id r) noexcept {
489 return !(l == r);
490 }
491
492 template<class C, class T>
493 inline std::basic_ostream<C, T>&
494 operator<<(std::basic_ostream<C, T>& out, thread::id id_) {
495#ifdef __clang__
496 return out << id_.id_;
497#else
498 return out << std::thread::id(id_.id_);
499#endif
500 }
501 };
502};
503
504#endif
Manage the attributes of a thread.
Definition: thread.hpp:59
sched_policy
Definition: thread.hpp:74
@ sched_other
Definition: thread.hpp:75
@ sched_sporadic
Definition: thread.hpp:78
@ sched_roundrobin
Definition: thread.hpp:77
@ sched_fifo
Definition: thread.hpp:76
const std::string & get_scheduler()
Definition: thread.cpp:158
attributes()
Definition: thread.cpp:84
void set_name(const std::string &name)
Definition: thread.cpp:104
void set_scheduler(const std::string &scheduler)
Definition: thread.cpp:146
void set_scheduler_policy(sched_policy policy)
Definition: thread.cpp:170
void set_priority(int priority)
Definition: thread.cpp:122
sched_policy get_scheduler_policy() const
Definition: thread.cpp:177
sched_attr
Definition: thread.hpp:64
@ sched_explicit
Definition: thread.hpp:67
@ sched_inherit
Definition: thread.hpp:65
void update()
Definition: thread.cpp:248
const std::string & get_name() const
Definition: thread.cpp:116
void set_stack_size(size_t size)
Definition: thread.cpp:134
bool operator==(const attributes &attr) const
Definition: thread.cpp:340
size_t get_stack_size() const
Definition: thread.cpp:140
int get_priority() const
Definition: thread.cpp:128
sched_attr get_scheduler_attr() const
Definition: thread.cpp:164
void commit()
Definition: thread.cpp:183
attributes & operator=(const attributes &attr)
Definition: thread.cpp:329
Definition: thread.hpp:285
Create a thread with thread attributes.
Definition: thread.hpp:251
thread() noexcept=default
thread & operator=(thread &&thread_)
Definition: thread.cpp:363
typename std::enable_if< std::is_same< DecayA, attributes >::value >::type enable_if_attributes
Definition: thread.hpp:279