mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
doc: fix and update cpp11 compat doxygen
This commit is contained in:
parent
8a36c33a6c
commit
27297bb640
@ -14,7 +14,7 @@
|
||||
* @brief C++11 chrono drop in replacement that adds the function now based on
|
||||
* xtimer/timex
|
||||
* @see <a href="http://en.cppreference.com/w/cpp/thread/thread">
|
||||
* std::thread, defined in header <thread>
|
||||
* std::thread, defined in header thread
|
||||
* </a>
|
||||
*
|
||||
* @author Raphael Hiesgen <raphael.hiesgen (at) haw-hamburg.de>
|
||||
@ -38,30 +38,37 @@ constexpr uint32_t microsecs_in_sec = 1000000;
|
||||
} // namespace anaonymous
|
||||
|
||||
/**
|
||||
* @brief time point to use for timed wait, as stdlib clocks are not available
|
||||
* @brief A time point for timed wait, as clocks from the standard are not
|
||||
* available on RIOT.
|
||||
*/
|
||||
class time_point {
|
||||
using native_handle_type = timex_t;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief create a time point with seconds and microseconds set to 0
|
||||
* @brief Creates a time point with seconds and microseconds set to 0.
|
||||
*/
|
||||
inline time_point() : m_handle{0, 0} {}
|
||||
/**
|
||||
* @brief create time point from timex_t struct
|
||||
* @brief Create time point from timex_t struct.
|
||||
*/
|
||||
inline time_point(timex_t&& tp) : m_handle(tp) {}
|
||||
/**
|
||||
* @brief Use default copy constructor.
|
||||
*/
|
||||
constexpr time_point(const time_point& tp) = default;
|
||||
/**
|
||||
* @brief Use default move constructor.
|
||||
*/
|
||||
constexpr time_point(time_point&& tp) = default;
|
||||
|
||||
/**
|
||||
* @brief get access to the handle used to store the time information
|
||||
* @brief Gives access to the native handle that stores the time information.
|
||||
*/
|
||||
inline native_handle_type native_handle() const { return m_handle; }
|
||||
|
||||
/**
|
||||
* @brief add a stdlib chrono::duration to this time point
|
||||
* @brief Add a standard chrono::duration to this time point.
|
||||
*/
|
||||
template <class Rep, class Period>
|
||||
inline time_point& operator+=(const std::chrono::duration<Rep, Period>& d) {
|
||||
@ -74,12 +81,12 @@ class time_point {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns seconds member as uint32_t
|
||||
* @brief Returns seconds member as uint32_t.
|
||||
*/
|
||||
inline uint32_t seconds() const { return m_handle.seconds; }
|
||||
|
||||
/**
|
||||
* @brief returns microseconds member as uint32_t
|
||||
* @brief Returns microseconds member as uint32_t.
|
||||
*/
|
||||
inline uint32_t microseconds() const { return m_handle.microseconds; }
|
||||
|
||||
@ -93,9 +100,9 @@ class time_point {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief get the current time saved in a time point
|
||||
* @brief Returns the current time saved in a time point.
|
||||
*
|
||||
* @return time_point containing the current time
|
||||
* @return time_point containing the current time.
|
||||
*/
|
||||
inline time_point now() {
|
||||
timex_t tp;
|
||||
@ -104,7 +111,7 @@ inline time_point now() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief compare two timepoints
|
||||
* @brief Compares two timepoints.
|
||||
*/
|
||||
inline bool operator<(const time_point& lhs, const time_point& rhs) {
|
||||
return lhs.seconds() < rhs.seconds()
|
||||
@ -113,21 +120,21 @@ inline bool operator<(const time_point& lhs, const time_point& rhs) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief compare two timepoints
|
||||
* @brief Compares two timepoints.
|
||||
*/
|
||||
inline bool operator>(const time_point& lhs, const time_point& rhs) {
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief compare two timepoints
|
||||
* @brief Compares two timepoints.
|
||||
*/
|
||||
inline bool operator<=(const time_point& lhs, const time_point& rhs) {
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief compare two timepoints
|
||||
* @brief Compare two timepoints.
|
||||
*/
|
||||
inline bool operator>=(const time_point& lhs, const time_point& rhs) {
|
||||
return !(lhs < rhs);
|
||||
|
@ -33,49 +33,110 @@
|
||||
|
||||
namespace riot {
|
||||
|
||||
/**
|
||||
* @brief Status for timeout-based calls of the condition variable.
|
||||
*/
|
||||
enum class cv_status {
|
||||
no_timeout,
|
||||
timeout
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief C++11 complient implementation of condition variable, uses the time
|
||||
* point implemented in our chrono replacement instead of the
|
||||
* specified one
|
||||
* @brief C++11 compliant implementation of condition variable, uses the time
|
||||
* point implemented in our chrono replacement instead of the
|
||||
* specified one
|
||||
* @see <a href="http://en.cppreference.com/w/cpp/thread/condition_variable">
|
||||
* std::condition_variable
|
||||
* </a>
|
||||
*/
|
||||
class condition_variable {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* @brief The native handle type used by the condition variable.
|
||||
*/
|
||||
using native_handle_type = priority_queue_t*;
|
||||
|
||||
inline condition_variable() { m_queue.first = NULL; }
|
||||
~condition_variable();
|
||||
|
||||
/**
|
||||
* @brief Notify one thread waiting on this condition.
|
||||
*/
|
||||
void notify_one() noexcept;
|
||||
/**
|
||||
* @brief Notify all threads waiting on this condition variable.
|
||||
*/
|
||||
void notify_all() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Block until woken up through the condition variable.
|
||||
* @param lock A lock that is locked by the current thread.
|
||||
*/
|
||||
void wait(unique_lock<mutex>& lock) noexcept;
|
||||
/**
|
||||
* @brief Block until woken up through the condition variable and a predicate
|
||||
* is fulfilled.
|
||||
* @param lock A lock that is locked by the current thread.
|
||||
* @param pred A predicate that returns a bool to signify if the thread
|
||||
* should continue to wait when woken up through the cv.
|
||||
*/
|
||||
template <class Predicate>
|
||||
void wait(unique_lock<mutex>& lock, Predicate pred);
|
||||
/**
|
||||
* @brief Block until woken up through the condition variable or a specified
|
||||
* point in time is reached. The lock is reacquired either way.
|
||||
* @param lock A lock that is locked by the current thread.
|
||||
* @param timeout_time Point in time when the thread is woken up
|
||||
* independently of the condition variable.
|
||||
* @return A status to signify if woken up due to a timeout or the cv.
|
||||
*/
|
||||
cv_status wait_until(unique_lock<mutex>& lock,
|
||||
const time_point& timeout_time);
|
||||
/**
|
||||
* @brief Block until woken up through the condition variable and a predicate
|
||||
* is fulfilled or a specified point in time is reached. The lock is
|
||||
* reacquired either way.
|
||||
* @param lock A lock that is locked by the current thread.
|
||||
* @param timeout_time Point in time when the thread is woken up
|
||||
* independently of the condition variable.
|
||||
* @param pred A predicate that returns a bool to signify if the
|
||||
* thread should continue to wait when woken up through
|
||||
* the cv.
|
||||
* @return Result of the pred when the function returns.
|
||||
*/
|
||||
template <class Predicate>
|
||||
bool wait_until(unique_lock<mutex>& lock, const time_point& timeout_time,
|
||||
Predicate pred);
|
||||
|
||||
/**
|
||||
* @brief Blocks until woken up through the condition variable or when the
|
||||
* thread has been blocked for a certain time.
|
||||
* @param lock A lock that is locked by the current thread.
|
||||
* @param rel_time The maximum time spent blocking.
|
||||
* @return A status to signify if woken up due to a timeout or the cv.
|
||||
*/
|
||||
template <class Rep, class Period>
|
||||
cv_status wait_for(unique_lock<mutex>& lock,
|
||||
const std::chrono::duration<Rep, Period>& rel_time);
|
||||
/**
|
||||
* @brief Blocks until woken up through the condition variable and a predicate
|
||||
* is fulfilled or when the thread has been blocked for a certain time.
|
||||
* @param lock A lock that is locked by the current thread.
|
||||
* @param rel_time The maximum time spent blocking.
|
||||
* @param pred A predicate that returns a bool to signify if the thread
|
||||
* should continue to wait when woken up through the cv.
|
||||
* @return Result of the pred when the function returns.
|
||||
*/
|
||||
template <class Rep, class Period, class Predicate>
|
||||
bool wait_for(unique_lock<mutex>& lock,
|
||||
const std::chrono::duration<Rep, Period>& rel_time,
|
||||
Predicate pred);
|
||||
|
||||
/**
|
||||
* @brief Returns the native handle of the condition variable.
|
||||
*/
|
||||
inline native_handle_type native_handle() { return &m_queue; }
|
||||
|
||||
private:
|
||||
private:
|
||||
condition_variable(const condition_variable&);
|
||||
condition_variable& operator=(const condition_variable&);
|
||||
|
||||
|
@ -29,34 +29,49 @@ namespace riot {
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* A list of integers (wraps a long... template parameter pack).
|
||||
* @brief A list of integers (wraps a long... template parameter pack).
|
||||
*/
|
||||
template <long... Is>
|
||||
struct int_list {};
|
||||
|
||||
/**
|
||||
* Creates indices for from `Pos` to `Max`.
|
||||
* @brief Creates indices from `Pos` to `Max`.
|
||||
*/
|
||||
template <long Max, long Pos = 0, typename Indices = int_list<>>
|
||||
struct il_indices;
|
||||
|
||||
/**
|
||||
* @brief End of recursion, `Pos` reached `Max`.
|
||||
*/
|
||||
template <long Pos, long... Is>
|
||||
struct il_indices<Pos, Pos, int_list<Is...>> {
|
||||
/**
|
||||
* @brief Result is the list containing `Is...`.
|
||||
*/
|
||||
using type = int_list<Is...>;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Recursion step.
|
||||
*/
|
||||
template <long Max, long Pos, long... Is>
|
||||
struct il_indices<Max, Pos, int_list<Is...>> {
|
||||
/**
|
||||
* @brief Append `Pos` to list and increment for the next step.
|
||||
*/
|
||||
using type = typename il_indices<Max, Pos + 1, int_list<Is..., Pos>>::type;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Function to create a list of indices from `From` to `To`.
|
||||
*/
|
||||
template <long To, long From = 0>
|
||||
typename il_indices<To, From>::type get_indices() {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* apply arguments to function
|
||||
* @brief Apply arguments in a tuple to function.
|
||||
*/
|
||||
template <class F, long... Is, class Tuple>
|
||||
inline auto apply_args(F& f, detail::int_list<Is...>, Tuple&& tup)
|
||||
@ -64,12 +79,20 @@ inline auto apply_args(F& f, detail::int_list<Is...>, Tuple&& tup)
|
||||
return f(std::get<Is>(tup)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prefix the argument tuple with additonal arguments.
|
||||
* In this case the tuple is empty.
|
||||
*/
|
||||
template <class F, class Tuple, class... Ts>
|
||||
inline auto apply_args_prefixed(F& f, detail::int_list<>, Tuple&, Ts&&... args)
|
||||
-> decltype(f(std::forward<Ts>(args)...)) {
|
||||
return f(std::forward<Ts>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prefix the argument tuple with additonal arguments.
|
||||
* In this case the tuple is contains arguments.
|
||||
*/
|
||||
template <class F, long... Is, class Tuple, class... Ts>
|
||||
inline auto apply_args_prefixed(F& f, detail::int_list<Is...>, Tuple& tup,
|
||||
Ts&&... args)
|
||||
@ -77,6 +100,9 @@ inline auto apply_args_prefixed(F& f, detail::int_list<Is...>, Tuple& tup,
|
||||
return f(std::forward<Ts>(args)..., std::get<Is>(tup)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Suffix the tuple with additonal arguments.
|
||||
*/
|
||||
template <class F, long... Is, class Tuple, class... Ts>
|
||||
inline auto apply_args_suffxied(F& f, detail::int_list<Is...>, Tuple& tup,
|
||||
Ts&&... args)
|
||||
|
@ -41,31 +41,66 @@ namespace riot {
|
||||
* </a>
|
||||
*/
|
||||
class mutex {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* The native handle type used by the mutex.
|
||||
*/
|
||||
using native_handle_type = mutex_t*;
|
||||
|
||||
inline constexpr mutex() noexcept : m_mtx{{0}} {}
|
||||
~mutex();
|
||||
|
||||
/**
|
||||
* @brief Lock the mutex.
|
||||
*/
|
||||
void lock();
|
||||
/**
|
||||
* @brief Try to lock the mutex.
|
||||
* @return `true` if the mutex was locked, `false` otherwise.
|
||||
*/
|
||||
bool try_lock() noexcept;
|
||||
/**
|
||||
* @brief Unlock the mutex.
|
||||
*/
|
||||
void unlock() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Provides access to the native handle.
|
||||
* @return The native handle of the mutex.
|
||||
*/
|
||||
inline native_handle_type native_handle() { return &m_mtx; }
|
||||
|
||||
private:
|
||||
private:
|
||||
mutex(const mutex&);
|
||||
mutex& operator=(const mutex&);
|
||||
|
||||
mutex_t m_mtx;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Tag type for defer lock strategy.
|
||||
*/
|
||||
struct defer_lock_t {};
|
||||
/**
|
||||
* @brief Tag type for try lock strategy.
|
||||
*/
|
||||
struct try_to_lock_t {};
|
||||
/**
|
||||
* @brief Tag type for adopt lock strategy.
|
||||
*/
|
||||
struct adopt_lock_t {};
|
||||
|
||||
/**
|
||||
* @brief Tag constant for defer lock strategy.
|
||||
*/
|
||||
constexpr defer_lock_t defer_lock = defer_lock_t();
|
||||
/**
|
||||
* @brief Tag constant for try lock strategy.
|
||||
*/
|
||||
constexpr try_to_lock_t try_to_lock = try_to_lock_t();
|
||||
/**
|
||||
* @brief Tag constant for adopt lock strategy.
|
||||
*/
|
||||
constexpr adopt_lock_t adopt_lock = adopt_lock_t();
|
||||
|
||||
/**
|
||||
@ -76,15 +111,24 @@ constexpr adopt_lock_t adopt_lock = adopt_lock_t();
|
||||
*/
|
||||
template <class Mutex>
|
||||
class lock_guard {
|
||||
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* The type of Mutex used by the lock_guard.
|
||||
*/
|
||||
using mutex_type = Mutex;
|
||||
|
||||
/**
|
||||
* @brief Constructs a lock_gurad from a Mutex and locks it.
|
||||
*/
|
||||
inline explicit lock_guard(mutex_type& mtx) : m_mtx(mtx) { m_mtx.lock(); }
|
||||
/**
|
||||
* @brief Constructs a lock_guard from a Mutex, acquireing ownership without
|
||||
* locking it.
|
||||
*/
|
||||
inline lock_guard(mutex_type& mtx, adopt_lock_t) : m_mtx{mtx} {}
|
||||
inline ~lock_guard() { m_mtx.unlock(); }
|
||||
|
||||
private:
|
||||
private:
|
||||
mutex_type& m_mtx;
|
||||
};
|
||||
|
||||
@ -96,18 +140,33 @@ class lock_guard {
|
||||
*/
|
||||
template <class Mutex>
|
||||
class unique_lock {
|
||||
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* The type of Mutex used by the lock.
|
||||
*/
|
||||
using mutex_type = Mutex;
|
||||
|
||||
inline unique_lock() noexcept : m_mtx{nullptr}, m_owns{false} {}
|
||||
/**
|
||||
* @brief Constructs a unique_lock from a Mutex and locks it.
|
||||
*/
|
||||
inline explicit unique_lock(mutex_type& mtx) : m_mtx{&mtx}, m_owns{true} {
|
||||
m_mtx->lock();
|
||||
}
|
||||
/**
|
||||
* @brief Constructs a unique_lock from a Mutex but does not lock it.
|
||||
*/
|
||||
inline unique_lock(mutex_type& mtx, defer_lock_t) noexcept : m_mtx{&mtx},
|
||||
m_owns{false} {}
|
||||
/**
|
||||
* @brief Constructs a unique_lock from a Mutex and tries to lock it.
|
||||
*/
|
||||
inline unique_lock(mutex_type& mtx, try_to_lock_t)
|
||||
: m_mtx{&mtx}, m_owns{mtx.try_lock()} {}
|
||||
/**
|
||||
* @brief Constructs a unique_lock from a Mutex that is already owned by the
|
||||
* thread.
|
||||
*/
|
||||
inline unique_lock(mutex_type& mtx, adopt_lock_t)
|
||||
: m_mtx{&mtx}, m_owns{true} {}
|
||||
inline ~unique_lock() {
|
||||
@ -115,11 +174,17 @@ class unique_lock {
|
||||
m_mtx->unlock();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Move constructor.
|
||||
*/
|
||||
inline unique_lock(unique_lock&& lock) noexcept : m_mtx{lock.m_mtx},
|
||||
m_owns{lock.m_owns} {
|
||||
lock.m_mtx = nullptr;
|
||||
lock.m_owns = false;
|
||||
}
|
||||
/**
|
||||
* @brief Move assignment operator.
|
||||
*/
|
||||
inline unique_lock& operator=(unique_lock&& lock) noexcept {
|
||||
if (m_owns) {
|
||||
m_mtx->unlock();
|
||||
@ -131,16 +196,34 @@ class unique_lock {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Locks the associated mutex.
|
||||
*/
|
||||
void lock();
|
||||
/**
|
||||
* @brief Tries to lock the associated mutex.
|
||||
* @return `true` if the mutex has been locked successfully,
|
||||
* `false` otherwise.
|
||||
*/
|
||||
bool try_lock();
|
||||
|
||||
/**
|
||||
* @brief Unlocks the associated mutex.
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
/**
|
||||
* @brief Swap this unique_lock with another unique_lock.
|
||||
*/
|
||||
inline void swap(unique_lock& lock) noexcept {
|
||||
std::swap(m_mtx, lock.m_mtx);
|
||||
std::swap(m_owns, lock.m_owns);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disassociate this lock from its mutex. The caller is responsible to
|
||||
* unlock the mutex if it was locked before.
|
||||
* @return A pointer to the associated mutex or `nullptr` if there was none.
|
||||
*/
|
||||
inline mutex_type* release() noexcept {
|
||||
mutex_type* mtx = m_mtx;
|
||||
m_mtx = nullptr;
|
||||
@ -148,11 +231,25 @@ class unique_lock {
|
||||
return mtx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Query ownership of the associate mutex.
|
||||
* @return `true` if an associated mutex exists and the lock owns it,
|
||||
* `false` otherwise.
|
||||
*/
|
||||
inline bool owns_lock() const noexcept { return m_owns; }
|
||||
/**
|
||||
* @brief Operator to query the ownership of the associated mutex.
|
||||
* @return `true` if an associated mutex exists and the lock owns it,
|
||||
* `false` otherwise.
|
||||
*/
|
||||
inline explicit operator bool() const noexcept { return m_owns; }
|
||||
/**
|
||||
* @brief Provides access to the associated mutex.
|
||||
* @return A pointer to the associated mutex or nullptr it there was none.
|
||||
*/
|
||||
inline mutex_type* mutex() const noexcept { return m_mtx; }
|
||||
|
||||
private:
|
||||
private:
|
||||
unique_lock(unique_lock const&);
|
||||
unique_lock& operator=(unique_lock const&);
|
||||
|
||||
@ -203,6 +300,11 @@ void unique_lock<Mutex>::unlock() {
|
||||
m_owns = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Swaps two mutexes.
|
||||
* @param[inout] lhs Reference to one mutex.
|
||||
* @param[inout] rhs Reference to the other mutex.
|
||||
*/
|
||||
template <class Mutex>
|
||||
inline void swap(unique_lock<Mutex>& lhs, unique_lock<Mutex>& rhs) noexcept {
|
||||
lhs.swap(rhs);
|
||||
|
@ -45,24 +45,39 @@
|
||||
namespace riot {
|
||||
|
||||
namespace {
|
||||
/**
|
||||
* @brief Identify uninitialized threads.
|
||||
*/
|
||||
constexpr kernel_pid_t thread_uninitialized = -1;
|
||||
/**
|
||||
* @brief The stack size for new threads.
|
||||
*/
|
||||
constexpr size_t stack_size = THREAD_STACKSIZE_MAIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Holds context data for the thread.
|
||||
*/
|
||||
struct thread_data {
|
||||
thread_data() : ref_count{2}, joining_thread{thread_uninitialized} {
|
||||
// nop
|
||||
}
|
||||
/** @cond INTERNAL */
|
||||
std::atomic<unsigned> ref_count;
|
||||
kernel_pid_t joining_thread;
|
||||
char stack[stack_size];
|
||||
/** @endcond */
|
||||
};
|
||||
|
||||
/**
|
||||
* This deleter prevents our thread data from being destroyed if the thread
|
||||
* object is destroyed before the thread had a chance to run
|
||||
* @brief This deleter prevents our thread data from being destroyed if the
|
||||
* thread object is destroyed before the thread had a chance to run.
|
||||
*/
|
||||
struct thread_data_deleter {
|
||||
/**
|
||||
* @brief Called by the deleter of a thread object to manage the lifetime of
|
||||
* the thread internal management data.
|
||||
*/
|
||||
void operator()(thread_data* ptr) {
|
||||
if (--ptr->ref_count == 0) {
|
||||
delete ptr;
|
||||
@ -83,33 +98,60 @@ class thread_id {
|
||||
thread_id id);
|
||||
friend class thread;
|
||||
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* @brief Creates a uninitialized thread id.
|
||||
*/
|
||||
inline thread_id() noexcept : m_handle{thread_uninitialized} {}
|
||||
/**
|
||||
* @brief Create a thread id from a native handle.
|
||||
*/
|
||||
inline thread_id(kernel_pid_t handle) : m_handle{handle} {}
|
||||
|
||||
/**
|
||||
* @brief Comparison operator for thread ids.
|
||||
*/
|
||||
inline bool operator==(thread_id other) noexcept {
|
||||
return m_handle == other.m_handle;
|
||||
}
|
||||
/**
|
||||
* @brief Comparison operator for thread ids.
|
||||
*/
|
||||
inline bool operator!=(thread_id other) noexcept {
|
||||
return !(m_handle == other.m_handle);
|
||||
}
|
||||
/**
|
||||
* @brief Comparison operator for thread ids.
|
||||
*/
|
||||
inline bool operator<(thread_id other) noexcept {
|
||||
return m_handle < other.m_handle;
|
||||
}
|
||||
/**
|
||||
* @brief Comparison operator for thread ids.
|
||||
*/
|
||||
inline bool operator<=(thread_id other) noexcept {
|
||||
return !(m_handle > other.m_handle);
|
||||
}
|
||||
/**
|
||||
* @brief Comparison operator for thread ids.
|
||||
*/
|
||||
inline bool operator>(thread_id other) noexcept {
|
||||
return m_handle > other.m_handle;
|
||||
}
|
||||
/**
|
||||
* @brief Comparison operator for thread ids.
|
||||
*/
|
||||
inline bool operator>=(thread_id other) noexcept {
|
||||
return !(m_handle < other.m_handle);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
kernel_pid_t m_handle;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Enable printing of thread ids using output streams.
|
||||
*/
|
||||
template <class T, class Traits>
|
||||
inline std::basic_ostream<T, Traits>& operator<<(std::basic_ostream
|
||||
<T, Traits>& out,
|
||||
@ -119,9 +161,23 @@ inline std::basic_ostream<T, Traits>& operator<<(std::basic_ostream
|
||||
|
||||
namespace this_thread {
|
||||
|
||||
/**
|
||||
* @brief Access the id of the currently running thread.
|
||||
*/
|
||||
inline thread_id get_id() noexcept { return thread_getpid(); }
|
||||
/**
|
||||
* @brief Yield the currently running thread.
|
||||
*/
|
||||
inline void yield() noexcept { thread_yield(); }
|
||||
/**
|
||||
* @brief Puts the current thread to sleep.
|
||||
* @param[in] ns Duration to sleep in nanoseconds.
|
||||
*/
|
||||
void sleep_for(const std::chrono::nanoseconds& ns);
|
||||
/**
|
||||
* @brief Puts the current thread to sleep.
|
||||
* @param[in] sleep_duration The duration to sleep.
|
||||
*/
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const std::chrono::duration<Rep, Period>& sleep_duration) {
|
||||
using namespace std::chrono;
|
||||
@ -139,6 +195,11 @@ void sleep_for(const std::chrono::duration<Rep, Period>& sleep_duration) {
|
||||
sleep_for(ns);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Puts the current thread to sleep.
|
||||
* @param[in] sleep_time A point in time that specifies when the thread
|
||||
* should wake up.
|
||||
*/
|
||||
inline void sleep_until(const riot::time_point& sleep_time) {
|
||||
mutex mtx;
|
||||
condition_variable cv;
|
||||
@ -149,7 +210,7 @@ inline void sleep_until(const riot::time_point& sleep_time) {
|
||||
}
|
||||
} // namespace this_thread
|
||||
|
||||
/*
|
||||
/**
|
||||
* @brief C++11 compliant implementation of thread, however uses the time
|
||||
* point from out chrono header instead of the specified one
|
||||
* @see <a href="http://en.cppreference.com/w/cpp/thread/thread">
|
||||
@ -157,44 +218,100 @@ inline void sleep_until(const riot::time_point& sleep_time) {
|
||||
* </a>
|
||||
*/
|
||||
class thread {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* @brief The id is of type `thread_id`-
|
||||
*/
|
||||
using id = thread_id;
|
||||
/**
|
||||
* @brief The native handle type is the `kernel_pid_t` of RIOT.
|
||||
*/
|
||||
using native_handle_type = kernel_pid_t;
|
||||
|
||||
/**
|
||||
* @brief Per default, an uninitialized thread is created.
|
||||
*/
|
||||
inline thread() noexcept : m_handle{thread_uninitialized} {}
|
||||
/**
|
||||
* @brief Create a thread from a functor and arguments for it.
|
||||
* @param[in] f Functor to run as a thread.
|
||||
* @param[in] args Arguments passed to the functor.
|
||||
*/
|
||||
template <class F, class... Args>
|
||||
explicit thread(F&& f, Args&&... args);
|
||||
~thread();
|
||||
|
||||
thread(const thread&) = delete;
|
||||
/**
|
||||
* @brief Move constructor.
|
||||
*/
|
||||
inline thread(thread&& t) noexcept : m_handle{t.m_handle} {
|
||||
t.m_handle = thread_uninitialized;
|
||||
std::swap(m_data, t.m_data);
|
||||
}
|
||||
|
||||
~thread();
|
||||
|
||||
thread& operator=(const thread&) = delete;
|
||||
/**
|
||||
* @brief Move assignment operator.
|
||||
*/
|
||||
thread& operator=(thread&&) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Swap threads.
|
||||
* @param[inout] t Thread to swap data with.
|
||||
*/
|
||||
void swap(thread& t) noexcept {
|
||||
std::swap(m_data, t.m_data);
|
||||
std::swap(m_handle, t.m_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Query if the thread is joinable.
|
||||
* @return `true` if the thread is joinable, `false` otherwise.
|
||||
*/
|
||||
inline bool joinable() const noexcept {
|
||||
return m_handle != thread_uninitialized;
|
||||
}
|
||||
/**
|
||||
* @brief Block until the thread finishes. Leads to an error if the thread is
|
||||
* not joinable or a thread joins itself.
|
||||
*/
|
||||
void join();
|
||||
/**
|
||||
* @brief Detaches a thread from its handle and allows it to execute
|
||||
* independently. The thread cleans up its resources when it
|
||||
* finishes.
|
||||
*/
|
||||
void detach();
|
||||
/**
|
||||
* @brief Returns the id of a thread.
|
||||
*/
|
||||
inline id get_id() const noexcept { return m_handle; }
|
||||
/**
|
||||
* @brief Returns the native handle to a thread.
|
||||
*/
|
||||
inline native_handle_type native_handle() noexcept { return m_handle; }
|
||||
|
||||
/**
|
||||
* @brief Returns the number of concurrent threads supported by the
|
||||
* underlying hardware. Since there is no RIOT API to query this
|
||||
* information, the function always returns 1;
|
||||
*/
|
||||
static unsigned hardware_concurrency() noexcept;
|
||||
|
||||
private:
|
||||
kernel_pid_t m_handle;
|
||||
std::unique_ptr<thread_data, thread_data_deleter> m_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Swaps two threads.
|
||||
* @param[inout] lhs Reference to one thread.
|
||||
* @param[inout] rhs Reference to the other thread.
|
||||
*/
|
||||
void swap(thread& lhs, thread& rhs) noexcept;
|
||||
|
||||
/** @cond INTERNAL */
|
||||
template <class Tuple>
|
||||
void* thread_proxy(void* vp) {
|
||||
{ // without this scope, the objects here are not cleaned up corrctly
|
||||
@ -217,6 +334,7 @@ void* thread_proxy(void* vp) {
|
||||
sched_task_exit();
|
||||
return nullptr;
|
||||
}
|
||||
/** @endcond */
|
||||
|
||||
template <class F, class... Args>
|
||||
thread::thread(F&& f, Args&&... args)
|
||||
@ -224,7 +342,7 @@ thread::thread(F&& f, Args&&... args)
|
||||
using namespace std;
|
||||
using func_and_args = tuple
|
||||
<thread_data*, typename decay<F>::type, typename decay<Args>::type...>;
|
||||
std::unique_ptr<func_and_args> p(
|
||||
unique_ptr<func_and_args> p(
|
||||
new func_and_args(m_data.get(), forward<F>(f), forward<Args>(args)...));
|
||||
m_handle = thread_create(
|
||||
m_data->stack, stack_size, THREAD_PRIORITY_MAIN - 1, 0,
|
||||
|
Loading…
Reference in New Issue
Block a user