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#include <system_error>
33#include <type_traits>
34#include <utility>
35
36namespace idfxx {
37
50class task {
51 struct context;
52
53public:
68 enum class errc : esp_err_t {
69 would_deadlock = 1,
70 };
71
76 class error_category : public std::error_category {
77 public:
80
82 [[nodiscard]] std::string message(int ec) const override final;
83
92 };
93
101 friend class task;
102 explicit self(context* ctx) noexcept
103 : _context(ctx) {}
104
105 public:
106 self(const self&) = delete;
107 self& operator=(const self&) = delete;
108
118
125
134
143 void wait() noexcept;
144
160 bool wait_for(const std::chrono::duration<Rep, Period>& timeout) noexcept {
161 return _take(chrono::ticks(timeout)) != 0;
162 }
163
178 template<typename Clock, typename Duration>
179 bool wait_until(const std::chrono::time_point<Clock, Duration>& deadline) noexcept {
180 auto remaining = deadline - Clock::now();
181 if (remaining <= decltype(remaining)::zero()) {
182 return _take(0) != 0;
183 }
184 return _take(chrono::ticks(remaining)) != 0;
185 }
186
199
216 uint32_t take_for(const std::chrono::duration<Rep, Period>& timeout) noexcept {
217 return _take(chrono::ticks(timeout));
218 }
219
235 template<typename Clock, typename Duration>
236 uint32_t take_until(const std::chrono::time_point<Clock, Duration>& deadline) noexcept {
237 auto remaining = deadline - Clock::now();
238 if (remaining <= decltype(remaining)::zero()) {
239 return _take(0);
240 }
241 return _take(chrono::ticks(remaining));
242 }
243
250
257
267
273 [[nodiscard]] std::string name() const;
274
281
282 private:
283 uint32_t _take(TickType_t ticks) noexcept;
284
285 context* _context;
286 };
287
293 std::string_view name = "task";
294 size_t stack_size = 4096;
296 std::optional<core_id> core_affinity = std::nullopt;
298 };
299
310 [[nodiscard]] explicit task(const config& cfg, std::move_only_function<void(self&)> task_func);
311
322 static void spawn(config cfg, std::move_only_function<void(self&)> task_func);
323
339
340 task(const task&) = delete;
341 task& operator=(const task&) = delete;
342 task(task&& other) noexcept;
343 task& operator=(task&& other) noexcept;
344
353
359 [[nodiscard]] const std::string& name() const noexcept { return _name; }
360
367
378
385
393 [[nodiscard]] bool joinable() const noexcept { return _handle != nullptr; }
394
406
413
414#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
424
431 void resume() { unwrap(try_resume()); }
432#endif
433
443
451
469
470#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
483 void notify() { unwrap(try_notify()); }
484#endif
485
499
522
523#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
532#endif
533
542
543#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
554 void detach() { unwrap(try_detach()); }
555#endif
556
571
572#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
596 void kill() { unwrap(try_kill()); }
597#endif
598
623
624#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
638 void join() { unwrap(try_join()); }
639
653 template<typename Rep, typename Period>
654 void join(const std::chrono::duration<Rep, Period>& timeout) {
656 }
657
671 template<typename Clock, typename Duration>
672 void join_until(const std::chrono::time_point<Clock, Duration>& deadline) {
674 }
675#endif
676
691
708 template<typename Rep, typename Period>
709 [[nodiscard]] result<void> try_join(const std::chrono::duration<Rep, Period>& timeout) {
710 return _try_join(chrono::ticks(timeout));
711 }
712
729 template<typename Clock, typename Duration>
730 [[nodiscard]] result<void> try_join_until(const std::chrono::time_point<Clock, Duration>& deadline) {
731 auto remaining = deadline - Clock::now();
732 if (remaining <= decltype(remaining)::zero()) {
733 return _try_join(0);
734 }
735 return _try_join(chrono::ticks(remaining));
736 }
737
738 // =========================================================================
739 // Static utility methods for current task operations
740 // =========================================================================
741
748
754 [[nodiscard]] static std::string current_name() { return pcTaskGetName(nullptr); }
755
756private:
757 static void trampoline(void* arg);
758
759 static TaskHandle_t _create(context* ctx, const config& cfg, const char* name);
760 [[nodiscard]] result<void> _try_join(TickType_t ticks);
761 void _stop_and_delete() noexcept;
762 [[nodiscard]] bool _is_running() const noexcept;
763
764 explicit task(TaskHandle_t handle, std::string name, context* ctx);
765
766 TaskHandle_t _handle = nullptr;
767 std::string _name;
768 context* _context = nullptr;
769};
770
777
786 return {std::to_underlying(e), task_category()};
787}
788
// end of idfxx_task
790
791} // namespace idfxx
792
794namespace std {
795template<>
796struct is_error_code_enum<idfxx::task::errc> : true_type {};
797} // namespace std
Error category for IDFXX and ESP-IDF error codes.
Definition error.hpp:72
Error category for task errors.
Definition task.hpp:76
const char * name() const noexcept override final
Returns the name of the error category.
bool equivalent(int code, const std::error_condition &condition) const noexcept override final
Tests whether an errc value is equivalent to a standard condition.
std::string message(int ec) const override final
Returns a human-readable message for the given error code.
Handle for task self-interaction.
Definition task.hpp:100
task_priority priority() const noexcept
Returns the current task priority.
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:179
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:236
self(const self &)=delete
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).
Type-safe wrapper for FreeRTOS task priority values.
Definition cpu.hpp:84
Task lifecycle management.
Definition task.hpp:50
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:654
static TaskHandle_t current_handle() noexcept
Returns the handle of the currently executing task.
Definition task.hpp:747
void join()
Blocks until the task function completes.
Definition task.hpp:638
result< void > try_detach()
Releases ownership of the task.
void notify()
Sends a notification to the task.
Definition task.hpp:483
const std::string & name() const noexcept
Returns the task name.
Definition task.hpp:359
bool stop_requested() const noexcept
Checks if a stop has been requested for this task.
errc
Error codes for task operations.
Definition task.hpp:68
bool notify_from_isr() noexcept
Sends a notification to the task from ISR context.
void resume()
Resumes a suspended task.
Definition task.hpp:431
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:554
void suspend()
Suspends the task.
Definition task.hpp:423
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:730
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:596
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:754
result< void > try_join(const std::chrono::duration< Rep, Period > &timeout)
Blocks until the task function completes or the timeout expires.
Definition task.hpp:709
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:393
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:531
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:352
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:672
size_t stack_high_water_mark() const noexcept
Returns the minimum free stack space (in bytes) since the task started.
constexpr TickType_t ticks(const std::chrono::duration< Rep, Period > &d)
Converts a std::chrono duration to TickType_t ticks.
Definition chrono.hpp:33
int esp_err_t
Definition error.hpp:35
@ dram
Internal DRAM (8-bit accessible)
const task::error_category & task_category() noexcept
Returns a reference to the task error category singleton.
std::error_code make_error_code(errc e) noexcept
Creates a std::error_code from an idfxx::errc value.
Definition error.hpp:101
T unwrap(result< T > result)
Throws a std::system_error if the result is an error.
Definition error.hpp:307
errc
IDFXX error codes.
Definition error.hpp:46
@ 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:292