C/C++ API Reference
Loading...
Searching...
No Matches
forwarding_channel.h
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 <mutex>
18#include <optional>
19
20#include "pw_async2/dispatcher.h"
21#include "pw_async2/poll.h"
22#include "pw_channel/channel.h"
23#include "pw_multibuf/allocator.h"
24#include "pw_multibuf/allocator_async.h"
25#include "pw_sync/lock_annotations.h"
26#include "pw_sync/mutex.h"
27
28namespace pw::channel {
29namespace internal {
30
31// Internal Channel implementation for use with ForwardingChannelPair. It is
32// specialized for kDatagram and kByte.
33template <DataType kType>
35
36} // namespace internal
37
39
42
48template <DataType kType>
50 public:
51 explicit constexpr ForwardingChannelPair(
52 multibuf::MultiBufAllocator& first_write_alloc,
53 multibuf::MultiBufAllocator& second_write_alloc);
54
56 ForwardingChannelPair& operator=(const ForwardingChannelPair&) = delete;
57
59 ForwardingChannelPair& operator=(ForwardingChannelPair&&) = delete;
60
63 return first_.channel();
64 }
65
68 return first_;
69 }
70
73 return second_.channel();
74 }
75
78 return second_;
79 }
80
81 private:
82 template <DataType>
83 friend class internal::ForwardingChannel;
84
85 sync::Mutex mutex_;
86 // These channels refer to each other, so their lifetimes must match.
89};
90
94
97
99
100namespace internal {
101
102template <>
103class ForwardingChannel<DataType::kDatagram>
104 : public Implement<ReliableDatagramReaderWriter> {
105 public:
106 ForwardingChannel(const ForwardingChannel&) = delete;
107 ForwardingChannel& operator=(const ForwardingChannel&) = delete;
108
110 ForwardingChannel& operator=(ForwardingChannel&&) = delete;
111
112 private:
113 friend class ForwardingChannelPair<DataType::kDatagram>;
114
115 constexpr ForwardingChannel(ForwardingChannelPair<DataType::kDatagram>& pair,
116 ForwardingChannel* sibling,
117 multibuf::MultiBufAllocator& write_alloc)
118 : pair_(pair), sibling_(*sibling), write_alloc_future_(write_alloc) {}
119
121 async2::Context& cx) override;
122
123 async2::Poll<Status> DoPendReadyToWrite(async2::Context& cx) override;
124
125 async2::PollOptional<multibuf::MultiBuf> DoPendAllocateWriteBuffer(
126 async2::Context& cx, size_t min_bytes) override {
127 write_alloc_future_.SetDesiredSize(min_bytes);
128 return write_alloc_future_.Pend(cx);
129 }
130
131 Status DoStageWrite(multibuf::MultiBuf&& data) override;
132
133 async2::Poll<Status> DoPendWrite(async2::Context&) override {
134 return OkStatus();
135 }
136
137 async2::Poll<Status> DoPendClose(async2::Context&) override;
138
139 // The two channels share one mutex. Lock safty analysis doesn't understand
140 // that, so has to be disabled for some functions.
142 ForwardingChannel& sibling_;
143
144 // Could use a queue here.
145 std::optional<multibuf::MultiBuf> read_queue_ PW_GUARDED_BY(pair_.mutex_);
146 async2::Waker waker_ PW_GUARDED_BY(pair_.mutex_);
147 multibuf::MultiBufAllocationFuture write_alloc_future_;
148};
149
150template <>
151class ForwardingChannel<DataType::kByte>
152 : public Implement<ReliableByteReaderWriter> {
153 public:
154 ForwardingChannel(const ForwardingChannel&) = delete;
155 ForwardingChannel& operator=(const ForwardingChannel&) = delete;
156
158 ForwardingChannel& operator=(ForwardingChannel&&) = delete;
159
160 private:
161 friend class ForwardingChannelPair<DataType::kByte>;
162
163 constexpr ForwardingChannel(ForwardingChannelPair<DataType::kByte>& pair,
164 ForwardingChannel* sibling,
165 multibuf::MultiBufAllocator& write_alloc)
166 : pair_(pair), sibling_(*sibling), write_alloc_future_(write_alloc) {}
167
169 async2::Context& cx) override;
170
171 async2::Poll<Status> DoPendReadyToWrite(async2::Context&) override {
172 return async2::Ready(OkStatus());
173 }
174
175 async2::PollOptional<multibuf::MultiBuf> DoPendAllocateWriteBuffer(
176 async2::Context& cx, size_t min_bytes) override {
177 write_alloc_future_.SetDesiredSize(min_bytes);
178 return write_alloc_future_.Pend(cx);
179 }
180
181 Status DoStageWrite(multibuf::MultiBuf&& data) override;
182
183 async2::Poll<Status> DoPendWrite(async2::Context&) override {
184 return OkStatus();
185 }
186
187 async2::Poll<Status> DoPendClose(async2::Context&) override;
188
190 ForwardingChannel& sibling_;
191
192 multibuf::MultiBuf read_queue_ PW_GUARDED_BY(pair_.mutex_);
193 async2::Waker read_waker_ PW_GUARDED_BY(pair_.mutex_);
194 multibuf::MultiBufAllocationFuture write_alloc_future_;
195};
196
197} // namespace internal
198
199// Define the constructor out-of-line, after ForwardingChannel is defined.
200template <DataType kType>
202 multibuf::MultiBufAllocator& first_write_allocator,
203 multibuf::MultiBufAllocator& second_write_allocator)
204 : first_(*this, &second_, first_write_allocator),
205 second_(*this, &first_, second_write_allocator) {}
206
207} // namespace pw::channel
Definition: status.h:109
Definition: context.h:55
Definition: poll.h:60
Definition: waker.h:160
Definition: channel.h:55
Definition: forwarding_channel.h:49
Definition: channel.h:583
Definition: forwarding_channel.h:34
Definition: allocator_async.h:93
Definition: allocator.h:57
Definition: multibuf_v1.h:248
Definition: mutex.h:40
constexpr Poll Ready()
Returns a value indicating completion.
Definition: poll.h:255
Channel< kType, kReliable, kReadable, kWritable > & second()
Returns the second channel in the pair.
Definition: forwarding_channel.h:72
Channel< kType, kReliable, kReadable, kWritable > & first()
Returns the first channel in the pair.
Definition: forwarding_channel.h:62
const Channel< kType, kReliable, kReadable, kWritable > & second() const
Returns a const reference to the second channel in the pair.
Definition: forwarding_channel.h:77
const Channel< kType, kReliable, kReadable, kWritable > & first() const
Returns a const reference to the first channel in the pair.
Definition: forwarding_channel.h:67
constexpr Status OkStatus()
Definition: status.h:297
#define PW_GUARDED_BY(x)
Definition: lock_annotations.h:60