diff options
| author | liukangcc <[email protected]> | 2021-09-03 11:38:48 +0800 |
|---|---|---|
| committer | liukangcc <[email protected]> | 2021-09-16 09:51:33 +0800 |
| commit | a3541b2a243bdf1cc49029b696b217ce752199c7 (patch) | |
| tree | ed7bd0398a322fb597938f3fb476909a7cc66606 /components/cplusplus/cpp11/gcc/thread | |
| parent | dca7dcb42a44249abbe6c36ce2a69355e60d1f79 (diff) | |
[update] support armclang and c++11.
Diffstat (limited to 'components/cplusplus/cpp11/gcc/thread')
| -rw-r--r-- | components/cplusplus/cpp11/gcc/thread | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/components/cplusplus/cpp11/gcc/thread b/components/cplusplus/cpp11/gcc/thread new file mode 100644 index 0000000000..5b64decd6a --- /dev/null +++ b/components/cplusplus/cpp11/gcc/thread @@ -0,0 +1,239 @@ +#pragma once + +#if __cplusplus < 201103L +#error "C++ version lower than C++11" +#endif + +//#if defined(RT_USING_LIBC) && 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); + } + + } +} |
