xref: /aosp_15_r20/external/pigweed/pw_channel/public/pw_channel/loopback_channel.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2024 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 
16 #include <cstdint>
17 #include <optional>
18 
19 #include "pw_async2/dispatcher.h"
20 #include "pw_async2/poll.h"
21 #include "pw_channel/channel.h"
22 #include "pw_multibuf/allocator.h"
23 #include "pw_multibuf/multibuf.h"
24 
25 namespace pw::channel {
26 
27 /// @defgroup pw_channel_loopback
28 /// @{
29 
30 // Channel implementation which will read its own writes.
31 template <DataType kType>
32 class LoopbackChannel;
33 
34 /// Alias for a loopback channel that sends and receives datagrams.
35 using LoopbackDatagramChannel = LoopbackChannel<DataType::kDatagram>;
36 
37 /// Alias for a loopback channel that sends and receives bytes.
38 using LoopbackByteChannel = LoopbackChannel<DataType::kByte>;
39 
40 /// @}
41 
42 template <>
43 class LoopbackChannel<DataType::kDatagram>
44     : public Implement<ReliableDatagramReaderWriter> {
45  public:
LoopbackChannel(multibuf::MultiBufAllocator & write_allocator)46   LoopbackChannel(multibuf::MultiBufAllocator& write_allocator)
47       : write_alloc_future_(write_allocator) {}
48   LoopbackChannel(const LoopbackChannel&) = delete;
49   LoopbackChannel& operator=(const LoopbackChannel&) = delete;
50 
51   LoopbackChannel(LoopbackChannel&&) = default;
52   LoopbackChannel& operator=(LoopbackChannel&&) = default;
53 
54  private:
55   async2::Poll<Result<multibuf::MultiBuf>> DoPendRead(
56       async2::Context& cx) override;
57 
58   async2::Poll<Status> DoPendReadyToWrite(async2::Context& cx) final;
59 
DoPendAllocateWriteBuffer(async2::Context & cx,size_t min_bytes)60   async2::Poll<std::optional<multibuf::MultiBuf>> DoPendAllocateWriteBuffer(
61       async2::Context& cx, size_t min_bytes) final {
62     write_alloc_future_.SetDesiredSize(min_bytes);
63     return write_alloc_future_.Pend(cx);
64   }
65 
66   Status DoStageWrite(multibuf::MultiBuf&& data) final;
67 
68   async2::Poll<Status> DoPendWrite(async2::Context&) final;
69 
70   async2::Poll<Status> DoPendClose(async2::Context&) final;
71 
72   multibuf::MultiBufAllocationFuture write_alloc_future_;
73   std::optional<multibuf::MultiBuf> queue_;
74 
75   async2::Waker waker_;
76 };
77 
78 template <>
79 class LoopbackChannel<DataType::kByte>
80     : public Implement<ReliableByteReaderWriter> {
81  public:
LoopbackChannel(multibuf::MultiBufAllocator & write_allocator)82   LoopbackChannel(multibuf::MultiBufAllocator& write_allocator)
83       : write_alloc_future_(write_allocator) {}
84   LoopbackChannel(const LoopbackChannel&) = delete;
85   LoopbackChannel& operator=(const LoopbackChannel&) = delete;
86 
87   LoopbackChannel(LoopbackChannel&&) = default;
88   LoopbackChannel& operator=(LoopbackChannel&&) = default;
89 
90  private:
91   async2::Poll<Result<multibuf::MultiBuf>> DoPendRead(
92       async2::Context& cx) override;
93 
DoPendReadyToWrite(async2::Context &)94   async2::Poll<Status> DoPendReadyToWrite(async2::Context&) final {
95     return async2::Ready(OkStatus());
96   }
97 
DoPendAllocateWriteBuffer(async2::Context & cx,size_t min_bytes)98   async2::Poll<std::optional<multibuf::MultiBuf>> DoPendAllocateWriteBuffer(
99       async2::Context& cx, size_t min_bytes) final {
100     write_alloc_future_.SetDesiredSize(min_bytes);
101     return write_alloc_future_.Pend(cx);
102   }
103 
104   Status DoStageWrite(multibuf::MultiBuf&& data) final;
105 
106   async2::Poll<Status> DoPendWrite(async2::Context&) final;
107 
108   async2::Poll<Status> DoPendClose(async2::Context&) final;
109 
110   multibuf::MultiBufAllocationFuture write_alloc_future_;
111   multibuf::MultiBuf queue_;
112 
113   async2::Waker read_waker_;
114 };
115 
116 }  // namespace pw::channel
117