1#pragma once 2 3#if __cplusplus < 201103L 4#error "C++ version lower than C++11" 5#endif 6 7//#if defined(RT_USING_PTHREADS) 8 9#include <unistd.h> 10#include <pthread.h> 11#include <sched.h> 12#include <rtthread.h> 13 14#include <cstddef> 15#include <cerrno> 16#include <ostream> 17#include <functional> 18#include <utility> 19#include <chrono> 20#include <memory> 21 22#define rt_cpp_thread_t pthread_t 23#ifndef PTHREAD_NUM_MAX 24#define PTHREAD_NUM_MAX 32 25#endif 26#define CPP_UNJOINABLE_THREAD PTHREAD_NUM_MAX 27 28namespace std 29{ 30 #define __STDCPP_THREADS__ __cplusplus 31 32 33 34 class thread 35 { 36 public: 37 typedef rt_cpp_thread_t native_handle_type; 38 39 struct invoker_base; 40 typedef shared_ptr<invoker_base> invoker_base_ptr; 41 42 class id 43 { 44 // basically a wrapper around native_handle_type 45 native_handle_type __cpp_thread_t; 46 47 public: 48 id() noexcept : __cpp_thread_t(CPP_UNJOINABLE_THREAD) {} 49 50 explicit id(native_handle_type hid) 51 : __cpp_thread_t(hid) {} 52 private: 53 friend class thread; 54 friend class hash<thread::id>; 55 56 friend bool operator==(thread::id x, thread::id y) noexcept; 57 58 friend bool operator<(thread::id x, thread::id y) noexcept; 59 60 template <class charT, class traits> 61 friend basic_ostream<charT, traits>& 62 operator<<(basic_ostream<charT, traits>& out, thread::id id); 63 }; 64 65 thread() noexcept = default; 66 thread(const thread&) = delete; 67 thread& operator=(const thread&) = delete; 68 ~thread(); 69 70 template <class F, class ...Args> 71 explicit thread(F&& f, Args&&... args) 72 { 73 start_thread(make_invoker_ptr(std::bind( 74 std::forward<F>(f), 75 std::forward<Args>(args)... 76 ))); 77 } 78 79 thread(thread&& t) noexcept 80 { 81 swap(t); 82 } 83 84 thread& operator=(thread&& t) noexcept 85 { 86 if (joinable()) 87 terminate(); 88 swap(t); 89 return *this; 90 } 91 92 // member functions 93 void swap(thread& t) noexcept 94 { 95 std::swap(_m_thr, t._m_thr); 96 } 97 98 bool joinable() const noexcept 99 { 100 return (_m_thr.__cpp_thread_t < PTHREAD_NUM_MAX); 101 } 102 103 void join(); 104 105 void detach(); 106 107 id get_id() const noexcept { return _m_thr; } 108 109 native_handle_type native_handle() { return _m_thr.__cpp_thread_t; } 110 111 // static members 112 static unsigned hardware_concurrency() noexcept; 113 114 private: 115 id _m_thr; 116 117 void start_thread(invoker_base_ptr b); 118 public: 119 struct invoker_base 120 { 121 invoker_base_ptr this_ptr; 122 123 virtual ~invoker_base() = default; 124 125 virtual void invoke() = 0; 126 }; 127 128 129 template<typename Callable> 130 struct invoker : public invoker_base 131 { 132 Callable func; 133 134 invoker(Callable&& F) : func(std::forward<Callable>(F)) { } 135 136 void invoke() { func(); } 137 }; 138 139 template <typename Callable> 140 shared_ptr<invoker<Callable>> make_invoker_ptr(Callable&& F) 141 { 142 return std::make_shared<invoker<Callable>>(std::forward<Callable>(F)); 143 } 144 145 146 }; 147 148 inline void swap(thread& x, thread& y) noexcept 149 { 150 x.swap(y); 151 } 152 153 154 inline bool operator==(thread::id x, thread::id y) noexcept 155 { 156 // From POSIX for pthread_equal: 157 //"If either t1 or t2 are not valid thread IDs, the behavior is undefined." 158 return x.__cpp_thread_t == y.__cpp_thread_t; 159 } 160 161 inline bool operator!=(thread::id x, thread::id y) noexcept 162 { 163 return !(x == y); 164 } 165 166 inline bool operator<(thread::id x, thread::id y) noexcept 167 { 168 return x.__cpp_thread_t < y.__cpp_thread_t; 169 } 170 171 inline bool operator<=(thread::id x, thread::id y) noexcept 172 { 173 return !(y < x); 174 } 175 176 inline bool operator>(thread::id x, thread::id y) noexcept 177 { 178 return !(x <= y); 179 } 180 181 inline bool operator>=(thread::id x, thread::id y) noexcept 182 { 183 return !(x < y); 184 } 185 186 template <class charT, class traits> 187 inline basic_ostream<charT, traits>& 188 operator<<(basic_ostream<charT, traits>& out, thread::id id) 189 { 190 if (id == thread::id()) // id is invalid, representing no pthread 191 out << "thread::id of a non-executing thread"; 192 else 193 out << id.__cpp_thread_t; 194 return out; 195 } 196 197 template <> 198 struct hash<thread::id> 199 { 200 typedef size_t result_type; 201 typedef thread::id argument_type; 202 size_t operator()(const thread::id& id) const noexcept 203 { 204 return hash<rt_cpp_thread_t>()(id.__cpp_thread_t); 205 } 206 }; 207 208 namespace this_thread 209 { 210 inline thread::id get_id() noexcept 211 { 212 return thread::id(pthread_self()); 213 } 214 215 inline void yield() noexcept 216 { 217 sched_yield(); 218 } 219 220 template <class Rep, class Period> 221 inline void sleep_for(const chrono::duration<Rep, Period>& rel_time) 222 { 223 if (rel_time <= rel_time.zero()) // less than zero, no need to sleep 224 return; 225 auto milli_secs = chrono::duration_cast<chrono::milliseconds>(rel_time); 226 // the precision is limited by rt-thread thread API 227 rt_thread_mdelay(milli_secs.count()); 228 } 229 230 template <class Clock, class Duration> 231 inline void sleep_until(const chrono::time_point<Clock, Duration>& abs_time) 232 { 233 auto now = Clock::now(); 234 if (abs_time > now) 235 sleep_for(abs_time - now); 236 } 237 238 } 239} 240