pw_async2: Move PW_CO_TRY functions

Change-Id: I9d35803370e5294bcd411e2124db99a01e17a544
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/209911
Commit-Queue: Taylor Cramer <cramertj@google.com>
Lint: Lint 🤖 <android-build-ayeaye@system.gserviceaccount.com>
Reviewed-by: Wyatt Hepler <hepler@google.com>
This commit is contained in:
Taylor Cramer 2024-05-16 19:17:29 +00:00 committed by CQ Bot Account
parent d1841fd3dd
commit dcbe39839b
5 changed files with 66 additions and 39 deletions

View File

@ -243,6 +243,7 @@ _doxygen_input_files = [ # keep-sorted: start
"$dir_pw_spi/public/pw_spi/chip_selector.h",
"$dir_pw_spi/public/pw_spi/chip_selector_digital_out.h",
"$dir_pw_status/public/pw_status/status.h",
"$dir_pw_status/public/pw_status/try.h",
"$dir_pw_stream/public/pw_stream/stream.h",
"$dir_pw_stream_uart_linux/public/pw_stream_uart_linux/stream.h",
"$dir_pw_string/public/pw_string/format.h",

View File

@ -16,10 +16,10 @@ pw_async2
like other tasks, and can easily plug into an existing ``pw_async2``
systems.
:cpp:type:`pw::async2::Task` is Pigweed's async primitive. ``Task`` objects
are cooperatively-scheduled "threads" which yield to the ``Dispatcher``
when waiting. When the ``Task`` is able to make progress, the ``Dispatcher``
will run it again. For example:
:cpp:class:`pw::async2::Task` is Pigweed's async primitive. ``Task`` objects
are cooperatively-scheduled "threads" which yield to the
:cpp:class:`pw::async2::Dispatcher` when waiting. When the ``Task`` is able to make
progress, the ``Dispatcher`` will run it again. For example:
.. code-block:: cpp
@ -82,8 +82,8 @@ will run it again. For example:
std::optional<SendFuture> send_future_ = std::nullopt;
};
Tasks can then be run on a ``Dispatcher`` using the ``Dispatcher::Post``
method:
Tasks can then be run on a :cpp:class:`pw::async2::Dispatcher` using the
:cpp:func:`pw::async2::Dispatcher::Post` method:
.. code-block:: cpp
@ -108,6 +108,18 @@ C++20 users can also define tasks using coroutines!
:start-after: [pw_async2-examples-coro-injection]
:end-before: [pw_async2-examples-coro-injection]
Any value with a ``Poll<T> Pend(Context&)`` method can be passed to
``co_await``, which will return with a ``T`` when the result is ready.
To return from a coroutine, ``co_return <expression>`` must be used instead of
the usual ``return <expression>`` syntax. Because of this, the
:c:macro:`PW_TRY` and :c:macro:`PW_TRY_ASSIGN` macros are not usable within
coroutines. :c:macro:`PW_CO_TRY` and :c:macro:`PW_CO_TRY_ASSIGN` should be
used instead.
For a more detailed explanation of Pigweed's coroutine support, see the
documentation on the :cpp:class:`pw::async2::Coro<T>` type.
-----------------
C++ API reference
-----------------
@ -137,6 +149,9 @@ C++ API reference
.. doxygenclass:: pw::async2::Coro
:members:
.. doxygenclass:: pw::async2::CoroContext
:members:
-------------
C++ Utilities
-------------

View File

@ -496,32 +496,3 @@ Coro<T> CoroPromiseType<T>::get_return_object_on_allocation_failure() {
} // namespace internal
} // namespace pw::async2
/// Like `PW_TRY`, but using `co_return` instead of early `return`.
///
/// This is necessary because only `co_return` can be used inside of a
/// coroutine, and there is no way to detect whether particular code is running
/// within a coroutine or not.
#define PW_CO_TRY(expr) _PW_CO_TRY(_PW_TRY_UNIQUE(__LINE__), expr)
#define _PW_CO_TRY(result, expr) \
do { \
if (auto result = (expr); !result.ok()) { \
co_return ::pw::internal::ConvertToStatus(result); \
} \
} while (0)
/// Like `PW_TRY_ASSIGN`, but using `co_return` instead of early `return`.
///
/// This is necessary because only `co_return` can be used inside of a
/// coroutine, and there is no way to detect whether particular code is running
/// within a coroutine or not.
#define PW_CO_TRY_ASSIGN(assignment_lhs, expression) \
_PW_CO_TRY_ASSIGN(_PW_TRY_UNIQUE(__LINE__), assignment_lhs, expression)
#define _PW_CO_TRY_ASSIGN(result, lhs, expr) \
auto result = (expr); \
if (!result.ok()) { \
co_return ::pw::internal::ConvertToStatus(result); \
} \
lhs = ::pw::internal::ConvertToValue(result);

