summaryrefslogtreecommitdiff
path: root/components/cplusplus/cpp11/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'components/cplusplus/cpp11/gcc')
-rw-r--r--components/cplusplus/cpp11/gcc/__utils.h59
-rw-r--r--components/cplusplus/cpp11/gcc/condition_variable222
-rw-r--r--components/cplusplus/cpp11/gcc/condition_variable.cpp34
-rw-r--r--components/cplusplus/cpp11/gcc/future336
-rw-r--r--components/cplusplus/cpp11/gcc/mutex512
-rw-r--r--components/cplusplus/cpp11/gcc/mutex.cpp52
-rw-r--r--components/cplusplus/cpp11/gcc/thread239
-rw-r--r--components/cplusplus/cpp11/gcc/thread.cpp94
-rw-r--r--components/cplusplus/cpp11/gcc/utils.cpp29
9 files changed, 1577 insertions, 0 deletions
diff --git a/components/cplusplus/cpp11/gcc/__utils.h b/components/cplusplus/cpp11/gcc/__utils.h
new file mode 100644
index 0000000000..f9a3c93796
--- /dev/null
+++ b/components/cplusplus/cpp11/gcc/__utils.h
@@ -0,0 +1,59 @@
+/*
+ * 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>
+
+#define RT_USING_CPP_EXCEPTION
+
+inline void throw_system_error(int err, const char *what_msg)
+{
+#ifdef RT_USING_CPP_EXCEPTION
+ 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;
+};
diff --git a/components/cplusplus/cpp11/gcc/condition_variable b/components/cplusplus/cpp11/gcc/condition_variable
new file mode 100644
index 0000000000..f2d48dd5b5
--- /dev/null
+++ b/components/cplusplus/cpp11/gcc/condition_variable
@@ -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
diff --git a/components/cplusplus/cpp11/gcc/condition_variable.cpp b/components/cplusplus/cpp11/gcc/condition_variable.cpp
new file mode 100644
index 0000000000..2860dd9161
--- /dev/null
+++ b/components/cplusplus/cpp11/gcc/condition_variable.cpp
@@ -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
diff --git a/components/cplusplus/cpp11/gcc/future b/components/cplusplus/cpp11/gcc/future
new file mode 100644
index 0000000000..6a686063fb
--- /dev/null
+++ b/components/cplusplus/cpp11/gcc/future
@@ -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
diff --git a/components/cplusplus/cpp11/gcc/mutex b/components/cplusplus/cpp11/gcc/mutex
new file mode 100644
index 0000000000..cc593cc139
--- /dev/null
+++ b/components/cplusplus/cpp11/gcc/mutex
@@ -0,0 +1,512 @@
+#pragma once
+
+#if __cplusplus < 201103L
+#error "C++ version lower than C++11"
+#endif
+
+//#if defined(RT_USING_LIBC) && 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_LIBC) && (RT_USING_PTHREADS) \ No newline at end of file
diff --git a/components/cplusplus/cpp11/gcc/mutex.cpp b/components/cplusplus/cpp11/gcc/mutex.cpp
new file mode 100644
index 0000000000..014460ffde
--- /dev/null
+++ b/components/cplusplus/cpp11/gcc/mutex.cpp
@@ -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();
+ }
+ }
+}
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);
+ }
+
+ }
+}
diff --git a/components/cplusplus/cpp11/gcc/thread.cpp b/components/cplusplus/cpp11/gcc/thread.cpp
new file mode 100644
index 0000000000..947170da25
--- /dev/null
+++ b/components/cplusplus/cpp11/gcc/thread.cpp
@@ -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;
+ }
+}
diff --git a/components/cplusplus/cpp11/gcc/utils.cpp b/components/cplusplus/cpp11/gcc/utils.cpp
new file mode 100644
index 0000000000..1ec3b70cad
--- /dev/null
+++ b/components/cplusplus/cpp11/gcc/utils.cpp
@@ -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));
+}