7 #ifndef ZPP_INCLUDE_ZPP_THREAD_HPP
8 #define ZPP_INCLUDE_ZPP_THREAD_HPP
20 #include <zephyr/kernel.h>
21 #include <zephyr/sys/__assert.h>
22 #include <zephyr/sys/util.h>
35 namespace this_thread {
44 return ::zpp::thread_id(k_current_get());
60 template<
class T_Rep,
class T_Period>
62 busy_wait_for(
const std::chrono::duration<T_Rep, T_Period>& wait_duration)
64 using namespace std::chrono;
66 microseconds us = duration_cast<microseconds>(wait_duration);
67 k_busy_wait(us.count());
75 template<
class T_Rep,
class T_Period >
77 sleep_for(
const std::chrono::duration<T_Rep, T_Period>& sleep_duration)
79 auto res = k_sleep(
to_timeout(sleep_duration));
81 return std::chrono::milliseconds(res);
89 template<
class T_Clock,
class T_Duration>
91 sleep_until(
const std::chrono::time_point<T_Clock, T_Duration>& sleep_time)
93 using namespace std::chrono;
96 while ( (dt = sleep_time - T_Clock::now()) > T_Duration::zero()) {
106 k_thread_abort(k_current_get());
114 k_thread_suspend(k_current_get());
124 return thread_prio( k_thread_priority_get(k_current_get()) );
134 k_thread_priority_set(k_current_get(), prio.native_value());
139 template <
class T>
typename std::decay<T>::type
decay_copy(T&& v) noexcept
141 return std::forward<T>(v);
149 template<
typename T_CallInfo>
150 static void callback_helper(
void* a1,
void* a2,
void* a3) noexcept
155 auto cip =
reinterpret_cast<T_CallInfo*
>(a1);
156 __ASSERT_NO_MSG(cip !=
nullptr);
158 auto f = std::move(cip->m_f);
159 auto args = std::move(cip->m_args);
161 auto heap = cip->m_heap;
163 std::destroy_at(cip);
166 std::apply(f, std::move(args));
169 template<
typename T_Callback,
typename T_CallbackArg>
170 static void callback_helper(
void* a1,
void* a2,
void* a3) noexcept
174 auto f =
reinterpret_cast<T_Callback
>(a1);
175 __ASSERT_NO_MSG(f !=
nullptr);
177 auto arg =
reinterpret_cast<T_CallbackArg*
>(&a2);
178 __ASSERT_NO_MSG(arg !=
nullptr);
180 std::invoke(*f, *arg);
183 template<
typename T_Callback>
184 static void callback_helper_void(
void* a1,
void* a2,
void* a3) noexcept
189 auto f =
reinterpret_cast<T_Callback
>(a1);
190 __ASSERT_NO_MSG(f !=
nullptr);
221 template<
typename T_Heap,
typename T_Callback,
typename... T_CallbackArgs,
222 std::enable_if_t<std::is_nothrow_invocable_v<T_Callback, T_CallbackArgs...>,
bool> =
true
230 T_CallbackArgs&&... args) noexcept
232 typedef typename std::decay<T_Heap>::type CallInfoHeap;
233 typedef typename std::decay<T_Callback>::type CallInfoF;
234 typedef std::tuple<typename std::decay<T_CallbackArgs>::type...> CallInfoArgs;
236 static_assert(std::is_invocable_v<T_Callback, T_CallbackArgs...>);
237 static_assert(std::is_nothrow_invocable_v<T_Callback, T_CallbackArgs...>);
240 CallInfoHeap* m_heap;
249 auto cip = std::construct_at(
reinterpret_cast<call_info*
>(vp),
254 __ASSERT_NO_MSG(cip !=
nullptr);
256 auto tid = k_thread_create(
260 &callback_helper<call_info>,
261 reinterpret_cast<void*
>(cip),
265 attr.native_options(),
266 attr.native_delay());
281 template<
typename T_Callback,
typename T_CallbackArg,
282 std::enable_if_t<std::is_nothrow_invocable_v<T_Callback, T_CallbackArg>,
bool> =
true
289 T_CallbackArg arg) noexcept
291 using func_t = void (*)(T_CallbackArg) noexcept;
293 static_assert(
sizeof(T_CallbackArg) <=
sizeof(
void*));
294 static_assert(std::is_invocable_v<T_Callback, T_CallbackArg>);
295 static_assert(std::is_nothrow_invocable_v<T_Callback, T_CallbackArg>);
296 static_assert(std::is_invocable_v<func_t, T_CallbackArg>);
297 static_assert(std::is_nothrow_invocable_v<func_t, T_CallbackArg>);
298 static_assert(
sizeof(func_t) <=
sizeof(
void*));
299 static_assert(
alignof(T_CallbackArg) <=
alignof(
void*));
300 static_assert(std::is_trivial_v<T_CallbackArg>);
305 std::construct_at(
reinterpret_cast<T_CallbackArg*
>(&arg_vp), arg);
307 auto tid = k_thread_create(
311 &callback_helper<func_t, T_CallbackArg>,
312 reinterpret_cast<void*
>(fp),
316 attr.native_options(),
317 attr.native_delay());
331 template<
typename T_Callback,
332 std::enable_if_t<std::is_nothrow_invocable_v<T_Callback>,
bool> =
true
338 T_Callback f) noexcept
340 using func_t = void (*)() noexcept;
342 static_assert(std::is_invocable_v<T_Callback>);
343 static_assert(std::is_nothrow_invocable_v<T_Callback>);
344 static_assert(std::is_invocable_v<func_t>);
345 static_assert(std::is_nothrow_invocable_v<func_t>);
346 static_assert(
sizeof(func_t) <=
sizeof(
void*));
350 auto tid = k_thread_create(
354 &callback_helper_void<func_t>,
355 reinterpret_cast<void*
>(fp),
359 attr.native_options(),
360 attr.native_delay());
398 k_thread_abort(m_tid.native_handle());
407 constexpr
explicit operator bool() const noexcept {
427 k_wakeup(m_tid.native_handle());
442 k_thread_start(m_tid.native_handle());
457 k_thread_abort(m_tid.native_handle());
473 k_thread_resume(m_tid.native_handle());
483 [[nodiscard]]
auto join() noexcept
488 auto rc = k_thread_join(m_tid.native_handle(), K_FOREVER);
507 k_thread_suspend(m_tid.native_handle());
524 res =
thread_prio( k_thread_priority_get(m_tid.native_handle()) );
540 k_thread_priority_set(m_tid.native_handle(), prio.native_value());
552 [[nodiscard]]
auto set_name(
const char* name) noexcept
557 auto rc = k_thread_name_set(m_tid.native_handle(), name);
573 [[nodiscard]]
auto name() const noexcept
578 auto rc = k_thread_name_get(m_tid.native_handle());
void * try_allocate(size_t bytes) noexcept
Allocate memory from this heap without waiting.
void deallocate(void *mem) noexcept
Deallocate memory previously allocated.
helper class for error result
void assign_value(const T_Ok &v) noexcept
void assign_error(const T_Error &e) noexcept
Thread creation attributes.
thread_data holds the stack and thread control block memory
constexpr static thread_id any() noexcept
Create an ID with value K_ANY.
thread_stack holds the stack and thread control block memory
The class thread repecents a single Zephyr thread.
auto set_priority(thread_prio prio) const noexcept
Set priority of the thread this object mamages.
auto suspend() noexcept
suspend the thread this object mamages.
constexpr thread(thread_data &td, thread_stack &&tstack, const thread_attr &attr, T_Callback f, T_CallbackArg arg) noexcept
Creates a object which represents a new Zephyr thread.
constexpr thread(thread_data &td, thread_stack &&tstack, const thread_attr &attr, T_Callback f) noexcept
Creates a object which represents a new Zephyr thread.
auto name() const noexcept
Get name of the thread this object mamages.
constexpr thread(thread &&other) noexcept
Move constructor.
auto join() noexcept
join the thread this object mamages.
constexpr thread(thread_data &td, thread_stack &&tstack, const thread_attr &attr, T_Heap *heap, T_Callback &&f, T_CallbackArgs &&... args) noexcept
Creates a object which represents a new Zephyr thread.
constexpr thread() noexcept
Creates a object which doesn't represent a Zephyr thread.
auto priority() noexcept
Get priority of the thread this object mamages.
auto start() noexcept
start the thread this object mamages.
auto wakeup() noexcept
wakeup the thread this object mamages.
auto abort() noexcept
abort the thread this object mamages.
constexpr thread(thread_id tid) noexcept
Creates a object which represents Zephyr thread with tid.
auto set_name(const char *name) noexcept
Set name of the thread this object mamages.
thread & operator=(const thread &)=delete
auto resume() noexcept
resume the thread this object mamages.
constexpr void detach() noexcept
Detach this object from the thread.
~thread() noexcept
Destructor, will abort the thread.
constexpr thread & operator=(thread &&other) noexcept
Move assignment operator.
thread(const thread &)=delete
void sleep_until(const std::chrono::time_point< T_Clock, T_Duration > &sleep_time)
Suspend the current thread until a specified time point.
void set_priority(thread_prio prio) noexcept
Set the current thread's priority.
auto get_id() noexcept
Get the thread ID of the current thread.
void suspend() noexcept
Suspend the current thread.
auto sleep_for(const std::chrono::duration< T_Rep, T_Period > &sleep_duration)
Suspend the current thread for a specified time duration.
void abort() noexcept
Abort the current thread.
void yield() noexcept
Yield the current thread.
thread_prio get_priority() noexcept
Get the current thread's priority.
void busy_wait_for(const std::chrono::duration< T_Rep, T_Period > &wait_duration)
Busy wait for a specified time duration.
constexpr error_code to_error_code(int v) noexcept
constexpr k_timeout_t to_timeout(const std::chrono::duration< T_Rep, T_Period > &d) noexcept
convert a duration to tick
std::decay< T >::type decay_copy(T &&v) noexcept
@ k_notsup
Unsupported value.
@ k_inval
Invalid argument.