1
0

thread 5.7 KB

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