31#include "lib/stdcompat/utility.h"
32#include "pw_assert/assert.h"
33#include "pw_async2/context.h"
34#include "pw_async2/poll.h"
35#include "pw_async2/try.h"
36#include "pw_async2/waker.h"
37#include "pw_channel/properties.h"
38#include "pw_result/result.h"
39#include "pw_status/status.h"
41namespace pw::channel {
47template <
typename Packet>
50 constexpr PendingWrite() : channel_(
nullptr), num_packets_(0) {}
56 : channel_(other.channel_),
57 num_packets_(cpp20::exchange(other.num_packets_, 0u)) {}
59 channel_ = other.channel_;
60 num_packets_ = cpp20::exchange(other.num_packets_, 0u);
66 PW_ASSERT(num_packets_ == 0u);
74 PW_ASSERT(num_packets_ > 0u);
75 channel_->DoStageWrite(std::move(packet));
79 size_t num_packets()
const {
return num_packets_; }
82 friend class AnyPacketChannel<Packet>;
84 constexpr PendingWrite(AnyPacketChannel<Packet>& channel,
size_t num_packets)
85 : channel_(&channel), num_packets_(num_packets) {}
87 AnyPacketChannel<Packet>* channel_;
96inline constexpr uint16_t
kNoFlowControl = std::numeric_limits<uint16_t>::max();
110template <
typename T, Property... kProperties>
116 [[nodiscard]]
static constexpr bool readable() {
117 return ((kProperties == Property::kReadable) || ...);
120 [[nodiscard]]
static constexpr bool writable() {
121 return ((kProperties == Property::kWritable) || ...);
125 [[nodiscard]]
constexpr bool is_read_open()
const;
128 [[nodiscard]]
constexpr bool is_write_open()
const;
131 [[nodiscard]]
constexpr bool is_read_or_write_open()
const {
132 return is_read_open() || is_write_open();
149 void SetAvailableWrites(uint16_t available_writes);
151 void AcknowledgeWrites(uint16_t num_completed);
159 template <
typename Sibling,
160 typename = internal::EnableIfConvertible<PacketChannel, Sibling>>
161 constexpr operator Sibling&() {
162 return as<Sibling>();
164 template <
typename Sibling,
165 typename = internal::EnableIfConvertible<PacketChannel, Sibling>>
166 constexpr operator const Sibling&()
const {
167 return as<Sibling>();
169 constexpr operator AnyPacketChannel<Packet>&() {
170 return static_cast<AnyPacketChannel<Packet>&
>(*this);
172 constexpr operator const AnyPacketChannel<Packet>&()
const {
173 return static_cast<const AnyPacketChannel<Packet>&
>(*this);
177 template <
typename Sibling>
178 [[nodiscard]] Sibling&
as() {
179 internal::CheckPacketChannelConversion<PacketChannel, Sibling>();
182 template <
typename Sibling>
183 [[nodiscard]]
const Sibling&
as()
const {
184 internal::CheckPacketChannelConversion<PacketChannel, Sibling>();
185 return static_cast<const Sibling&
>(
191 template <Property... kOtherProperties>
192 [[nodiscard]]
auto&
as() {
195 template <Property... kOtherProperties>
196 [[nodiscard]]
const auto&
as()
const {
202 uint16_t GetAvailableWrites()
const;
205 static_assert(internal::PacketChannelPropertiesAreValid<kProperties...>());
208 friend class AnyPacketChannel;
210 explicit constexpr PacketChannel() =
default;
230 return (properties_ & kReadable) != 0u;
235 return (properties_ & kWritable) != 0u;
241 return (read_write_open_ & kReadable) != 0u;
247 return (read_write_open_ & kWritable) != 0u;
252 return read_write_open_ != 0u;
272 return DoPendRead(cx);
357 template <
typename, Property...>
360 template <
typename, Property...>
367 : available_writes_(available_writes),
368 properties_(properties),
369 read_write_open_{uint8_t{kReadable} | uint8_t{kWritable}} {}
375 virtual void DoStageWrite(Packet&& packet) = 0;
381 uint16_t available_writes_;
383 uint8_t read_write_open_;
392template <
typename Packet>
398template <
typename Packet>
404template <
typename Packet>
410template <
typename ChannelType>
413template <
typename Packet, Property... kProperties>
417 explicit constexpr Implement() =
default;
422template <
typename Packet>
425 PW_DASSERT(num > 0u);
427 if (!is_write_open()) {
431 if (GetAvailableWrites() < num) {
442template <
typename Packet>
444 if (!is_write_open()) {
448 if (GetAvailableWrites() == 0u) {
450 cx, write_waker_,
"waiting for writes to be acknowledged");
456 available_writes_ -= 1;
462template <
typename Packet>
464 if (available_writes > available_writes_) {
465 std::move(write_waker_).Wake();
467 available_writes_ = available_writes;
470template <
typename Packet>
472 PW_DASSERT(num_completed > 0u);
475 uint32_t new_available_writes = uint32_t{available_writes_} + num_completed;
478 available_writes_ =
static_cast<uint16_t
>(new_available_writes);
480 std::move(write_waker_).Wake();
483template <
typename Packet>
485 if (!is_read_or_write_open()) {
488 auto result = DoPendClose(cx);
489 if (result.IsReady()) {
490 set_read_write_closed();
492 std::move(write_waker_).Wake();
499template <
typename Packet, Property... kProperties>
505template <
typename Packet, Property... kProperties>
506constexpr bool PacketChannel<Packet, kProperties...>::is_write_open()
const {
508 static_cast<const AnyPacketChannel<Packet>*
>(
this)->is_write_open();
511template <
typename Packet, Property... kProperties>
512async2::PollResult<Packet> PacketChannel<Packet, kProperties...>::PendRead(
513 async2::Context& cx) {
514 static_assert(readable(),
"PendRead may only be called on readable channels");
515 return static_cast<AnyPacketChannel<Packet>*
>(
this)->PendRead(cx);
518template <
typename Packet, Property... kProperties>
519async2::PollResult<PendingWrite<Packet>>
520PacketChannel<Packet, kProperties...>::PendReadyToWrite(async2::Context& cx,
522 static_assert(writable(),
523 "PendReadyToWrite may only be called on writable channels");
524 return static_cast<AnyPacketChannel<Packet>*
>(
this)->PendReadyToWrite(cx,
527template <
typename Packet, Property... kProperties>
528async2::Poll<> PacketChannel<Packet, kProperties...>::PendWrite(
529 async2::Context& cx) {
530 static_assert(writable(),
531 "PendWrite may only be called on writable channels");
532 return static_cast<AnyPacketChannel<Packet>*
>(
this)->PendWrite(cx);
534template <
typename Packet, Property... kProperties>
535uint16_t PacketChannel<Packet, kProperties...>::GetAvailableWrites()
const {
536 static_assert(writable(),
537 "GetAvailableWrites may only be called on writable channels");
538 return static_cast<const AnyPacketChannel<Packet>&
>(*this)
539 .GetAvailableWrites();
541template <
typename Packet, Property... kProperties>
542void PacketChannel<Packet, kProperties...>::SetAvailableWrites(
543 uint16_t available_writes) {
544 static_assert(writable(),
545 "SetAvailableWrites may only be called on writable channels");
546 return static_cast<AnyPacketChannel<Packet>*
>(
this)->SetAvailableWrites(
549template <
typename Packet, Property... kProperties>
550void PacketChannel<Packet, kProperties...>::AcknowledgeWrites(
551 uint16_t num_completed) {
552 static_assert(writable(),
553 "AcknowledgeWrites may only be called on writable channels");
554 return static_cast<AnyPacketChannel<Packet>*
>(
this)->AcknowledgeWrites(
558template <
typename Packet, Property... kProperties>
559async2::Poll<Status> PacketChannel<Packet, kProperties...>::PendClose(
560 async2::Context& cx) {
561 return static_cast<AnyPacketChannel<Packet>*
>(
this)->PendClose(cx);
568template <
typename Packet, Property... kProperties>
573 Channel& channel() {
return *
this; }
574 const Channel& channel()
const {
return *
this; }
580 using Channel::PendRead;
582 using Channel::AcknowledgeWrites;
583 using Channel::GetAvailableWrites;
584 using Channel::PendReadyToWrite;
585 using Channel::PendWrite;
586 using Channel::SetAvailableWrites;
588 using Channel::PendClose;
597template <
typename Packet, Property... kProperties>
599 static_assert(PacketChannelPropertiesAreValid<kProperties...>());
603template <
typename Packet>
610 void DoStageWrite(Packet&&)
final { PW_ASSERT(
false); }
615template <
typename Packet>
625template <
typename Packet>
static constexpr Status Unimplemented()
Definition: status.h:280
constexpr bool ok() const
Definition: status.h:346
static constexpr Status FailedPrecondition()
Definition: status.h:243
Definition: packet_channel.h:222
Definition: channel.h:550
Definition: packet_channel.h:111
auto & as()
Definition: packet_channel.h:192
Definition: packet_channel.h:48
Definition: packet_channel.h:569
Definition: packet_channel.h:598
#define PW_TRY_READY_ASSIGN(lhs, expression)
Definition: try.h:28
#define PW_TRY_READY(expr)
Returns Poll::Pending() if expr is Poll::Pending().
Definition: try.h:19
constexpr PendingType Pending()
Returns a value indicating that an operation was not yet able to complete.
Definition: poll.h:271
#define PW_ASYNC_STORE_WAKER(context, waker_or_queue_out, wait_reason_string)
Definition: waker.h:60
constexpr Poll Ready()
Returns a value indicating completion.
Definition: poll.h:255
constexpr uint16_t kNoFlowControl
Definition: packet_channel.h:96
void Stage(Packet &&packet)
Definition: packet_channel.h:73
void set_write_closed()
Definition: packet_channel.h:344
async2::Poll PendWrite(async2::Context &cx)
Definition: packet_channel.h:443
void SetAvailableWrites(uint16_t available_writes)
Definition: packet_channel.h:463
uint16_t GetAvailableWrites() const
Definition: packet_channel.h:332
Sibling & as()
Returns a reference to this as another compatible packet channel type.
Definition: packet_channel.h:178
constexpr bool is_read_open() const
Definition: packet_channel.h:240
async2::PollResult< Packet > PendRead(async2::Context &cx)
Definition: packet_channel.h:265
async2::Poll< Status > PendClose(async2::Context &cx)
Definition: packet_channel.h:484
constexpr bool is_write_open() const
Definition: packet_channel.h:246
void set_read_closed()
Definition: packet_channel.h:338
constexpr bool is_read_or_write_open() const
True if the channel is open for either reading or writing.
Definition: packet_channel.h:251
constexpr bool readable() const
Returns whether the channel implementation is readable.
Definition: packet_channel.h:229
void AcknowledgeWrites(uint16_t num_completed)
Definition: packet_channel.h:471
void set_read_write_closed()
Definition: packet_channel.h:351
async2::PollResult< PendingWrite< Packet > > PendReadyToWrite(async2::Context &cx, size_t num=1)
Definition: packet_channel.h:424
constexpr bool writable() const
Returns whether the channel implementation is writable.
Definition: packet_channel.h:234
async2::Waker & write_waker()
Allows implementations to access the write waker.
Definition: packet_channel.h:354
constexpr Status OkStatus()
Definition: status.h:450