idfxx 1.0.0
Modern C++23 components for ESP-IDF
Loading...
Searching...
No Matches
task.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Chris Leishman
3
4#pragma once
5
20#include <idfxx/chrono>
21#include <idfxx/cpu>
22#include <idfxx/error>
23#include <idfxx/memory>
24
25#include <chrono>
26#include <freertos/FreeRTOS.h>
27#include <freertos/task.h>
28#include <functional>
29#include <optional>
30#include <string>
31#include <string_view>
32
33namespace idfxx {
34
47class task {
48 struct context;
49
50public:
57 class self {
58 friend class task;
59 explicit self(context* ctx) noexcept
60 : _context(ctx) {}
61
62 public:
63 self(const self&) = delete;
64 self& operator=(const self&) = delete;
65
75
82
91
101
117 bool wait_for(const std::chrono::duration<Rep, Period>& timeout) noexcept {
118 return _take(chrono::ticks(timeout)) != 0;
119 }
120
135 template<typename Clock, typename Duration>
136 bool wait_until(const std::chrono::time_point<Clock, Duration>& deadline) noexcept {
137 auto remaining = deadline - Clock::now();
138 if (remaining <= decltype(remaining)::zero()) {
139 return _take(0) != 0;
140 }
141 return _take(chrono::ticks(remaining)) != 0;
142 }
143
156
173 uint32_t take_for(const std::chrono::duration<Rep, Period>& timeout) noexcept {
174 return _take(chrono::ticks(timeout));
175 }
176
192 template<typename Clock, typename Duration>
193 uint32_t take_until(const std::chrono::time_point<Clock, Duration>& deadline) noexcept {
194 auto remaining = deadline - Clock::now();
195 if (remaining <= decltype(remaining)::zero()) {
196 return _take(0);
197 }
198 return _take(chrono::ticks(remaining));
199 }
200
207
214
224
230 [[nodiscard]] std::string name() const;
231
238
239 private:
240 uint32_t _take(TickType_t ticks) noexcept;
241
242 context* _context;
243 };
244
250 std::string_view name = "task";
251 size_t stack_size = 4096;
253 std::optional<core_id> core_affinity = std::nullopt;
255 };
256
267 [[nodiscard]] explicit task(const config& cfg, std::move_only_function<void(self&)> task_func);
268
279 static void spawn(config cfg, std::move_only_function<void(self&)> task_func);
280
296
297 task(const task&) = delete;
298 task& operator=(const task&) = delete;
299 task(task&& other) noexcept;
300 task& operator=(task&& other) noexcept;
301
310
316 [[nodiscard]] const std::string& name() const noexcept { return _name; }
317
324
335
342
350 [[nodiscard]] bool joinable() const noexcept { return _handle != nullptr; }
351
363
370
371#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
381
388 void resume() { unwrap(try_resume()); }
389#endif
390
400
408
426
427#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
440 void notify() { unwrap(try_notify()); }
441#endif
442
456
479
480#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
489#endif
490
499
500#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
511 void detach() { unwrap(try_detach()); }
512#endif
513
528
529#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
553 void kill() { unwrap(try_kill()); }
554#endif
555
580
581#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
594 void join() { unwrap(try_join()); }
595
608 template<typename Rep, typename Period>
609 void join(const std::chrono::duration<Rep, Period>& timeout) {
611 }
612
625 template<typename Clock, typename Duration>
626 void join_until(const std::chrono::time_point<Clock, Duration>& deadline) {
628 }
629#endif
630
643
658 template<typename Rep, typename Period>
659 [[nodiscard]] result<void> try_join(const std::chrono::duration<Rep, Period>& timeout) {
660 return _try_join(chrono::ticks(timeout));
661 }
662
677 template<typename Clock, typename Duration>
678 [[nodiscard]] result<void> try_join_until(const std::chrono::time_point<Clock, Duration>& deadline) {
679 auto remaining = deadline - Clock::now();
680 if (remaining <= decltype(remaining)::zero()) {
681 return _try_join(0);
682 }
683 return _try_join(chrono::ticks(remaining));
684 }
685
686 // =========================================================================
687 // Static utility methods for current task operations
688 // =========================================================================
689
696
702 [[nodiscard]] static std::string current_name() { return pcTaskGetName(nullptr); }
703
704private:
705 static void trampoline(void* arg);
706
707 static TaskHandle_t _create(context* ctx, const config& cfg, const char* name);
708 [[nodiscard]] result<void> _try_join(TickType_t ticks);
709 void _stop_and_delete() noexcept;
710 [[nodiscard]] bool _is_running() const noexcept;
711
712 explicit task(TaskHandle_t handle, std::string name, context* ctx);
713
714 TaskHandle_t _handle = nullptr;
715 std::string _name;
716 context* _context = nullptr;
717};
718
// end of idfxx_task
720
721} // namespace idfxx
Handle for task self-interaction.
Definition task.hpp:57
task_priority priority() const noexcept
Returns the current task priority.
bool wait_for(const std::chrono::duration< Rep, Period > &timeout) noexcept
Waits for a notification with a timeout (binary semaphore pattern).
Definition task.hpp:117
bool wait_until(const std::chrono::time_point< Clock, Duration > &deadline) noexcept
Waits for a notification until a deadline (binary semaphore pattern).
Definition task.hpp:136
bool stop_requested() const noexcept
Checks if a stop has been requested for this task.
void set_priority(task_priority new_priority) noexcept
Changes the current task priority.
uint32_t take_for(const std::chrono::duration< Rep, Period > &timeout) noexcept
Takes accumulated notifications with a timeout (counting semaphore pattern).
Definition task.hpp:173
uint32_t take_until(const std::chrono::time_point< Clock, Duration > &deadline) noexcept
Takes accumulated notifications until a deadline (counting semaphore pattern).
Definition task.hpp:193
self(const self &)=delete
TaskHandle_t idf_handle() const noexcept
Returns the FreeRTOS handle of the current task.
bool is_detached() const noexcept
Checks if the current task has been detached.
self & operator=(const self &)=delete
uint32_t take() noexcept
Takes accumulated notifications (counting semaphore pattern).
void wait() noexcept
Waits for a notification (binary semaphore pattern).
size_t stack_high_water_mark() const noexcept
Returns the minimum free stack space (in bytes) since the task started.
std::string name() const
Returns the current task name.
void suspend() noexcept
Suspends the current task.
Type-safe wrapper for FreeRTOS task priority values.
Definition cpu.hpp:84
Task lifecycle management.
Definition task.hpp:47
result< void > try_resume()
Resumes a suspended task.
void join(const std::chrono::duration< Rep, Period > &timeout)
Blocks until the task function completes or the timeout expires.
Definition task.hpp:609
static TaskHandle_t current_handle() noexcept
Returns the handle of the currently executing task.
Definition task.hpp:695
void join()
Blocks until the task function completes.
Definition task.hpp:594
result< void > try_detach()
Releases ownership of the task.
void notify()
Sends a notification to the task.
Definition task.hpp:440
const std::string & name() const noexcept
Returns the task name.
Definition task.hpp:316
bool notify_from_isr() noexcept
Sends a notification to the task from ISR context.
void resume()
Resumes a suspended task.
Definition task.hpp:388
result< void > try_join()
Blocks until the task function completes.
task_priority priority() const noexcept
Returns the current task priority.
task & operator=(const task &)=delete
void detach()
Releases ownership of the task.
Definition task.hpp:511
void suspend()
Suspends the task.
Definition task.hpp:380
result< void > try_kill()
Immediately terminates the task without waiting for completion.
result< void > try_join_until(const std::chrono::time_point< Clock, Duration > &deadline)
Blocks until the task function completes or the deadline is reached.
Definition task.hpp:678
static void spawn(config cfg, std::move_only_function< void(self &)> task_func)
Creates a fire-and-forget task with a std::move_only_function callback.
task(const task &)=delete
void kill()
Immediately terminates the task without waiting for completion.
Definition task.hpp:553
task(task &&other) noexcept
result< void > try_notify()
Sends a notification to the task.
static std::string current_name()
Returns the name of the currently executing task.
Definition task.hpp:702
result< void > try_join(const std::chrono::duration< Rep, Period > &timeout)
Blocks until the task function completes or the timeout expires.
Definition task.hpp:659
bool is_completed() const noexcept
Checks if the task function has returned.
bool joinable() const noexcept
Checks if this task object owns the task.
Definition task.hpp:350
result< void > try_set_priority(task_priority new_priority)
Changes the task priority.
~task()
Destroys the task, requesting stop and blocking until the task function completes.
bool request_stop() noexcept
Requests the task to stop.
void set_priority(task_priority new_priority)
Changes the task priority.
Definition task.hpp:488
bool resume_from_isr() noexcept
Resumes a suspended task from ISR context.
result< void > try_suspend()
Suspends the task.
TaskHandle_t idf_handle() const noexcept
Returns the underlying FreeRTOS task handle.
Definition task.hpp:309
task(const config &cfg, std::move_only_function< void(self &)> task_func)
Creates a task with a std::move_only_function callback.
task & operator=(task &&other) noexcept
void join_until(const std::chrono::time_point< Clock, Duration > &deadline)
Blocks until the task function completes or the deadline is reached.
Definition task.hpp:626
constexpr TickType_t ticks(const std::chrono::duration< Rep, Period > &d)
Converts a std::chrono duration to TickType_t ticks.
Definition chrono.hpp:33
@ dram
Internal DRAM (8-bit accessible)
T unwrap(result< T > result)
Throws a std::system_error if the result is an error.
Definition error.hpp:307
@ timeout
Operation timed out.
std::expected< T, std::error_code > result
result type wrapping a value or error code.
Definition error.hpp:120
Task configuration parameters.
Definition task.hpp:249