添加rtthread相关代码
This commit is contained in:
		
							
								
								
									
										57
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/__utils.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										57
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/__utils.h
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| /* | ||||
|  * Copyright (c) 2006-2021, RT-Thread Development Team | ||||
|  * | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  * | ||||
|  * Change Logs: | ||||
|  * Date           Author       Notes | ||||
|  * 2021-04-27     flybreak     the first version. | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <cstdlib> | ||||
| #include <system_error> | ||||
| #include <chrono> | ||||
| #include <ratio> | ||||
|  | ||||
| #include <rtthread.h> | ||||
|  | ||||
| inline void throw_system_error(int err, const char *what_msg) | ||||
| { | ||||
| #ifdef RT_USING_CPP_EXCEPTIONS | ||||
|     throw std::system_error(std::error_code(err, std::system_category()), what_msg); | ||||
| #else | ||||
|     (void)err; | ||||
|     (void)what_msg; | ||||
|     ::abort(); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| class tick_clock | ||||
| { | ||||
| public: | ||||
|     typedef clock_t rep; | ||||
|     typedef std::ratio<1, RT_TICK_PER_SECOND> period; | ||||
|  | ||||
|     typedef std::chrono::duration<tick_clock::rep, tick_clock::period> duration; | ||||
|     typedef std::chrono::time_point<tick_clock> time_point; | ||||
|  | ||||
|     constexpr static bool is_ready = true; | ||||
|  | ||||
|     static time_point now(); | ||||
| }; | ||||
|  | ||||
| class real_time_clock | ||||
| { | ||||
| public: | ||||
|     typedef std::chrono::nanoseconds duration; | ||||
|     typedef duration::rep rep; | ||||
|     typedef duration::period period; | ||||
|     typedef std::chrono::time_point<real_time_clock, duration> time_point; | ||||
|  | ||||
|     static constexpr bool is_steady = true; | ||||
|  | ||||
|     static time_point | ||||
|     now() noexcept; | ||||
| }; | ||||
							
								
								
									
										222
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/condition_variable
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										222
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/condition_variable
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,222 @@ | ||||
| #pragma once | ||||
|  | ||||
| #if __cplusplus < 201103L | ||||
| #error "C++ version lower than C++11" | ||||
| #endif | ||||
|  | ||||
| #include <pthread.h> | ||||
|  | ||||
| #include <system_error> | ||||
| #include <chrono> | ||||
| #include <utility> | ||||
| #include <functional> | ||||
| #include <memory> | ||||
|  | ||||
| #include "__utils.h" | ||||
| #include "mutex" | ||||
|  | ||||
| #define rt_cpp_cond_var pthread_cond_t | ||||
|  | ||||
| namespace std | ||||
| { | ||||
|  | ||||
|     enum class cv_status | ||||
|     { | ||||
|         no_timeout, | ||||
|         timeout | ||||
|     }; | ||||
|  | ||||
|     class condition_variable | ||||
|     { | ||||
|     public: | ||||
|         typedef rt_cpp_cond_var *native_handle_type; | ||||
|  | ||||
|         condition_variable(const condition_variable &) = delete; | ||||
|         condition_variable &operator=(const condition_variable &) = delete; | ||||
|  | ||||
|         condition_variable() = default; | ||||
|  | ||||
|         ~condition_variable() | ||||
|         { | ||||
|             pthread_cond_destroy(&_m_cond); | ||||
|         } | ||||
|  | ||||
|         void wait(unique_lock<mutex> &lock); | ||||
|  | ||||
|         void notify_one() noexcept | ||||
|         { | ||||
|             pthread_cond_signal(&_m_cond); | ||||
|         } | ||||
|  | ||||
|         void notify_all() noexcept | ||||
|         { | ||||
|             pthread_cond_broadcast(&_m_cond); | ||||
|         } | ||||
|  | ||||
|         template <class Predicate> | ||||
|         void wait(unique_lock<mutex> &lock, Predicate pred) | ||||
|         { | ||||
|             while (!pred()) | ||||
|                 wait(lock); | ||||
|         } | ||||
|  | ||||
|         template <class Clock, class Duration> | ||||
|         cv_status wait_until(unique_lock<mutex> &lock, | ||||
|                              const chrono::time_point<Clock, Duration> &abs_time) | ||||
|         { | ||||
|             if (!lock.owns_lock()) | ||||
|                 throw_system_error((int)errc::operation_not_permitted, | ||||
|                                    "condition_variable::wailt_until: waiting on unlocked lock"); | ||||
|             auto secs = chrono::time_point_cast<chrono::seconds>(abs_time); | ||||
|             auto nano_secs = chrono::duration_cast<chrono::nanoseconds>(abs_time - secs); | ||||
|  | ||||
|             struct timespec c_abs_time = {static_cast<time_t>(secs.time_since_epoch().count()), | ||||
|                                           static_cast<long>(nano_secs.count())}; | ||||
|  | ||||
|             pthread_cond_timedwait(&_m_cond, lock.mutex()->native_handle(), &c_abs_time); | ||||
|  | ||||
|             return (Clock::now() < abs_time) ? cv_status::no_timeout : cv_status::timeout; | ||||
|         } | ||||
|  | ||||
|         template <class Clock, class Duration, class Predicate> | ||||
|         bool wait_until(unique_lock<mutex> &lock, | ||||
|                         const chrono::time_point<Clock, Duration> &abs_time, | ||||
|                         Predicate pred) | ||||
|         { | ||||
|             while (!pred()) | ||||
|                 if (wait_until(lock, abs_time) == cv_status::timeout) | ||||
|                     return pred(); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         template <class Rep, class Period> | ||||
|         cv_status wait_for(unique_lock<mutex> &lock, | ||||
|                            const chrono::duration<Rep, Period> &rel_time) | ||||
|         { | ||||
|             return wait_until(lock, real_time_clock::now() + rel_time); | ||||
|         } | ||||
|  | ||||
|         template <class Rep, class Period, class Predicate> | ||||
|         bool wait_for(unique_lock<mutex> &lock, | ||||
|                       const chrono::duration<Rep, Period> &rel_time, | ||||
|                       Predicate pred) | ||||
|         { | ||||
|             return wait_until(lock, real_time_clock::now() + rel_time, std::move(pred)); | ||||
|         } | ||||
|  | ||||
|         native_handle_type native_handle() | ||||
|         { | ||||
|             return &_m_cond; | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|         rt_cpp_cond_var _m_cond = PTHREAD_COND_INITIALIZER; | ||||
|     }; | ||||
|  | ||||
|     // Lockable is only required to have `lock()` and `unlock()` | ||||
|     class condition_variable_any | ||||
|     { | ||||
|     private: | ||||
|         condition_variable _m_cond; | ||||
|         shared_ptr<mutex> _m_mtx; | ||||
|  | ||||
|         // so that Lockable automatically unlocks when waiting and locks after waiting | ||||
|         template <class Lockable> | ||||
|         struct unlocker | ||||
|         { | ||||
|             Lockable &_m_lock; | ||||
|  | ||||
|             explicit unlocker(Lockable &lk) | ||||
|                 : _m_lock(lk) | ||||
|             { | ||||
|                 _m_lock.unlock(); | ||||
|             } | ||||
|  | ||||
|             ~unlocker() | ||||
|             { | ||||
|                 _m_lock.lock(); | ||||
|             } | ||||
|  | ||||
|             unlocker(const unlocker &) = delete; | ||||
|             unlocker &operator=(const unlocker &) = delete; | ||||
|         }; | ||||
|  | ||||
|     public: | ||||
|         condition_variable_any() : _m_mtx(std::make_shared<mutex>()) {} | ||||
|         ~condition_variable_any() = default; | ||||
|  | ||||
|         condition_variable_any(const condition_variable_any &) = delete; | ||||
|         condition_variable_any &operator=(const condition_variable_any &) = delete; | ||||
|  | ||||
|         void notify_one() noexcept | ||||
|         { | ||||
|             lock_guard<mutex> lk(*_m_mtx); | ||||
|             _m_cond.notify_one(); | ||||
|         } | ||||
|  | ||||
|         void notify_all() noexcept | ||||
|         { | ||||
|             lock_guard<mutex> lk(*_m_mtx); | ||||
|             _m_cond.notify_all(); | ||||
|         } | ||||
|  | ||||
|         template <class Lock> | ||||
|         void wait(Lock &lock) | ||||
|         { | ||||
|             shared_ptr<mutex> mut = _m_mtx; | ||||
|             unique_lock<mutex> lk(*mut); | ||||
|             unlocker<Lock> auto_lk(lock); // unlock here | ||||
|  | ||||
|             unique_lock<mutex> lk2(std::move(lk)); | ||||
|             _m_cond.wait(lk2); | ||||
|         } // mut.unlock(); lock.lock(); | ||||
|  | ||||
|         template <class Lock, class Predicate> | ||||
|         void wait(Lock &lock, Predicate pred) | ||||
|         { | ||||
|             while (!pred()) | ||||
|                 wait(lock); | ||||
|         } | ||||
|  | ||||
|         template <class Lock, class Clock, class Duration> | ||||
|         cv_status wait_until(Lock &lock, | ||||
|                              const chrono::time_point<Clock, Duration> &abs_time) | ||||
|         { | ||||
|             shared_ptr<mutex> mut = _m_mtx; | ||||
|             unique_lock<mutex> lk(*mut); | ||||
|             unlocker<Lock> auto_lk(lock); // unlock here | ||||
|  | ||||
|             unique_lock<mutex> lk2(std::move(lk)); | ||||
|             return _m_cond.wait_until(lk2, abs_time); | ||||
|         } | ||||
|  | ||||
|         template <class Lock, class Clock, class Duration, class Predicate> | ||||
|         bool wait_until(Lock &lock, | ||||
|                         const chrono::time_point<Clock, Duration> &abs_time, | ||||
|                         Predicate pred) | ||||
|         { | ||||
|             while (!pred()) | ||||
|                 if (wait_until(lock, abs_time) == cv_status::timeout) | ||||
|                     return pred(); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         template <class Lock, class Rep, class Period> | ||||
|         cv_status wait_for(Lock &lock, | ||||
|                            const chrono::duration<Rep, Period> &rel_time) | ||||
|         { | ||||
|             return wait_until(lock, real_time_clock::now() + rel_time); | ||||
|         } | ||||
|  | ||||
|         template <class Lock, class Rep, class Period, class Predicate> | ||||
|         bool wait_for(Lock &lock, | ||||
|                       const chrono::duration<Rep, Period> &rel_time, | ||||
|                       Predicate pred) | ||||
|         { | ||||
|             return wait_until(lock, real_time_clock::now() + rel_time, std::move(pred)); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     void notify_all_at_thread_exit(condition_variable &cond, unique_lock<mutex> lk); | ||||
|  | ||||
| } // namespace std | ||||
							
								
								
									
										34
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/condition_variable.cpp
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										34
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/condition_variable.cpp
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| /* | ||||
|  * Copyright (c) 2006-2021, RT-Thread Development Team | ||||
|  * | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  * | ||||
|  * Change Logs: | ||||
|  * Date           Author       Notes | ||||
|  * 2021-04-27     flybreak     the first version. | ||||
|  */ | ||||
|  | ||||
| #include "condition_variable" | ||||
|  | ||||
| namespace std | ||||
| { | ||||
|     void condition_variable::wait(unique_lock<mutex>& lock) | ||||
|     { | ||||
|         int err = pthread_cond_wait(&_m_cond, lock.mutex()->native_handle()); | ||||
|  | ||||
|         if (err) | ||||
|         { | ||||
|             throw_system_error(err, "condition_variable::wait: failed to wait on a condition"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk) | ||||
|     { | ||||
|         // TLS currently not available | ||||
|         mutex* mut = lk.release(); | ||||
|         mut->unlock(); | ||||
|         cond.notify_all(); | ||||
|     } | ||||
|  | ||||
|  | ||||
| } // namespace std | ||||
							
								
								
									
										336
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/future
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										336
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/future
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,336 @@ | ||||
| #pragma once | ||||
|  | ||||
| #if __cplusplus < 201103L | ||||
| #error "C++ version lower than C++11" | ||||
| #endif | ||||
|  | ||||
| #include <mutex> | ||||
| #include <condition_variable> | ||||
| #include <memory> | ||||
| #include <chrono> | ||||
| #include <cassert> | ||||
|  | ||||
| namespace std { | ||||
|  | ||||
| enum class future_status { | ||||
|     ready, | ||||
|     timeout, | ||||
|     deferred | ||||
| }; | ||||
|  | ||||
| namespace detail { | ||||
|  | ||||
| class shared_state_base { | ||||
| protected: | ||||
|     typedef void (*deleter_fn)(void *v); | ||||
|  | ||||
|     using scoped_lock = std::lock_guard<std::mutex>; | ||||
|     using unique_lock = std::unique_lock<std::mutex>; | ||||
| public: | ||||
|     explicit shared_state_base(deleter_fn d) : v_(nullptr), d_(d), valid_(true) {} | ||||
|  | ||||
|     ~shared_state_base() { d_(v_); } | ||||
|  | ||||
|     shared_state_base(shared_state_base &&other) = delete; | ||||
|  | ||||
|     shared_state_base(const shared_state_base &other) = delete; | ||||
|  | ||||
|     shared_state_base &operator=(shared_state_base &&other) = delete; | ||||
|  | ||||
|     shared_state_base &operator=(const shared_state_base &other) = delete; | ||||
|  | ||||
|     void wait() { | ||||
|         unique_lock lock(m_); | ||||
|         c_.wait(lock, [this] { return has_value(); }); | ||||
|     } | ||||
|  | ||||
|     template <class Rep, class Period> | ||||
|     std::future_status | ||||
|     wait_for(const std::chrono::duration<Rep, Period> &rel_time) { | ||||
|         unique_lock lock(m_); | ||||
|         if (c_.wait_for(lock, rel_time, [this] { return has_value(); })) { | ||||
|             return std::future_status::ready; | ||||
|         } | ||||
|         return std::future_status::timeout; | ||||
|     } | ||||
|  | ||||
|     template <class Clock, class Duration> | ||||
|     std::future_status | ||||
|     wait_until(const std::chrono::time_point<Clock, Duration> &abs_time) { | ||||
|         unique_lock lock(m_); | ||||
|         if (c_.wait_until(lock, abs_time, [this] { return has_value(); })) { | ||||
|             return std::future_status::ready; | ||||
|         } | ||||
|         return std::future_status::timeout; | ||||
|     } | ||||
|  | ||||
| protected: | ||||
|     bool has_value() { return v_ != nullptr; } | ||||
|  | ||||
| protected: | ||||
|     std::mutex m_; | ||||
|     std::condition_variable c_; | ||||
|     void *v_; | ||||
|     deleter_fn d_; | ||||
|     bool valid_; | ||||
| }; | ||||
|  | ||||
|  | ||||
| template <typename R> | ||||
| class shared_state: public shared_state_base { | ||||
| public: | ||||
|     shared_state() :shared_state_base(default_deleter_) {} | ||||
|  | ||||
|     ~shared_state() {} | ||||
|  | ||||
|     R &get() { | ||||
|         wait(); | ||||
|         scoped_lock lock(m_); | ||||
|         assert(valid_); | ||||
|         valid_ = false; | ||||
|         return *(static_cast<R *>(v_)); | ||||
|     } | ||||
|  | ||||
|     void set(const R &v) { | ||||
|         scoped_lock lock(m_); | ||||
|         assert(!has_value()); | ||||
|         v_ = new R(v); | ||||
|         valid_ = true; | ||||
|         c_.notify_one(); | ||||
|     } | ||||
|  | ||||
|     void set(R &&v) { | ||||
|         scoped_lock lock(m_); | ||||
|         assert(!has_value()); | ||||
|         v_ = new R(std::move(v)); | ||||
|         valid_ = true; | ||||
|         c_.notify_one(); | ||||
|     } | ||||
|  | ||||
|     bool valid() { | ||||
|         scoped_lock lock(m_); | ||||
|         return valid_; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     static void default_deleter_(void *v) { delete static_cast<R *>(v); } | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| template <typename R> | ||||
| class shared_future { | ||||
| }; | ||||
|  | ||||
|  | ||||
| template <typename R> | ||||
| class future { | ||||
|     using state_type = std::shared_ptr<detail::shared_state<R>>; | ||||
| public: | ||||
|     future() {} | ||||
|  | ||||
|     explicit future(const state_type &state) : state_(state) {} | ||||
|  | ||||
|     future(future &&other) noexcept: state_(std::move(other.state_)) { | ||||
|         other.state_.reset(); | ||||
|     } | ||||
|  | ||||
|     future(const future &other) = delete; | ||||
|  | ||||
|     ~future() {} | ||||
|  | ||||
|     future &operator=(future &&other) noexcept { | ||||
|         if (&other != this) { | ||||
|             state_ = std::move(other.state_); | ||||
|             other.state_.reset(); | ||||
|         } | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     future &operator=(const future &other) = delete; | ||||
|  | ||||
|     void swap(future &other) noexcept { | ||||
|         std::swap(state_, other.state_); | ||||
|     } | ||||
|  | ||||
|     std::shared_future<R> share() noexcept { return std::shared_future<R>(); } | ||||
|  | ||||
|     R get() { return state_->get(); } | ||||
|  | ||||
|     bool valid() const noexcept { return state_->valid(); } | ||||
|  | ||||
|     void wait() const { state_->wait(); } | ||||
|  | ||||
|     template <class Rep, class Period> | ||||
|     std::future_status | ||||
|     wait_for(const std::chrono::duration<Rep, Period> &rel_time) const { | ||||
|         return state_->wait_for(rel_time); | ||||
|     } | ||||
|  | ||||
|     template <class Clock, class Duration> | ||||
|     std::future_status | ||||
|     wait_until(const std::chrono::time_point<Clock, Duration> &abs_time) const { | ||||
|         return state_->wait_until(abs_time); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     state_type state_; | ||||
| }; | ||||
|  | ||||
|  | ||||
| template <> | ||||
| class future<void> { | ||||
|     using state_type = std::shared_ptr<detail::shared_state<int>>; | ||||
| public: | ||||
|     future() {} | ||||
|  | ||||
|     explicit future(const state_type &state) : state_(state) {} | ||||
|  | ||||
|     future(future &&other) noexcept: state_(std::move(other.state_)) { | ||||
|         other.state_.reset(); | ||||
|     } | ||||
|  | ||||
|     future(const future &other) = delete; | ||||
|  | ||||
|     ~future() {} | ||||
|  | ||||
|     future &operator=(future &&other) noexcept { | ||||
|         if (&other != this) { | ||||
|             state_ = std::move(other.state_); | ||||
|             other.state_.reset(); | ||||
|         } | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     future &operator=(const future &other) = delete; | ||||
|  | ||||
|     void swap(future &other) noexcept { | ||||
|         std::swap(state_, other.state_); | ||||
|     } | ||||
|  | ||||
|     std::shared_future<void> share() noexcept { return std::shared_future<void>(); } | ||||
|  | ||||
|     void get() { state_->get(); } | ||||
|  | ||||
|     bool valid() const noexcept { return state_->valid(); } | ||||
|  | ||||
|     void wait() const { state_->wait(); } | ||||
|  | ||||
|     template <class Rep, class Period> | ||||
|     std::future_status | ||||
|     wait_for(const std::chrono::duration<Rep, Period> &rel_time) const { | ||||
|         return state_->wait_for(rel_time); | ||||
|     } | ||||
|  | ||||
|     template <class Clock, class Duration> | ||||
|     std::future_status | ||||
|     wait_until(const std::chrono::time_point<Clock, Duration> &abs_time) const { | ||||
|         return state_->wait_until(abs_time); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     state_type state_; | ||||
| }; | ||||
|  | ||||
|  | ||||
| template <typename R> | ||||
| class promise { | ||||
|     using state_type = std::shared_ptr<detail::shared_state<R>>; | ||||
| public: | ||||
|     promise() : state_(new detail::shared_state<R>()) {} | ||||
|  | ||||
|     promise(promise &&other) noexcept: state_(std::move(other.state_)) { | ||||
|         other.state_.reset(); | ||||
|     } | ||||
|  | ||||
|     promise(const promise &other) = delete; | ||||
|  | ||||
|     ~promise() {} | ||||
|  | ||||
|     promise &operator=(promise &&other) noexcept { | ||||
|         if (&other != this) { | ||||
|             state_ = std::move(other.state_); | ||||
|             other.state_.reset(); | ||||
|         } | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     promise &operator=(const promise &other) = delete; | ||||
|  | ||||
|     void swap(promise &other) noexcept { | ||||
|         std::swap(state_, other.state_); | ||||
|     } | ||||
|  | ||||
|     std::future<R> get_future() { return std::future<R>(state_); } | ||||
|  | ||||
|     void set_value(const R &value) { state_->set(value); } | ||||
|  | ||||
|     void set_value(R &&value) { state_->set(std::move(value)); } | ||||
|  | ||||
|     void set_value_at_thread_exit(const R &value); | ||||
|  | ||||
|     void set_value_at_thread_exit(R &&value); | ||||
|  | ||||
|     void set_exception(std::exception_ptr p); | ||||
|  | ||||
|     void set_exception_at_thread_exit(std::exception_ptr p); | ||||
|  | ||||
| private: | ||||
|     state_type state_; | ||||
| }; | ||||
|  | ||||
|  | ||||
| template <> | ||||
| class promise<void> { | ||||
|     using state_type = std::shared_ptr<detail::shared_state<int>>; | ||||
| public: | ||||
|     promise() : state_(new detail::shared_state<int>()) {} | ||||
|  | ||||
|     promise(promise &&other) noexcept: state_(std::move(other.state_)) { | ||||
|         other.state_.reset(); | ||||
|     } | ||||
|  | ||||
|     promise(const promise &other) = delete; | ||||
|  | ||||
|     ~promise() {} | ||||
|  | ||||
|     promise &operator=(promise &&other) noexcept { | ||||
|         if (&other != this) { | ||||
|             state_ = std::move(other.state_); | ||||
|             other.state_.reset(); | ||||
|         } | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     promise &operator=(const promise &other) = delete; | ||||
|  | ||||
|     void swap(promise &other) noexcept { | ||||
|         std::swap(state_, other.state_); | ||||
|     } | ||||
|  | ||||
|     std::future<void> get_future() { return std::future<void>(state_); } | ||||
|  | ||||
|     void set_value() { state_->set(0); } | ||||
|  | ||||
|     void set_value_at_thread_exit(); | ||||
|  | ||||
|     void set_exception(std::exception_ptr p); | ||||
|  | ||||
|     void set_exception_at_thread_exit(std::exception_ptr p); | ||||
|  | ||||
| private: | ||||
|     state_type state_; | ||||
| }; | ||||
|  | ||||
|  | ||||
| template <class R> | ||||
| void swap(std::future<R> &lhs, std::future<R> &rhs) noexcept { | ||||
|     lhs.swap(rhs); | ||||
| } | ||||
|  | ||||
| template <class R> | ||||
| void swap(std::promise<R> &lhs, std::promise<R> &rhs) noexcept { | ||||
|     lhs.swap(rhs); | ||||
| } | ||||
|  | ||||
| } // namespace std | ||||
							
								
								
									
										512
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/mutex
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										512
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/mutex
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,512 @@ | ||||
| #pragma once | ||||
|  | ||||
| #if __cplusplus < 201103L | ||||
| #error "C++ version lower than C++11" | ||||
| #endif | ||||
|  | ||||
| //#if defined(RT_USING_PTHREADS) | ||||
|  | ||||
| #include <pthread.h> | ||||
|  | ||||
| #include <system_error> | ||||
| #include <chrono> | ||||
| #include <utility> | ||||
| #include <functional> | ||||
|  | ||||
| #include "__utils.h" | ||||
|  | ||||
| #define rt_cpp_mutex_t  pthread_mutex_t | ||||
|  | ||||
| namespace std  | ||||
| { | ||||
|     // Base class on which to build std::mutex and std::timed_mutex | ||||
|     class __mutex_base | ||||
|     { | ||||
|         protected: | ||||
|             typedef rt_cpp_mutex_t  __native_type; | ||||
|  | ||||
|             __native_type _m_mutex = PTHREAD_MUTEX_INITIALIZER; | ||||
|  | ||||
|             constexpr __mutex_base() noexcept = default; | ||||
|             __mutex_base(const __mutex_base&) = delete; | ||||
|             __mutex_base& operator=(const __mutex_base&) = delete; | ||||
|     }; | ||||
|  | ||||
|      | ||||
|     class mutex : private __mutex_base | ||||
|     { | ||||
|         public: | ||||
|             constexpr mutex() = default; | ||||
|             ~mutex() = default; | ||||
|  | ||||
|             mutex(const mutex&) = delete; | ||||
|             mutex& operator=(const mutex&) = delete; | ||||
|  | ||||
|             void lock() | ||||
|             { | ||||
|                 int err  = pthread_mutex_lock(&_m_mutex); | ||||
|  | ||||
|                 if (err) | ||||
|                 { | ||||
|                     throw_system_error(err, "mutex:lock failed."); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             bool try_lock() noexcept | ||||
|             { | ||||
|                 return !pthread_mutex_trylock(&_m_mutex); | ||||
|             } | ||||
|  | ||||
|             void unlock() noexcept | ||||
|             { | ||||
|                 pthread_mutex_unlock(&_m_mutex); | ||||
|             } | ||||
|  | ||||
|             typedef __native_type* native_handle_type; | ||||
|  | ||||
|             native_handle_type native_handle()  | ||||
|             { | ||||
|                 return &_m_mutex; | ||||
|             }; | ||||
|  | ||||
|     }; | ||||
|  | ||||
|     inline int __rt_cpp_recursive_mutex_init(rt_cpp_mutex_t* m) | ||||
|     { | ||||
|         pthread_mutexattr_t attr; | ||||
|         int res; | ||||
|  | ||||
|         res = pthread_mutexattr_init(&attr); | ||||
|         if (res) | ||||
|             return res; | ||||
|         res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); | ||||
|         if (res) | ||||
|             goto attr_cleanup; | ||||
|         res = pthread_mutex_init(m, &attr); | ||||
|  | ||||
|         attr_cleanup: | ||||
|             int err = pthread_mutexattr_destroy(&attr); | ||||
|             return res ? res : err; | ||||
|     } | ||||
|  | ||||
|     class __recursive_mutex_base | ||||
|     { | ||||
|         protected: | ||||
|             typedef rt_cpp_mutex_t __native_type; | ||||
|  | ||||
|             __native_type _m_recursive_mutex; | ||||
|  | ||||
|             __recursive_mutex_base(const __recursive_mutex_base&) = delete; | ||||
|             __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete; | ||||
|  | ||||
|             __recursive_mutex_base() | ||||
|             { | ||||
|                 int err = __rt_cpp_recursive_mutex_init(&_m_recursive_mutex); | ||||
|                 if (err) | ||||
|                     throw_system_error(err, "Recursive mutex failed to construct"); | ||||
|             } | ||||
|  | ||||
|             ~__recursive_mutex_base() | ||||
|             { | ||||
|                 pthread_mutex_destroy(&_m_recursive_mutex); | ||||
|             } | ||||
|     }; | ||||
|  | ||||
|     class recursive_mutex : private __recursive_mutex_base | ||||
|     { | ||||
|         public: | ||||
|             typedef __native_type* native_handle_type;  | ||||
|             recursive_mutex() = default; | ||||
|             ~recursive_mutex() = default; | ||||
|  | ||||
|             recursive_mutex(const recursive_mutex&) = delete; | ||||
|             recursive_mutex& operator=(const recursive_mutex&) = delete; | ||||
|             void lock() | ||||
|             { | ||||
|                 int err = pthread_mutex_lock(&_m_recursive_mutex); | ||||
|  | ||||
|                 if (err) | ||||
|                     throw_system_error(err, "recursive_mutex::lock failed"); | ||||
|             } | ||||
|  | ||||
|             bool try_lock() noexcept | ||||
|             { | ||||
|                 return !pthread_mutex_trylock(&_m_recursive_mutex); | ||||
|             } | ||||
|  | ||||
|             void unlock() noexcept | ||||
|             { | ||||
|                 pthread_mutex_unlock(&_m_recursive_mutex); | ||||
|             } | ||||
|  | ||||
|             native_handle_type native_handle() | ||||
|             { return &_m_recursive_mutex; } | ||||
|     }; | ||||
|  | ||||
| #ifdef RT_PTHREAD_TIMED_MUTEX | ||||
|  | ||||
|     class timed_mutex; | ||||
|  | ||||
|     class recursive_timed_mutex; | ||||
|  | ||||
| #endif // RT_PTHREAD_TIMED_MUTEX | ||||
|  | ||||
|      | ||||
|     struct defer_lock_t {}; | ||||
|     struct try_to_lock_t {}; | ||||
|     struct adopt_lock_t {}; // take ownership of a locked mtuex | ||||
|  | ||||
|     constexpr defer_lock_t defer_lock { }; | ||||
|     constexpr try_to_lock_t try_to_lock { }; | ||||
|     constexpr adopt_lock_t adopt_lock { }; | ||||
|  | ||||
|     template <class Mutex>  | ||||
|     class lock_guard | ||||
|     { | ||||
|         public: | ||||
|             typedef Mutex mutex_type; | ||||
|  | ||||
|             explicit lock_guard(mutex_type& m) : pm(m) { pm.lock(); } | ||||
|             lock_guard(mutex_type& m, adopt_lock_t) noexcept : pm(m) | ||||
|             { } | ||||
|             ~lock_guard()  | ||||
|             { pm.unlock(); } | ||||
|  | ||||
|             lock_guard(lock_guard const&) = delete; | ||||
|             lock_guard& operator=(lock_guard const&) = delete; | ||||
|  | ||||
|         private: | ||||
|             mutex_type& pm; | ||||
|  | ||||
|     }; | ||||
|  | ||||
|     template <class Mutex> | ||||
|     class unique_lock | ||||
|     { | ||||
|         public: | ||||
|             typedef Mutex mutex_type; | ||||
|  | ||||
|             unique_lock() noexcept : pm(nullptr), owns(false) { } | ||||
|              | ||||
|             explicit unique_lock(mutex_type& m)  | ||||
|                 : pm(std::addressof(m)), owns(false) | ||||
|             { | ||||
|                 lock(); | ||||
|                 owns = true; | ||||
|             } | ||||
|  | ||||
|             unique_lock(mutex_type& m, defer_lock_t) noexcept  | ||||
|                 : pm(std::addressof(m)), owns(false) | ||||
|             { } | ||||
|  | ||||
|             unique_lock(mutex_type& m, try_to_lock_t) noexcept | ||||
|                 : pm(std::addressof(m)), owns(pm->try_lock()) | ||||
|             { } | ||||
|  | ||||
|             unique_lock(mutex_type& m, adopt_lock_t) noexcept | ||||
|                 : pm(std::addressof(m)), owns(true) | ||||
|             { } | ||||
|  | ||||
|             // any lock-involving timed mutex API is currently only for custom implementations | ||||
|             // the standard ones are not available | ||||
|             template <class Clock, class Duration> | ||||
|             unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time) noexcept | ||||
|                 : pm(std::addressof(m)), owns(pm->try_lock_until(abs_time)) | ||||
|             { } | ||||
|  | ||||
|             template <class Rep, class Period> | ||||
|             unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time) noexcept | ||||
|                 : pm(std::addressof(m)), owns(pm->try_lock_for(rel_time)) | ||||
|             { } | ||||
|              | ||||
|             ~unique_lock() | ||||
|             { | ||||
|                 if (owns) | ||||
|                     unlock(); | ||||
|             } | ||||
|              | ||||
|             unique_lock(unique_lock const&) = delete; | ||||
|             unique_lock& operator=(unique_lock const&) = delete; | ||||
|  | ||||
|             unique_lock(unique_lock&& u) noexcept | ||||
|                 : pm(u.pm), owns(u.owns) | ||||
|             { | ||||
|                 u.pm = nullptr; | ||||
|                 u.owns = false; | ||||
|             } | ||||
|  | ||||
|             unique_lock& operator=(unique_lock&& u) noexcept                 | ||||
|             { | ||||
|                 if (owns) | ||||
|                     unlock(); | ||||
|                  | ||||
|                 unique_lock(std::move(u)).swap(*this); | ||||
|  | ||||
|                 u.pm = nullptr; | ||||
|                 u.owns = false; | ||||
|  | ||||
|                 return *this; | ||||
|             } | ||||
|  | ||||
|             void lock() | ||||
|             { | ||||
|                 if (!pm) | ||||
|                     throw_system_error(int(errc::operation_not_permitted),  | ||||
|                                         "unique_lock::lock: references null mutex"); | ||||
|                 else if (owns) | ||||
|                     throw_system_error(int(errc::resource_deadlock_would_occur), | ||||
|                                         "unique_lock::lock: already locked" ); | ||||
|                 else { | ||||
|                     pm->lock(); | ||||
|                     owns = true; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             bool try_lock() | ||||
|             { | ||||
|                 if (!pm) | ||||
|                     throw_system_error(int(errc::operation_not_permitted),  | ||||
|                                         "unique_lock::try_lock: references null mutex"); | ||||
|                 else if (owns) | ||||
|                     throw_system_error(int(errc::resource_deadlock_would_occur), | ||||
|                                         "unique_lock::try_lock: already locked" ); | ||||
|                 else { | ||||
|                     owns = pm->try_lock(); | ||||
|                 } | ||||
|                 return owns; | ||||
|             } | ||||
|  | ||||
|             template <class Rep, class Period> | ||||
|             bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) | ||||
|             { | ||||
|                 if (!pm) | ||||
|                     throw_system_error(int(errc::operation_not_permitted), | ||||
|                                         "unique_lock::try_lock_for: references null mutex"); | ||||
|                 else if (owns) | ||||
|                     throw_system_error(int(errc::resource_deadlock_would_occur), | ||||
|                                         "unique_lock::try_lock_for: already locked"); | ||||
|                 else { | ||||
|                     owns = pm->try_lock_for(rel_time); | ||||
|                 } | ||||
|                 return owns; | ||||
|             } | ||||
|              | ||||
|             template <class Clock, class Duration> | ||||
|             bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time) | ||||
|             { | ||||
|                 if (!pm) | ||||
|                     throw_system_error(int(errc::operation_not_permitted), | ||||
|                                         "unique_lock::try_lock_until: references null mutex"); | ||||
|                 else if (owns) | ||||
|                     throw_system_error(int(errc::resource_deadlock_would_occur), | ||||
|                                         "unique_lock::try_lock_until: already locked"); | ||||
|                 else { | ||||
|                     owns = pm->try_lock_until(abs_time); | ||||
|                 } | ||||
|                 return owns; | ||||
|             } | ||||
|              | ||||
|             void unlock() | ||||
|             { | ||||
|                 if (!owns) | ||||
|                     throw_system_error(int(errc::operation_not_permitted),  | ||||
|                                         "unique_lock::unlock: not locked"); | ||||
|                 else { | ||||
|                     pm->unlock(); | ||||
|                     owns = false; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             void swap(unique_lock& u) noexcept | ||||
|             { | ||||
|                 std::swap(pm, u.pm); | ||||
|                 std::swap(owns, u.owns); | ||||
|             } | ||||
|  | ||||
|             mutex_type *release() noexcept | ||||
|             { | ||||
|                 mutex_type* ret_mutex = pm; | ||||
|                 pm = nullptr; | ||||
|                 owns = false; | ||||
|                  | ||||
|                 return ret_mutex; | ||||
|             } | ||||
|  | ||||
|             bool owns_lock() const noexcept | ||||
|             { return owns; } | ||||
|  | ||||
|             explicit operator bool() const noexcept | ||||
|             { return owns_lock(); } | ||||
|  | ||||
|             mutex_type* mutex() const noexcept | ||||
|             { return pm; } | ||||
|              | ||||
|              | ||||
|         private: | ||||
|             mutex_type *pm;  | ||||
|             bool owns; | ||||
|     }; | ||||
|  | ||||
|     template <class Mutex> | ||||
|     void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) | ||||
|     { | ||||
|         x.swap(y); | ||||
|     } | ||||
|  | ||||
|     template <class L0, class L1> | ||||
|     int try_lock(L0& l0, L1& l1) | ||||
|     { | ||||
|         unique_lock<L0> u0(l0, try_to_lock); // try to lock the first Lockable | ||||
|         // using unique_lock since we don't want to unlock l0 manually if l1 fails to lock | ||||
|         if (u0.owns_lock()) | ||||
|         { | ||||
|             if (l1.try_lock()) // lock the second one | ||||
|             { | ||||
|                 u0.release(); // do not let RAII of a unique_lock unlock l0 | ||||
|                 return -1; | ||||
|             } | ||||
|             else | ||||
|                 return 1;  | ||||
|         } | ||||
|         return 0; | ||||
|     }  | ||||
|  | ||||
|      | ||||
|     template <class L0, class L1, class L2, class... L3> | ||||
|     int try_lock(L0& l0, L1& l1, L2& l2, L3&... l3) | ||||
|     { | ||||
|         int r = 0; | ||||
|         unique_lock<L0> u0(l0, try_to_lock); | ||||
|         // automatically unlock is done through RAII of unique_lock | ||||
|         if (u0.owns_lock()) | ||||
|         { | ||||
|             r = try_lock(l1, l2, l3...); | ||||
|             if (r == -1) | ||||
|                 u0.release(); | ||||
|             else | ||||
|                 ++r; | ||||
|         } | ||||
|         return r; | ||||
|     } | ||||
|  | ||||
|     template <class L0, class L1, class L2, class ...L3> | ||||
|     void | ||||
|     __lock_first(int i, L0& l0, L1& l1, L2& l2, L3&... l3) | ||||
|     { | ||||
|         while (true) | ||||
|         { | ||||
|             // we first lock the one that is the most difficult to lock  | ||||
|             switch (i)  | ||||
|             { | ||||
|             case 0: | ||||
|                 { | ||||
|                     unique_lock<L0> u0(l0); | ||||
|                     i = try_lock(l1, l2, l3...); | ||||
|                     if (i == -1) | ||||
|                     { | ||||
|                         u0.release(); | ||||
|                         return; | ||||
|                     } | ||||
|                 } | ||||
|                 ++i; | ||||
|                 sched_yield(); | ||||
|                 break; | ||||
|             case 1: | ||||
|                 { | ||||
|                     unique_lock<L1> u1(l1); | ||||
|                     i = try_lock(l2, l3..., l0); | ||||
|                     if (i == -1) | ||||
|                     { | ||||
|                         u1.release(); | ||||
|                         return; | ||||
|                     } | ||||
|                 } | ||||
|                 if (i == sizeof...(L3) + 1) // all except l0 are locked | ||||
|                     i = 0; | ||||
|                 else | ||||
|                     i += 2; // since i was two-based above | ||||
|                 sched_yield(); | ||||
|                 break; | ||||
|             default: | ||||
|                 __lock_first(i - 2, l2, l3..., l0, l1); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     template <class L0, class L1> | ||||
|     void lock(L0& l0, L1& l1) | ||||
|     { | ||||
|         while (true) | ||||
|         { | ||||
|             { | ||||
|                 unique_lock<L0> u0(l0); | ||||
|                 if (l1.try_lock()) | ||||
|                 { | ||||
|                     u0.release(); | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             sched_yield(); | ||||
|             // wait and try the other way | ||||
|             { | ||||
|                 unique_lock<L1> u1(l1); | ||||
|                 if (l0.try_lock()) | ||||
|                 { | ||||
|                     u1.release(); | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             sched_yield(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     template <class L0, class L1, class... L2> | ||||
|     void lock(L0& l0, L1& l1, L2&... l2) | ||||
|     { | ||||
|         __lock_first(0, l0, l1, l2...); | ||||
|     } | ||||
|  | ||||
|     struct once_flag  | ||||
|     { | ||||
|         constexpr once_flag() noexcept = default; | ||||
|  | ||||
|         once_flag(const once_flag&) = delete; | ||||
|         once_flag& operator=(const once_flag&) = delete; | ||||
|  | ||||
|         template <class Callable, class... Args> | ||||
|         friend void call_once(once_flag& flag, Callable&& func, Args&&... args); | ||||
|  | ||||
|         private: | ||||
|             pthread_once_t _m_once = PTHREAD_ONCE_INIT; | ||||
|     }; | ||||
|  | ||||
|     mutex& get_once_mutex(); | ||||
|     extern function<void()> once_functor; | ||||
|     extern void set_once_functor_lock_ptr(unique_lock<mutex>*); | ||||
|  | ||||
|     extern "C" void once_proxy(); // passed into pthread_once | ||||
|  | ||||
|     template <class Callable, class... Args> | ||||
|     void call_once(once_flag& flag, Callable&& func, Args&&... args) | ||||
|     { | ||||
|         // use a lock to ensure the call to the functor | ||||
|         // is exclusive to only the first calling thread | ||||
|         unique_lock<mutex> functor_lock(get_once_mutex());  | ||||
|  | ||||
|         auto call_wrapper = std::bind(std::forward<Callable>(func), std::forward<Args>(args)...); | ||||
|         once_functor = [&]() { call_wrapper(); }; | ||||
|  | ||||
|         set_once_functor_lock_ptr(&functor_lock); // so as to unlock when actually calling | ||||
|  | ||||
|         int err = pthread_once(&flag._m_once, &once_proxy); | ||||
|  | ||||
|         if (functor_lock) | ||||
|             set_once_functor_lock_ptr(nullptr); | ||||
|         if (err) | ||||
|             throw_system_error(err, "call_once failed"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| //#endif //(RT_USING_PTHREADS) | ||||
							
								
								
									
										52
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/mutex.cpp
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										52
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/mutex.cpp
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| /* | ||||
|  * Copyright (c) 2006-2021, RT-Thread Development Team | ||||
|  * | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  * | ||||
|  * Change Logs: | ||||
|  * Date           Author       Notes | ||||
|  * 2021-04-27     flybreak     the first version. | ||||
|  */ | ||||
|  | ||||
| #include "mutex" | ||||
|  | ||||
| namespace std | ||||
| { | ||||
|     // use a set of global and static objects | ||||
|     // a proxy function to pthread_once | ||||
|  | ||||
|     function<void()> once_functor; | ||||
|  | ||||
|     mutex& get_once_mutex() | ||||
|     { | ||||
|         static mutex once_mutex; | ||||
|         return once_mutex; | ||||
|     } | ||||
|  | ||||
|     inline unique_lock<mutex>*& get_once_functor_lock_ptr() | ||||
|     { | ||||
|         static unique_lock<mutex>* once_functor_mutex_ptr = nullptr; | ||||
|         return once_functor_mutex_ptr; | ||||
|     } | ||||
|  | ||||
|     void set_once_functor_lock_ptr(unique_lock<mutex>* m_ptr) | ||||
|     { | ||||
|         get_once_functor_lock_ptr() = m_ptr; | ||||
|     } | ||||
|  | ||||
|     extern "C" | ||||
|     { | ||||
|         void once_proxy() | ||||
|         { | ||||
|             // need to first transfer the functor's ownership so as to call it | ||||
|             function<void()> once_call = std::move(once_functor); | ||||
|  | ||||
|             // no need to hold the lock anymore | ||||
|             unique_lock<mutex>* lock_ptr = get_once_functor_lock_ptr(); | ||||
|             get_once_functor_lock_ptr() = nullptr; | ||||
|             lock_ptr->unlock(); | ||||
|  | ||||
|             once_call(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										239
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/thread
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										239
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/thread
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,239 @@ | ||||
| #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); | ||||
|         } | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										94
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/thread.cpp
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										94
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/thread.cpp
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| /* | ||||
|  * Copyright (c) 2006-2021, RT-Thread Development Team | ||||
|  * | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  * | ||||
|  * Change Logs: | ||||
|  * Date           Author       Notes | ||||
|  * 2021-04-27     flybreak     the first version. | ||||
|  */ | ||||
|  | ||||
| #include "thread" | ||||
| #include "__utils.h" | ||||
|  | ||||
|  | ||||
| #define _RT_NPROCS 0 | ||||
|  | ||||
| namespace std | ||||
| { | ||||
|  | ||||
|     extern "C" | ||||
|     { | ||||
|         static void* execute_native_thread_routine(void *p) | ||||
|         { | ||||
|             thread::invoker_base* t = static_cast<thread::invoker_base*>(p); | ||||
|             thread::invoker_base_ptr local; | ||||
|             local.swap(t->this_ptr); // tranfer the ownership of the invoker into the thread entry | ||||
|  | ||||
|             local->invoke(); | ||||
|  | ||||
|             return NULL; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void thread::start_thread(invoker_base_ptr b) | ||||
|     { | ||||
|         auto raw_ptr = b.get(); | ||||
|         // transfer the ownership of the invoker to the new thread | ||||
|         raw_ptr->this_ptr = std::move(b); | ||||
|         int err = pthread_create(&_m_thr.__cpp_thread_t, NULL, | ||||
|                 &execute_native_thread_routine, raw_ptr); | ||||
|  | ||||
|         if (err) | ||||
|         { | ||||
|             raw_ptr->this_ptr.reset(); | ||||
|             throw_system_error(err, "Failed to create a thread"); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     thread::~thread() | ||||
|     { | ||||
|         if (joinable()) // when either not joined or not detached | ||||
|             terminate(); | ||||
|     } | ||||
|  | ||||
|     void thread::join() | ||||
|     { | ||||
|         int err = EINVAL; | ||||
|  | ||||
|         if (joinable()) | ||||
|             err = pthread_join(native_handle(), NULL); | ||||
|  | ||||
|         if (err) | ||||
|         { | ||||
|             throw_system_error(err, "thread::join failed"); | ||||
|         } | ||||
|  | ||||
|         _m_thr = id(); | ||||
|     } | ||||
|  | ||||
|     void thread::detach() | ||||
|     { | ||||
|         int err = EINVAL; | ||||
|  | ||||
|         if (joinable()) | ||||
|             err = pthread_detach(native_handle()); | ||||
|         if (err) | ||||
|         { | ||||
|             throw_system_error(err, "thread::detach failed"); | ||||
|         } | ||||
|  | ||||
|         _m_thr = id(); | ||||
|     } | ||||
|  | ||||
|     // TODO: not yet actually implemented. | ||||
|     // The standard states that the returned value should only be considered a hint. | ||||
|     unsigned thread::hardware_concurrency() noexcept | ||||
|     { | ||||
|         int __n = _RT_NPROCS; | ||||
|         if (__n < 0) | ||||
|             __n = 0; | ||||
|         return __n; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										29
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/utils.cpp
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										29
									
								
								riscv/rtthread/components/libc/cplusplus/cpp11/gcc/utils.cpp
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| /* | ||||
|  * Copyright (c) 2006-2021, RT-Thread Development Team | ||||
|  * | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  * | ||||
|  * Change Logs: | ||||
|  * Date           Author       Notes | ||||
|  * 2021-04-27     flybreak     the first version. | ||||
|  */ | ||||
|  | ||||
| #include "__utils.h" | ||||
| #include <sys/time.h> | ||||
|  | ||||
| tick_clock::time_point tick_clock::now() | ||||
| { | ||||
|     tick_clock::rep cur_tk = clock(); | ||||
|     tick_clock::duration cur_time(cur_tk); | ||||
|  | ||||
|     return tick_clock::time_point(cur_time); | ||||
| } | ||||
|  | ||||
| real_time_clock::time_point real_time_clock::now() noexcept | ||||
| { | ||||
|     timespec tp; | ||||
|     clock_gettime(CLOCK_REALTIME, &tp); | ||||
|  | ||||
|     return time_point(duration(std::chrono::seconds(tp.tv_sec)) | ||||
|                         + std::chrono::nanoseconds(tp.tv_nsec)); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user