#pragma once #if __cplusplus < 201103L #error "C++ version lower than C++11" #endif //#if defined(RT_USING_LIBC) && defined(RT_USING_PTHREADS) #include #include #include #include #include #include #include #include #include #include #include #define rt_cpp_thread_t pthread_t #ifndef PTHREAD_NUM_MAX #define PTHREAD_NUM_MAX 32 #endif #define CPP_UNJOINABLE_THREAD PTHREAD_NUM_MAX namespace std { #define __STDCPP_THREADS__ __cplusplus class thread { public: typedef rt_cpp_thread_t native_handle_type; struct invoker_base; typedef shared_ptr invoker_base_ptr; class id { // basically a wrapper around native_handle_type native_handle_type __cpp_thread_t; public: id() noexcept : __cpp_thread_t(CPP_UNJOINABLE_THREAD) {} explicit id(native_handle_type hid) : __cpp_thread_t(hid) {} private: friend class thread; friend class hash; friend bool operator==(thread::id x, thread::id y) noexcept; friend bool operator<(thread::id x, thread::id y) noexcept; template friend basic_ostream& operator<<(basic_ostream& out, thread::id id); }; thread() noexcept = default; thread(const thread&) = delete; thread& operator=(const thread&) = delete; ~thread(); template explicit thread(F&& f, Args&&... args) { start_thread(make_invoker_ptr(std::bind( std::forward(f), std::forward(args)... ))); } thread(thread&& t) noexcept { swap(t); } thread& operator=(thread&& t) noexcept { if (joinable()) terminate(); swap(t); return *this; } // member functions void swap(thread& t) noexcept { std::swap(_m_thr, t._m_thr); } bool joinable() const noexcept { return (_m_thr.__cpp_thread_t < PTHREAD_NUM_MAX); } void join(); void detach(); id get_id() const noexcept { return _m_thr; } native_handle_type native_handle() { return _m_thr.__cpp_thread_t; } // static members static unsigned hardware_concurrency() noexcept; private: id _m_thr; void start_thread(invoker_base_ptr b); public: struct invoker_base { invoker_base_ptr this_ptr; virtual ~invoker_base() = default; virtual void invoke() = 0; }; template struct invoker : public invoker_base { Callable func; invoker(Callable&& F) : func(std::forward(F)) { } void invoke() { func(); } }; template shared_ptr> make_invoker_ptr(Callable&& F) { return std::make_shared>(std::forward(F)); } }; inline void swap(thread& x, thread& y) noexcept { x.swap(y); } inline bool operator==(thread::id x, thread::id y) noexcept { // From POSIX for pthread_equal: //"If either t1 or t2 are not valid thread IDs, the behavior is undefined." return x.__cpp_thread_t == y.__cpp_thread_t; } inline bool operator!=(thread::id x, thread::id y) noexcept { return !(x == y); } inline bool operator<(thread::id x, thread::id y) noexcept { return x.__cpp_thread_t < y.__cpp_thread_t; } inline bool operator<=(thread::id x, thread::id y) noexcept { return !(y < x); } inline bool operator>(thread::id x, thread::id y) noexcept { return !(x <= y); } inline bool operator>=(thread::id x, thread::id y) noexcept { return !(x < y); } template inline basic_ostream& operator<<(basic_ostream& out, thread::id id) { if (id == thread::id()) // id is invalid, representing no pthread out << "thread::id of a non-executing thread"; else out << id.__cpp_thread_t; return out; } template <> struct hash { typedef size_t result_type; typedef thread::id argument_type; size_t operator()(const thread::id& id) const noexcept { return hash()(id.__cpp_thread_t); } }; namespace this_thread { inline thread::id get_id() noexcept { return thread::id(pthread_self()); } inline void yield() noexcept { sched_yield(); } template inline void sleep_for(const chrono::duration& rel_time) { if (rel_time <= rel_time.zero()) // less than zero, no need to sleep return; auto milli_secs = chrono::duration_cast(rel_time); // the precision is limited by rt-thread thread API rt_thread_mdelay(milli_secs.count()); } template inline void sleep_until(const chrono::time_point& abs_time) { auto now = Clock::now(); if (abs_time > now) sleep_for(abs_time - now); } } }