aboutsummaryrefslogtreecommitdiff
path: root/pw_rpc/nanopb/public/pw_rpc/nanopb/fake_channel_output.h
diff options
context:
space:
mode:
Diffstat (limited to 'pw_rpc/nanopb/public/pw_rpc/nanopb/fake_channel_output.h')
-rw-r--r--pw_rpc/nanopb/public/pw_rpc/nanopb/fake_channel_output.h45
1 files changed, 34 insertions, 11 deletions
diff --git a/pw_rpc/nanopb/public/pw_rpc/nanopb/fake_channel_output.h b/pw_rpc/nanopb/public/pw_rpc/nanopb/fake_channel_output.h
index 360cfc1d5..f71c87795 100644
--- a/pw_rpc/nanopb/public/pw_rpc/nanopb/fake_channel_output.h
+++ b/pw_rpc/nanopb/public/pw_rpc/nanopb/fake_channel_output.h
@@ -15,16 +15,28 @@
#include <cstddef>
#include <cstdint>
+#include <mutex>
#include "pw_assert/assert.h"
#include "pw_bytes/span.h"
#include "pw_containers/vector.h"
#include "pw_containers/wrapped_iterator.h"
#include "pw_rpc/internal/fake_channel_output.h"
+#include "pw_rpc/internal/lock.h"
#include "pw_rpc/nanopb/internal/common.h"
#include "pw_rpc/nanopb/internal/method.h"
namespace pw::rpc {
+namespace internal {
+
+// Forward declare for a friend statement.
+template <typename, size_t, size_t, size_t>
+class ForwardingChannelOutput;
+
+} // namespace internal
+} // namespace pw::rpc
+
+namespace pw::rpc {
namespace internal::test::nanopb {
// Forward declare for a friend statement.
@@ -44,7 +56,7 @@ class NanopbPayloadsView {
// Access the payload (rather than packet) with operator*.
Payload operator*() const {
Payload payload{};
- PW_ASSERT(serde_.Decode(Base::value(), &payload));
+ PW_ASSERT_OK(serde_.Decode(Base::value(), payload));
return payload;
}
@@ -60,7 +72,7 @@ class NanopbPayloadsView {
Payload operator[](size_t index) const {
Payload payload{};
- PW_ASSERT(serde_.Decode(view_[index], &payload));
+ PW_ASSERT_OK(serde_.Decode(view_[index], payload));
return payload;
}
@@ -112,11 +124,12 @@ class NanopbFakeChannelOutput final
// thread accesses the FakeChannelOutput.
template <auto kMethod>
NanopbPayloadsView<Request<kMethod>> requests(
- uint32_t channel_id = Channel::kUnassignedChannelId) const {
- constexpr internal::PacketType packet_type =
+ uint32_t channel_id = Channel::kUnassignedChannelId) const
+ PW_NO_LOCK_SAFETY_ANALYSIS {
+ constexpr internal::pwpb::PacketType packet_type =
HasClientStream(internal::MethodInfo<kMethod>::kType)
- ? internal::PacketType::CLIENT_STREAM
- : internal::PacketType::REQUEST;
+ ? internal::pwpb::PacketType::CLIENT_STREAM
+ : internal::pwpb::PacketType::REQUEST;
return NanopbPayloadsView<Request<kMethod>>(
internal::MethodInfo<kMethod>::serde().request(),
Base::packets(),
@@ -136,11 +149,12 @@ class NanopbFakeChannelOutput final
// thread accesses the FakeChannelOutput.
template <auto kMethod>
NanopbPayloadsView<Response<kMethod>> responses(
- uint32_t channel_id = Channel::kUnassignedChannelId) const {
- constexpr internal::PacketType packet_type =
+ uint32_t channel_id = Channel::kUnassignedChannelId) const
+ PW_NO_LOCK_SAFETY_ANALYSIS {
+ constexpr internal::pwpb::PacketType packet_type =
HasServerStream(internal::MethodInfo<kMethod>::kType)
- ? internal::PacketType::SERVER_STREAM
- : internal::PacketType::RESPONSE;
+ ? internal::pwpb::PacketType::SERVER_STREAM
+ : internal::pwpb::PacketType::RESPONSE;
return NanopbPayloadsView<Response<kMethod>>(
internal::MethodInfo<kMethod>::serde().response(),
Base::packets(),
@@ -153,6 +167,7 @@ class NanopbFakeChannelOutput final
template <auto kMethod>
Response<kMethod> last_response() const {
+ std::lock_guard lock(internal::test::FakeChannelOutput::mutex());
NanopbPayloadsView<Response<kMethod>> payloads = responses<kMethod>();
PW_ASSERT(!payloads.empty());
return payloads.back();
@@ -161,6 +176,8 @@ class NanopbFakeChannelOutput final
private:
template <typename, auto, uint32_t, size_t, size_t>
friend class internal::test::nanopb::NanopbInvocationContext;
+ template <typename, size_t, size_t, size_t>
+ friend class internal::ForwardingChannelOutput;
using Base =
internal::test::FakeChannelOutputBuffer<kMaxPackets,
@@ -168,12 +185,18 @@ class NanopbFakeChannelOutput final
using internal::test::FakeChannelOutput::last_packet;
+ // !!! WARNING !!!
+ //
+ // Access to the FakeChannelOutput through the NanopbPayloadsView is NOT
+ // synchronized! The NanopbPayloadsView is immediately invalidated if any
+ // thread accesses the FakeChannelOutput.
template <typename T>
NanopbPayloadsView<T> payload_structs(const internal::NanopbSerde& serde,
MethodType type,
uint32_t channel_id,
uint32_t service_id,
- uint32_t method_id) const {
+ uint32_t method_id) const
+ PW_NO_LOCK_SAFETY_ANALYSIS {
return NanopbPayloadsView<T>(
serde, Base::packets(), type, channel_id, service_id, method_id);
}