View File

@ -20,6 +20,8 @@
// Macros for cleanly working with Status or StatusWithSize objects in functions
// that return Status.
/// Returns early if \a expr is a non-OK `Status` or `Result`.
#define PW_TRY(expr) _PW_TRY(_PW_TRY_UNIQUE(__LINE__), expr)
#define _PW_TRY(result, expr) \
@ -29,8 +31,10 @@
} \
} while (0)
#define PW_TRY_ASSIGN(assignment_lhs, expression) \
_PW_TRY_ASSIGN(_PW_TRY_UNIQUE(__LINE__), assignment_lhs, expression)
/// Returns early if \a expression is a non-OK `Result`.
/// If \a expression is okay, assigns the inner value to \a lhs.
#define PW_TRY_ASSIGN(lhs, expression) \
_PW_TRY_ASSIGN(_PW_TRY_UNIQUE(__LINE__), lhs, expression)
#define _PW_TRY_ASSIGN(result, lhs, expr) \
auto result = (expr); \
@ -39,8 +43,9 @@
} \
lhs = ::pw::internal::ConvertToValue(result);
// Macro for cleanly working with Status or StatusWithSize objects in functions
// that return StatusWithSize.
/// Returns early if \a expr is a non-OK `Status` or `StatusWithSize`.
///
/// This is designed for use in functions that return a `StatusWithSize`.
#define PW_TRY_WITH_SIZE(expr) _PW_TRY_WITH_SIZE(_PW_TRY_UNIQUE(__LINE__), expr)
#define _PW_TRY_WITH_SIZE(result, expr) \
@ -53,6 +58,35 @@
#define _PW_TRY_UNIQUE(line) _PW_TRY_UNIQUE_EXPANDED(line)
#define _PW_TRY_UNIQUE_EXPANDED(line) _pw_try_unique_name_##line
/// Like `PW_TRY`, but using `co_return` instead of early `return`.
///
/// This is necessary because only `co_return` can be used inside of a
/// coroutine, and there is no way to detect whether particular code is running
/// within a coroutine or not.
#define PW_CO_TRY(expr) _PW_CO_TRY(_PW_TRY_UNIQUE(__LINE__), expr)
#define _PW_CO_TRY(result, expr) \
do { \
if (auto result = (expr); !result.ok()) { \
co_return ::pw::internal::ConvertToStatus(result); \
} \
} while (0)
/// Like `PW_TRY_ASSIGN`, but using `co_return` instead of early `return`.
///
/// This is necessary because only `co_return` can be used inside of a
/// coroutine, and there is no way to detect whether particular code is running
/// within a coroutine or not.
#define PW_CO_TRY_ASSIGN(lhs, expression) \
_PW_CO_TRY_ASSIGN(_PW_TRY_UNIQUE(__LINE__), lhs, expression)
#define _PW_CO_TRY_ASSIGN(result, lhs, expr) \
auto result = (expr); \
if (!result.ok()) { \
co_return ::pw::internal::ConvertToStatus(result); \
} \
lhs = ::pw::internal::ConvertToValue(result);
namespace pw::internal {
constexpr Status ConvertToStatus(Status status) { return status; }

View File

@ -373,6 +373,12 @@ C++ API
``PW_STATUS_``. For example, ``PW_STATUS_DATA_LOSS`` corresponds with
:c:enumerator:`DATA_LOSS`.
.. doxygendefine:: PW_TRY
.. doxygendefine:: PW_TRY_ASSIGN
.. doxygendefine:: PW_TRY_WITH_SIZE
.. doxygendefine:: PW_CO_TRY
.. doxygendefine:: PW_CO_TRY_ASSIGN
Unused result warnings
----------------------
If the ``PW_STATUS_CFG_CHECK_IF_USED`` option is enabled, ``pw::Status`` objects