import RT-Thread@9217865c without bsp, libcpu and components/net
This commit is contained in:
commit
e2376a3709
1414 changed files with 390370 additions and 0 deletions
59
components/libc/cplusplus/cpp11/gcc/__utils.h
Normal file
59
components/libc/cplusplus/cpp11/gcc/__utils.h
Normal file
|
@ -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;
|
||||
};
|
222
components/libc/cplusplus/cpp11/gcc/condition_variable
Normal file
222
components/libc/cplusplus/cpp11/gcc/condition_variable
Normal 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
components/libc/cplusplus/cpp11/gcc/condition_variable.cpp
Normal file
34
components/libc/cplusplus/cpp11/gcc/condition_variable.cpp
Normal 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
components/libc/cplusplus/cpp11/gcc/future
Normal file
336
components/libc/cplusplus/cpp11/gcc/future
Normal 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
components/libc/cplusplus/cpp11/gcc/mutex
Normal file
512
components/libc/cplusplus/cpp11/gcc/mutex
Normal 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
components/libc/cplusplus/cpp11/gcc/mutex.cpp
Normal file
52
components/libc/cplusplus/cpp11/gcc/mutex.cpp
Normal 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
components/libc/cplusplus/cpp11/gcc/thread
Normal file
239
components/libc/cplusplus/cpp11/gcc/thread
Normal 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
components/libc/cplusplus/cpp11/gcc/thread.cpp
Normal file
94
components/libc/cplusplus/cpp11/gcc/thread.cpp
Normal 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
components/libc/cplusplus/cpp11/gcc/utils.cpp
Normal file
29
components/libc/cplusplus/cpp11/gcc/utils.cpp
Normal 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));
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue