23#include <idfxx/chrono>
29#include <freertos/FreeRTOS.h>
30#include <freertos/event_groups.h>
82 requires(
sizeof(std::underlying_type_t<E>) <=
sizeof(EventBits_t))
91 : _handle(xEventGroupCreate()) {
92 if (_handle ==
nullptr) {
104 if (_handle !=
nullptr) {
105 vEventGroupDelete(_handle);
114 : _handle(std::exchange(other._handle,
nullptr)) {}
118 if (
this != &other) {
119 if (_handle !=
nullptr) {
120 vEventGroupDelete(_handle);
122 _handle = std::exchange(other._handle,
nullptr);
144 if (_handle ==
nullptr) {
147 return _from_bits(xEventGroupSetBits(_handle,
to_underlying(bits)));
163 if (_handle ==
nullptr) {
166 return _from_bits(xEventGroupClearBits(_handle,
to_underlying(bits)));
179 if (_handle ==
nullptr) {
182 return _from_bits(xEventGroupGetBits(_handle));
189#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
206 return unwrap(try_wait(bits, mode, clear_on_exit));
225 template<
typename Rep,
typename Period>
247 template<
typename Rep,
typename Period>
268 template<
typename Clock,
typename Duration>
272 const std::chrono::time_point<Clock, Duration>& deadline,
273 bool clear_on_exit =
true
275 return unwrap(try_wait_until(bits, mode, deadline, clear_on_exit));
294 template<
typename Clock,
typename Duration>
296 wait_until(
flags<E> bits,
const std::chrono::time_point<Clock, Duration>& deadline,
bool clear_on_exit =
true) {
315 return _try_wait(bits, mode, clear_on_exit, portMAX_DELAY);
332 template<
typename Rep,
typename Period>
336 const std::chrono::duration<Rep, Period>&
timeout,
337 bool clear_on_exit =
true
356 template<
typename Rep,
typename Period>
376 template<
typename Clock,
typename Duration>
380 const std::chrono::time_point<Clock, Duration>& deadline,
381 bool clear_on_exit =
true
383 auto remaining = deadline - Clock::now();
384 if (remaining <=
decltype(remaining)::zero()) {
385 return _try_wait(bits, mode, clear_on_exit, 0);
387 return _try_wait(bits, mode, clear_on_exit,
chrono::ticks(remaining));
404 template<
typename Clock,
typename Duration>
407 return try_wait_until(bits,
wait_mode::all, deadline, clear_on_exit);
414#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
449 template<
typename Rep,
typename Period>
469 template<
typename Clock,
typename Duration>
472 return unwrap(try_sync_until(set_bits, wait_bits, deadline));
492 return _try_sync(set_bits, wait_bits, portMAX_DELAY);
508 template<
typename Rep,
typename Period>
527 template<
typename Clock,
typename Duration>
530 auto remaining = deadline - Clock::now();
531 if (remaining <=
decltype(remaining)::zero()) {
532 return _try_sync(set_bits, wait_bits, 0);
534 return _try_sync(set_bits, wait_bits,
chrono::ticks(remaining));
572 if (_handle ==
nullptr) {
573 return {
false,
false};
575 BaseType_t woken = pdFALSE;
576 BaseType_t ret = xEventGroupSetBitsFromISR(_handle,
to_underlying(bits), &woken);
577 return {ret == pdPASS, woken == pdTRUE};
593 if (_handle ==
nullptr) {
596 return _from_bits(xEventGroupClearBitsFromISR(_handle,
to_underlying(bits)));
605 if (_handle ==
nullptr) {
608 return _from_bits(xEventGroupGetBitsFromISR(_handle));
623 [[nodiscard]] EventGroupHandle_t
idf_handle() const noexcept {
return _handle; }
626 static flags<E> _from_bits(EventBits_t bits)
noexcept {
627 return flags<E>(
static_cast<std::underlying_type_t<E>
>(bits));
630 [[nodiscard]] result<flags<E>> _try_wait(flags<E> bits,
wait_mode mode,
bool clear_on_exit, TickType_t ticks) {
631 if (_handle ==
nullptr) {
634 EventBits_t result_bits = xEventGroupWaitBits(
637 clear_on_exit ? pdTRUE : pdFALSE,
641 auto result_flags = _from_bits(result_bits);
642 bool satisfied = (
mode ==
wait_mode::all) ? result_flags.contains(bits) : result_flags.contains_any(bits);
649 [[nodiscard]] result<flags<E>> _try_sync(flags<E> set_bits, flags<E> wait_bits, TickType_t ticks) {
650 if (_handle ==
nullptr) {
654 auto result_flags = _from_bits(result_bits);
655 if (!result_flags.contains(wait_bits)) {
661 EventGroupHandle_t _handle =
nullptr;
Type-safe inter-task event group for bit-level synchronization.
flags< E > get() const noexcept
Returns the current event bits.
flags< E > sync(flags< E > set_bits, flags< E > wait_bits, const std::chrono::duration< Rep, Period > &timeout)
Atomically sets bits and waits for other bits, with a timeout.
result< flags< E > > try_wait(flags< E > bits, wait_mode mode, const std::chrono::duration< Rep, Period > &timeout, bool clear_on_exit=true)
Waits for event bits to be set, with a timeout.
flags< E > wait_until(flags< E > bits, const std::chrono::time_point< Clock, Duration > &deadline, bool clear_on_exit=true)
Waits for event bits to be set, with a deadline (mode defaults to all).
flags< E > clear(flags< E > bits) noexcept
Clears event bits in the event group.
flags< E > IRAM_ATTR clear_from_isr(flags< E > bits) noexcept
Clears event bits from ISR context.
result< flags< E > > try_sync(flags< E > set_bits, flags< E > wait_bits)
Atomically sets bits and waits for other bits, blocking indefinitely.
flags< E > sync(flags< E > set_bits, flags< E > wait_bits)
Atomically sets bits and waits for other bits, blocking indefinitely.
result< flags< E > > try_wait_until(flags< E > bits, const std::chrono::time_point< Clock, Duration > &deadline, bool clear_on_exit=true)
Waits for event bits to be set, with a deadline (mode defaults to all).
flags< E > wait(flags< E > bits, wait_mode mode=wait_mode::all, bool clear_on_exit=true)
Waits for event bits to be set, blocking indefinitely.
EventGroupHandle_t idf_handle() const noexcept
Returns the underlying FreeRTOS event group handle.
flags< E > IRAM_ATTR get_from_isr() const noexcept
Returns the current event bits from ISR context.
flags< E > sync_until(flags< E > set_bits, flags< E > wait_bits, const std::chrono::time_point< Clock, Duration > &deadline)
Atomically sets bits and waits for other bits, with a deadline.
result< flags< E > > try_sync_until(flags< E > set_bits, flags< E > wait_bits, const std::chrono::time_point< Clock, Duration > &deadline)
Atomically sets bits and waits for other bits, with a deadline.
~event_group()
Destroys the event group and releases all resources.
event_group(const event_group &)=delete
flags< E > set(flags< E > bits) noexcept
Sets event bits in the event group.
result< flags< E > > try_sync(flags< E > set_bits, flags< E > wait_bits, const std::chrono::duration< Rep, Period > &timeout)
Atomically sets bits and waits for other bits, with a timeout.
result< flags< E > > try_wait_until(flags< E > bits, wait_mode mode, const std::chrono::time_point< Clock, Duration > &deadline, bool clear_on_exit=true)
Waits for event bits to be set, with a deadline.
event_group & operator=(event_group &&other) noexcept
Move assignment.
event_group()
Creates an event group.
flags< E > wait(flags< E > bits, wait_mode mode, const std::chrono::duration< Rep, Period > &timeout, bool clear_on_exit=true)
Waits for event bits to be set, with a timeout.
event_group & operator=(const event_group &)=delete
result< flags< E > > try_wait(flags< E > bits, const std::chrono::duration< Rep, Period > &timeout, bool clear_on_exit=true)
Waits for event bits to be set, with a timeout (mode defaults to all).
event_group(event_group &&other) noexcept
Move constructor.
result< flags< E > > try_wait(flags< E > bits, wait_mode mode=wait_mode::all, bool clear_on_exit=true)
Waits for event bits to be set, blocking indefinitely.
isr_set_result IRAM_ATTR set_from_isr(flags< E > bits) noexcept
Sets event bits from ISR context.
flags< E > wait_until(flags< E > bits, wait_mode mode, const std::chrono::time_point< Clock, Duration > &deadline, bool clear_on_exit=true)
Waits for event bits to be set, with a deadline.
flags< E > wait(flags< E > bits, const std::chrono::duration< Rep, Period > &timeout, bool clear_on_exit=true)
Waits for event bits to be set, with a timeout (mode defaults to all).
Type-safe set of flags from a scoped enum.
constexpr TickType_t ticks(const std::chrono::duration< Rep, Period > &d)
Converts a std::chrono duration to TickType_t ticks.
wait_mode
Specifies whether to wait for any or all of the requested bits.
@ any
Wait for any of the specified bits to be set.
@ all
Wait for all of the specified bits to be set.
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.
constexpr auto to_underlying(flags< E > f) noexcept
Returns the underlying integral value of a flags object.
Result of setting event bits from ISR context.
bool yield
true if a context switch should be requested.
bool success
true if the set was posted to the timer daemon task successfully.