123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- #pragma once
- #if __cplusplus < 201103L
- #error "C++ version lower than C++11"
- #endif
- //#if defined(RT_USING_PTHREADS)
- #include <unistd.h>
- #include <pthread.h>
- #include <sched.h>
- #include <rtthread.h>
- #include <cstddef>
- #include <cerrno>
- #include <ostream>
- #include <functional>
- #include <utility>
- #include <chrono>
- #include <memory>
- #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> 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<thread::id>;
- friend bool operator==(thread::id x, thread::id y) noexcept;
- friend bool operator<(thread::id x, thread::id y) noexcept;
- template <class charT, class traits>
- friend basic_ostream<charT, traits>&
- operator<<(basic_ostream<charT, traits>& out, thread::id id);
- };
- thread() noexcept = default;
- thread(const thread&) = delete;
- thread& operator=(const thread&) = delete;
- ~thread();
-
- template <class F, class ...Args>
- explicit thread(F&& f, Args&&... args)
- {
- start_thread(make_invoker_ptr(std::bind(
- std::forward<F>(f),
- std::forward<Args>(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<typename Callable>
- struct invoker : public invoker_base
- {
- Callable func;
- invoker(Callable&& F) : func(std::forward<Callable>(F)) { }
- void invoke() { func(); }
- };
- template <typename Callable>
- shared_ptr<invoker<Callable>> make_invoker_ptr(Callable&& F)
- {
- return std::make_shared<invoker<Callable>>(std::forward<Callable>(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 <class charT, class traits>
- inline basic_ostream<charT, traits>&
- operator<<(basic_ostream<charT, traits>& 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<thread::id>
- {
- typedef size_t result_type;
- typedef thread::id argument_type;
- size_t operator()(const thread::id& id) const noexcept
- {
- return hash<rt_cpp_thread_t>()(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 <class Rep, class Period>
- inline void sleep_for(const chrono::duration<Rep, Period>& rel_time)
- {
- if (rel_time <= rel_time.zero()) // less than zero, no need to sleep
- return;
- auto milli_secs = chrono::duration_cast<chrono::milliseconds>(rel_time);
- // the precision is limited by rt-thread thread API
- rt_thread_mdelay(milli_secs.count());
- }
- template <class Clock, class Duration>
- inline void sleep_until(const chrono::time_point<Clock, Duration>& abs_time)
- {
- auto now = Clock::now();
- if (abs_time > now)
- sleep_for(abs_time - now);
- }
- }
- }
|