21#include <idfxx/chrono>
58#define IDFXX_EVENT_DEFINE_BASE(name, id_enum) \
59 inline constexpr char _##name##_base[] = #name; \
60 inline constexpr ::idfxx::event_base<id_enum> name{_##name##_base}; \
61 constexpr ::idfxx::event_base<id_enum> idfxx_get_event_base(id_enum*) { \
67template<
typename IdEnum>
89template<
typename IdEnum>
147 { T::from_opaque(data) } -> std::same_as<T>;
193template<
typename IdEnum,
typename DataType =
void>
196 static_assert(
sizeof(
IdEnum) <=
sizeof(
int32_t),
"event ID enum must fit in int32_t");
210template<
typename IdEnum>
224 if constexpr (
requires {
225 { T::from_opaque(data) } -> std::same_as<T>;
227 return T::from_opaque(data);
229 return *
static_cast<const T*
>(
data);
236template<
typename DataType>
238 using type = std::move_only_function<
void(
const DataType&)
const>;
243 using type = std::move_only_function<
void()
const>;
309#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
360 size_t stack_size = 2048;
367 std::optional<core_id> core_affinity = std::nullopt;
370#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
400#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
427 template<
typename IdEnum,
typename DataType>
444 template<
typename IdEnum>
460 template<
typename IdEnum,
typename DataType>
476 template<
typename IdEnum>
484#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
507#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
521 template<
typename IdEnum>
538 template<
typename IdEnum,
typename Rep,
typename Period>
558 template<
typename IdEnum,
typename DataType>
578 template<
typename IdEnum,
typename DataType,
typename Rep,
typename Period>
592 template<
typename IdEnum>
607 template<
typename IdEnum,
typename Rep,
typename Period>
625 template<
typename IdEnum,
typename DataType>
647 template<
typename IdEnum,
typename DataType,
typename Rep,
typename Period>
697 template<
typename IdEnum>
716 bool _system =
false;
785 if (
this != &other) {
850#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
874#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
890 template<
typename Rep,
typename Period>
891 void run(
const std::chrono::duration<Rep, Period>& duration) {
892 unwrap(try_run(duration));
906 template<
typename Rep,
typename Period>
908 if (idf_handle() ==
nullptr) {
909 return error(errc::invalid_state);
930#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
931template<
typename IdEnum,
typename DataType>
933 return unwrap(try_listener_add(
event, std::move(callback)));
936template<
typename IdEnum>
939 return unwrap(try_listener_add(
base, std::move(callback)));
943 unwrap(try_listener_remove(handle));
947template<
typename IdEnum>
959template<
typename IdEnum,
typename DataType>
962 if (!_system && _handle ==
nullptr) {
965 if constexpr (std::is_void_v<DataType>) {
966 return register_listener(
973 return register_listener(
982template<
typename IdEnum>
985 if (!_system && _handle ==
nullptr) {
Typed event base template.
constexpr esp_event_base_t idf_base() const noexcept
Returns the underlying ESP-IDF event base.
constexpr event_base(esp_event_base_t base) noexcept
Constructs from an ESP-IDF event base pointer.
IdEnum id_type
The enum type for event IDs.
Handle to a registered event listener.
listener_handle()=default
Default constructor creates an invalid handle.
RAII handle for event listener registration.
unique_listener_handle() noexcept=default
Constructs an empty handle.
unique_listener_handle & operator=(unique_listener_handle &&other) noexcept
Move assignment.
listener_handle release() noexcept
Releases ownership without removing the listener.
unique_listener_handle(const unique_listener_handle &)=delete
~unique_listener_handle()
Destructor.
unique_listener_handle & operator=(const unique_listener_handle &)=delete
unique_listener_handle(unique_listener_handle &&other) noexcept
Move constructor.
void reset() noexcept
Removes the listener and resets to empty.
Base class for event loops.
void post(event< IdEnum > evt)
Posts an event without data, waiting indefinitely.
static result< event_loop > make(task_config task, size_t queue_size=32)
Creates an event loop with a dedicated dispatch task.
result< void > try_listener_remove(listener_handle handle)
Removes a listener by handle.
event_loop(task_config task, size_t queue_size=32)
Creates an event loop with a dedicated dispatch task.
void post(event< IdEnum, DataType > evt, const DataType &data, const std::chrono::duration< Rep, Period > &timeout)
Posts an event with data, with a timeout.
result< void > try_post(event< IdEnum, DataType > evt, const DataType &data, const std::chrono::duration< Rep, Period > &timeout)
Posts an event with data, with a timeout.
static void destroy_system()
Destroys the system (default) event loop.
result< void > try_post(event< IdEnum > evt)
Posts an event without data, waiting indefinitely.
esp_event_loop_handle_t idf_handle() const
Returns the underlying ESP-IDF event loop handle.
static void create_system()
Creates the system (default) event loop.
event_loop & operator=(const event_loop &)=delete
event_loop(event_loop &&other) noexcept
Move constructor.
static event_loop & system()
Returns a reference to the system (default) event loop.
static result< void > try_destroy_system()
Destroys the system (default) event loop.
static result< void > try_create_system()
Creates the system (default) event loop.
event_loop(const event_loop &)=delete
result< void > try_post(event< IdEnum > evt, const std::chrono::duration< Rep, Period > &timeout)
Posts an event without data, with a timeout.
void post(event< IdEnum, DataType > evt, const DataType &data)
Posts an event with data, waiting indefinitely.
result< void > try_post(event< IdEnum, DataType > evt, const DataType &data)
Posts an event with data, waiting indefinitely.
event_loop & operator=(event_loop &&other) noexcept
Move assignment.
event_loop(esp_event_loop_handle_t handle, bool system=false)
Constructs an event_loop with the given handle.
void post(event< IdEnum > evt, const std::chrono::duration< Rep, Period > &timeout)
Posts an event without data, with a timeout.
Type-safe wrapper for FreeRTOS task priority values.
Task lifecycle management.
User-created event loop with manual dispatch.
result< void > try_run(const std::chrono::duration< Rep, Period > &duration)
Dispatches pending events.
user_event_loop & operator=(const user_event_loop &)=delete
static result< user_event_loop > make(size_t queue_size=32)
Creates a user event loop without a dedicated task.
user_event_loop(size_t queue_size)
Creates a user event loop without a dedicated task.
user_event_loop(user_event_loop &&) noexcept=default
user_event_loop(const user_event_loop &)=delete
void run(const std::chrono::duration< Rep, Period > &duration)
Dispatches pending events.
Concept for types that can be both received and posted as event data.
Concept for types that can be received as event data.
constexpr TickType_t ticks(const std::chrono::duration< Rep, Period > &d)
Converts a std::chrono duration to TickType_t ticks.
result< listener_handle > try_listener_add(event< IdEnum, DataType > event, event_handler< DataType > callback)
Registers a type-safe listener for a specific event.
void listener_remove(listener_handle handle)
Removes a listener by handle.
std::move_only_function< void(event_base< IdEnum > base, IdEnum id, void *event_data) const > opaque_event_handler
Callback type for wildcard event listeners.
typename event_handler_traits< DataType >::type event_handler
Handler type for typed event listeners.
listener_handle listener_add(event< IdEnum, DataType > event, event_handler< DataType > callback)
Registers a type-safe listener for a specific event.
@ base
Base (factory) MAC address.
constexpr std::unexpected< std::error_code > error(E e) noexcept
Creates an unexpected error from an error code enum.
T unwrap(result< T > result)
Throws a std::system_error if the result is an error.
@ invalid_state
Invalid state.
@ timeout
Operation timed out.
std::expected< T, std::error_code > result
result type wrapping a value or error code.
result< void > wrap(esp_err_t e)
Wraps an esp_err_t into a result<void>.
Configuration for a dedicated event dispatch task.
std::string_view name
Name of the task.
A typed event that pairs an event ID with its data type.