aboutsummaryrefslogtreecommitdiff
path: root/pw_rpc/public/pw_rpc/synchronous_call.h
diff options
context:
space:
mode:
authorWyatt Hepler <hepler@google.com>2023-04-11 01:27:36 +0000
committerCQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-04-11 01:27:36 +0000
commite850621049d267fbf5b78f9eb3f9b4895cdc4c92 (patch)
tree30504cb2541225f129353f84d3658b04fed96a5a /pw_rpc/public/pw_rpc/synchronous_call.h
parent3ceb704d2101ba27e064886414447b3365ca8f47 (diff)
downloadpigweed-e850621049d267fbf5b78f9eb3f9b4895cdc4c92.tar.gz
pw_rpc: Raw synchronous call API
Raw synchronous calls pass the raw response buffer to a callback function. Fixes: b/268216599 Change-Id: I0f9462e5d5baa987f754615c3156942e05f9215f Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/128371 Reviewed-by: Xiaofan Jiang <xiaofanj@google.com> Reviewed-by: Alexei Frolov <frolv@google.com> Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com> Pigweed-Auto-Submit: Wyatt Hepler <hepler@google.com>
Diffstat (limited to 'pw_rpc/public/pw_rpc/synchronous_call.h')
-rw-r--r--pw_rpc/public/pw_rpc/synchronous_call.h126
1 files changed, 114 insertions, 12 deletions
diff --git a/pw_rpc/public/pw_rpc/synchronous_call.h b/pw_rpc/public/pw_rpc/synchronous_call.h
index 92bd20217..8a2be800a 100644
--- a/pw_rpc/public/pw_rpc/synchronous_call.h
+++ b/pw_rpc/public/pw_rpc/synchronous_call.h
@@ -25,25 +25,28 @@
///
/// `pw_rpc` provides wrappers that convert the asynchronous client API to a
/// synchronous API. The `SynchronousCall<RpcMethod>` functions wrap the
-/// asynchronous client RPC call with a timed thread notification and return
-/// once a result is known or a timeout has occurred. These return a
-/// `SynchronousCallResult<Response>` object, which can be queried to determine
-/// whether any error scenarios occurred and, if not, access the response.
+/// asynchronous client RPC call with a timed thread notification and returns
+/// once a result is known or a timeout has occurred. Only unary methods are
+/// supported.
+///
+/// The Nanopb and pwpb APIs return a `SynchronousCallResult<Response>` object,
+/// which can be queried to determine whether any error scenarios occurred and,
+/// if not, access the response. The raw API executes a function when the call
+/// completes or returns a `pw::Status` if it does not.
///
/// `SynchronousCall<RpcMethod>` blocks indefinitely, whereas
/// `SynchronousCallFor<RpcMethod>` and `SynchronousCallUntil<RpcMethod>` block
/// for a given timeout or until a deadline, respectively. All wrappers work
-/// with both the standalone static RPC functions and the generated Client
-/// member methods.
+/// with either the standalone static RPC functions or the generated service
+/// client member methods.
///
/// @note Use of the SynchronousCall wrappers requires a
/// @cpp_class{pw::sync::TimedThreadNotification} backend.
///
-/// @note Only nanopb and pw_protobuf unary RPC methods are supported.
-///
-/// The following example blocks indefinitely. If you'd like to include a
-/// timeout for how long the call should block for, use the
-/// `SynchronousCallFor()` or `SynchronousCallUntil()` variants.
+/// The following examples use the Nanopb API to make a call that blocks
+/// indefinitely. If you'd like to include a timeout for how long the call
+/// should block for, use the `SynchronousCallFor()` or `SynchronousCallUntil()`
+/// variants.
///
/// @code{.cpp}
/// pw_rpc_EchoMessage request{.msg = "hello" };
@@ -58,7 +61,7 @@
///
/// Additionally, the use of a generated `Client` object is supported:
///
-/// @code
+/// @code{.cpp}
/// pw_rpc::nanopb::EchoService::Client client(rpc_client, channel_id);
/// pw_rpc_EchoMessage request{.msg = "hello" };
/// pw::rpc::SynchronousCallResult<pw_rpc_EchoMessage> result =
@@ -69,6 +72,22 @@
/// }
/// @endcode
///
+/// The raw API works similarly to the Nanopb API, but takes a
+/// @cpp_type{pw::Function} and returns a @cpp_class{pw::Status}. If the RPC
+/// completes, the @cpp_type{pw::Function} is called with the response and
+/// returned status, and the `SynchronousCall` invocation returns
+/// @pw_status{OK}. If the RPC fails, `SynchronousCall` returns an error.
+///
+/// @code{.cpp}
+/// pw::Status rpc_status = pw::rpc::SynchronousCall<EchoService::Echo>(
+/// rpc_client, channel_id, encoded_request,
+/// [](pw::ConstByteSpan reply, pw::Status status) {
+/// PW_LOG_INFO("Received %zu bytes with status %s",
+/// reply.size(),
+/// status.str());
+/// });
+/// @endcode
+///
/// @warning These wrappers should not be used from any context that cannot be
/// blocked! This method will block the calling thread until the RPC completes,
/// and translate the response into a `pw::rpc::SynchronousCallResult` that
@@ -134,6 +153,30 @@ SynchronousCall(
return std::move(call_state.result);
}
+/// Invokes a unary RPC synchronously using the raw API. Blocks until a
+/// response is received.
+template <auto kRpcMethod>
+Status SynchronousCall(Client& client,
+ uint32_t channel_id,
+ ConstByteSpan request,
+ Function<void(ConstByteSpan, Status)>&& on_completed) {
+ return internal::RawSynchronousCall<kRpcMethod>(
+ std::move(on_completed),
+ internal::CallFreeFunction<kRpcMethod>(client, channel_id, request));
+}
+
+/// Invokes a unary RPC synchronously using the raw API. Blocks until a
+/// response is received.
+template <auto kRpcMethod>
+Status SynchronousCall(
+ const typename internal::MethodInfo<kRpcMethod>::GeneratedClient& client,
+ ConstByteSpan request,
+ Function<void(ConstByteSpan, Status)>&& on_completed) {
+ return internal::RawSynchronousCall<kRpcMethod>(
+ std::move(on_completed),
+ internal::CallGeneratedClient<kRpcMethod>(client, request));
+}
+
/// Invokes a unary RPC synchronously using Nanopb or pwpb. Blocks until a
/// response is received or the provided timeout passes.
///
@@ -201,6 +244,35 @@ SynchronousCallFor(
return std::move(call_state.result);
}
+/// Invokes a unary RPC synchronously using the raw API. Blocks until a
+/// response is received or the provided timeout passes.
+template <auto kRpcMethod>
+Status SynchronousCallFor(
+ Client& client,
+ uint32_t channel_id,
+ ConstByteSpan request,
+ chrono::SystemClock::duration timeout,
+ Function<void(ConstByteSpan, Status)>&& on_completed) {
+ return internal::RawSynchronousCall<kRpcMethod>(
+ std::move(on_completed),
+ internal::CallFreeFunction<kRpcMethod>(client, channel_id, request),
+ timeout);
+}
+
+/// Invokes a unary RPC synchronously using the raw API. Blocks until a
+/// response is received or the provided timeout passes.
+template <auto kRpcMethod>
+Status SynchronousCallFor(
+ const typename internal::MethodInfo<kRpcMethod>::GeneratedClient& client,
+ ConstByteSpan request,
+ chrono::SystemClock::duration timeout,
+ Function<void(ConstByteSpan, Status)>&& on_completed) {
+ return internal::RawSynchronousCall<kRpcMethod>(
+ std::move(on_completed),
+ internal::CallGeneratedClient<kRpcMethod>(client, request),
+ timeout);
+}
+
/// Invokes a unary RPC synchronously using Nanopb or pwpb. Blocks until a
/// response is received or the provided deadline arrives.
///
@@ -267,4 +339,34 @@ SynchronousCallUntil(
return std::move(call_state.result);
}
+
+/// Invokes a unary RPC synchronously using the raw API. Blocks until a
+/// response is received or the provided deadline arrives.
+template <auto kRpcMethod>
+Status SynchronousCallUntil(
+ Client& client,
+ uint32_t channel_id,
+ ConstByteSpan request,
+ chrono::SystemClock::time_point deadline,
+ Function<void(ConstByteSpan, Status)>&& on_completed) {
+ return internal::RawSynchronousCall<kRpcMethod>(
+ std::move(on_completed),
+ internal::CallFreeFunction<kRpcMethod>(client, channel_id, request),
+ deadline);
+}
+
+/// Invokes a unary RPC synchronously using the raw API. Blocks until a
+/// response is received or the provided deadline arrives.
+template <auto kRpcMethod>
+Status SynchronousCallUntil(
+ const typename internal::MethodInfo<kRpcMethod>::GeneratedClient& client,
+ ConstByteSpan request,
+ chrono::SystemClock::time_point deadline,
+ Function<void(ConstByteSpan, Status)>&& on_completed) {
+ return internal::RawSynchronousCall<kRpcMethod>(
+ std::move(on_completed),
+ internal::CallGeneratedClient<kRpcMethod>(client, request),
+ deadline);
+}
+
} // namespace pw::rpc