summaryrefslogtreecommitdiff
path: root/components/cplusplus/cpp11/gcc/thread
diff options
context:
space:
mode:
authorliukangcc <[email protected]>2021-09-03 11:38:48 +0800
committerliukangcc <[email protected]>2021-09-16 09:51:33 +0800
commita3541b2a243bdf1cc49029b696b217ce752199c7 (patch)
treeed7bd0398a322fb597938f3fb476909a7cc66606 /components/cplusplus/cpp11/gcc/thread
parentdca7dcb42a44249abbe6c36ce2a69355e60d1f79 (diff)
[update] support armclang and c++11.
Diffstat (limited to 'components/cplusplus/cpp11/gcc/thread')
-rw-r--r--components/cplusplus/cpp11/gcc/thread239
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);
+ }
+
+ }
+}