diff options
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.h | 45 |
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); } |