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 {
45template <
typename Packet>
52 : channel_(other.channel_),
53 num_packets_(cpp20::exchange(other.num_packets_, 0u)) {}
55 channel_ = other.channel_;
56 num_packets_ = cpp20::exchange(other.num_packets_, 0u);
61 PW_ASSERT(num_packets_ == 0u);
69 PW_ASSERT(num_packets_ > 0u);
70 channel_->DoStageWrite(std::move(packet));
74 size_t num_packets()
const {
return num_packets_; }
77 friend class AnyPacketChannel<Packet>;
79 constexpr PendingWrite(AnyPacketChannel<Packet>& channel,
size_t num_packets)
80 : channel_(&channel), num_packets_(num_packets) {}
82 AnyPacketChannel<Packet>* channel_;
91inline constexpr uint16_t
kNoFlowControl = std::numeric_limits<uint16_t>::max();
105template <
typename T, Property... kProperties>
111 [[nodiscard]]
static constexpr bool readable() {
112 return ((kProperties == Property::kReadable) || ...);
115 [[nodiscard]]
static constexpr bool writable() {
116 return ((kProperties == Property::kWritable) || ...);
120 [[nodiscard]]
constexpr bool is_read_open()
const;
123 [[nodiscard]]
constexpr bool is_write_open()
const;
126 [[nodiscard]]
constexpr bool is_read_or_write_open()
const {
127 return is_read_open() || is_write_open();
144 void SetAvailableWrites(uint16_t available_writes);
146 void AcknowledgeWrites(uint16_t num_completed);
154 template <
typename Sibling,
155 typename = internal::EnableIfConvertible<PacketChannel, Sibling>>
156 constexpr operator Sibling&() {
157 return as<Sibling>();
159 template <
typename Sibling,
160 typename = internal::EnableIfConvertible<PacketChannel, Sibling>>
161 constexpr operator const Sibling&()
const {
162 return as<Sibling>();
164 constexpr operator AnyPacketChannel<Packet>&() {
165 return static_cast<AnyPacketChannel<Packet>&
>(*this);
167 constexpr operator const AnyPacketChannel<Packet>&()
const {
168 return static_cast<const AnyPacketChannel<Packet>&
>(*this);
172 template <
typename Sibling>
173 [[nodiscard]] Sibling&
as() {
174 internal::CheckPacketChannelConversion<PacketChannel, Sibling>();
177 template <
typename Sibling>
178 [[nodiscard]]
const Sibling&
as()
const {
179 internal::CheckPacketChannelConversion<PacketChannel, Sibling>();
180 return static_cast<const Sibling&
>(
186 template <Property... kOtherProperties>
187 [[nodiscard]]
auto&
as() {
190 template <Property... kOtherProperties>
191 [[nodiscard]]
const auto&
as()
const {
197 uint16_t GetAvailableWrites()
const;
200 static_assert(internal::PacketChannelPropertiesAreValid<kProperties...>());
203 friend class AnyPacketChannel;
205 explicit constexpr PacketChannel() =
default;
225 return (properties_ & kReadable) != 0u;
230 return (properties_ & kWritable) != 0u;
236 return (read_write_open_ & kReadable) != 0u;
242 return (read_write_open_ & kWritable) != 0u;
247 return read_write_open_ != 0u;
273 return async2::Ready(Status::FailedPrecondition());
275 return DoPendRead(cx);
373 template <
typename, Property...>
376 template <
typename, Property...>
383 : available_writes_(available_writes),
384 properties_(properties),
385 read_write_open_{uint8_t{kReadable} | uint8_t{kWritable}} {}
391 virtual void DoStageWrite(Packet&& packet) = 0;
397 uint16_t available_writes_;
399 uint8_t read_write_open_;
408template <
typename Packet>
414template <
typename Packet>
420template <
typename Packet>
426template <
typename ChannelType>
429template <
typename Packet, Property... kProperties>
433 explicit constexpr Implement() =
default;
438template <
typename Packet>
441 PW_DASSERT(num > 0u);
443 if (!is_write_open()) {
444 return Status::FailedPrecondition();
447 if (GetAvailableWrites() < num) {
448 PW_ASYNC_STORE_WAKER(cx, write_waker_,
"waiting for available writes");
449 return async2::Pending();
451 PW_TRY_READY_ASSIGN(
Status ready, DoPendReadyToWrite(cx, num));
458template <
typename Packet>
460 if (!is_write_open()) {
461 return async2::Ready();
464 if (GetAvailableWrites() == 0u) {
465 PW_ASYNC_STORE_WAKER(
466 cx, write_waker_,
"waiting for writes to be acknowledged");
467 return async2::Pending();
470 PW_TRY_READY(DoPendWrite(cx));
472 available_writes_ -= 1;
475 return async2::Ready();
478template <
typename Packet>
480 if (available_writes > available_writes_) {
481 std::move(write_waker_).Wake();
483 available_writes_ = available_writes;
486template <
typename Packet>
488 PW_DASSERT(num_completed > 0u);
491 uint32_t new_available_writes = uint32_t{available_writes_} + num_completed;
494 available_writes_ =
static_cast<uint16_t
>(new_available_writes);
496 std::move(write_waker_).Wake();
499template <
typename Packet>
501 if (!is_read_or_write_open()) {
504 auto result = DoPendClose(cx);
505 if (result.IsReady()) {
506 set_read_write_closed();
508 std::move(write_waker_).Wake();
515template <
typename Packet, Property... kProperties>
521template <
typename Packet, Property... kProperties>
522constexpr bool PacketChannel<Packet, kProperties...>::is_write_open()
const {
524 static_cast<const AnyPacketChannel<Packet>*
>(
this)->is_write_open();
527template <
typename Packet, Property... kProperties>
528async2::Poll<Result<Packet>> PacketChannel<Packet, kProperties...>::PendRead(
529 async2::Context& cx) {
530 static_assert(readable(),
"PendRead may only be called on readable channels");
531 return static_cast<AnyPacketChannel<Packet>*
>(
this)->PendRead(cx);
534template <
typename Packet, Property... kProperties>
535async2::Poll<Result<PendingWrite<Packet>>>
536PacketChannel<Packet, kProperties...>::PendReadyToWrite(async2::Context& cx,
538 static_assert(writable(),
539 "PendReadyToWrite may only be called on writable channels");
540 return static_cast<AnyPacketChannel<Packet>*
>(
this)->PendReadyToWrite(cx,
543template <
typename Packet, Property... kProperties>
544async2::Poll<> PacketChannel<Packet, kProperties...>::PendWrite(
545 async2::Context& cx) {
546 static_assert(writable(),
547 "PendWrite may only be called on writable channels");
548 return static_cast<AnyPacketChannel<Packet>*
>(
this)->PendWrite(cx);
550template <
typename Packet, Property... kProperties>
551uint16_t PacketChannel<Packet, kProperties...>::GetAvailableWrites()
const {
552 static_assert(writable(),
553 "GetAvailableWrites may only be called on writable channels");
554 return static_cast<const AnyPacketChannel<Packet>&
>(*this)
555 .GetAvailableWrites();
557template <
typename Packet, Property... kProperties>
558void PacketChannel<Packet, kProperties...>::SetAvailableWrites(
559 uint16_t available_writes) {
560 static_assert(writable(),
561 "SetAvailableWrites may only be called on writable channels");
562 return static_cast<AnyPacketChannel<Packet>*
>(
this)->SetAvailableWrites(
565template <
typename Packet, Property... kProperties>
566void PacketChannel<Packet, kProperties...>::AcknowledgeWrites(
567 uint16_t num_completed) {
568 static_assert(writable(),
569 "AcknowledgeWrites may only be called on writable channels");
570 return static_cast<AnyPacketChannel<Packet>*
>(
this)->AcknowledgeWrites(
574template <
typename Packet, Property... kProperties>
575async2::Poll<Status> PacketChannel<Packet, kProperties...>::PendClose(
576 async2::Context& cx) {
577 return static_cast<AnyPacketChannel<Packet>*
>(
this)->PendClose(cx);
584template <
typename Packet, Property... kProperties>
589 Channel& channel() {
return *
this; }
590 const Channel& channel()
const {
return *
this; }
596 using Channel::PendRead;
598 using Channel::AcknowledgeWrites;
599 using Channel::GetAvailableWrites;
600 using Channel::PendReadyToWrite;
601 using Channel::PendWrite;
602 using Channel::SetAvailableWrites;
604 using Channel::PendClose;
613template <
typename Packet, Property... kProperties>
615 static_assert(PacketChannelPropertiesAreValid<kProperties...>());
619template <
typename Packet>
624 return async2::Ready(Status::Unimplemented());
626 void DoStageWrite(Packet&&)
final { PW_ASSERT(
false); }
631template <
typename Packet>
636 return async2::Ready(Status::Unimplemented());
641template <
typename Packet>
constexpr bool ok() const
Definition: status.h:157
Definition: packet_channel.h:217
async2::Poll< Result< PendingWrite< Packet > > > PendReadyToWrite(async2::Context &cx, size_t num=1)
Definition: packet_channel.h:440
void set_write_closed()
Definition: packet_channel.h:360
async2::Poll PendWrite(async2::Context &cx)
Definition: packet_channel.h:459
async2::Poll< Result< Packet > > PendRead(async2::Context &cx)
Definition: packet_channel.h:268
void SetAvailableWrites(uint16_t available_writes)
Definition: packet_channel.h:479
uint16_t GetAvailableWrites() const
Definition: packet_channel.h:348
constexpr bool is_read_open() const
Definition: packet_channel.h:235
async2::Poll< Status > PendClose(async2::Context &cx)
Definition: packet_channel.h:500
constexpr bool is_write_open() const
Definition: packet_channel.h:241
void set_read_closed()
Definition: packet_channel.h:354
constexpr bool is_read_or_write_open() const
True if the channel is open for either reading or writing.
Definition: packet_channel.h:246
constexpr bool readable() const
Returns whether the channel implementation is readable.
Definition: packet_channel.h:224
void AcknowledgeWrites(uint16_t num_completed)
Definition: packet_channel.h:487
void set_read_write_closed()
Definition: packet_channel.h:367
constexpr bool writable() const
Returns whether the channel implementation is writable.
Definition: packet_channel.h:229
async2::Waker & write_waker()
Allows implementations to access the write waker.
Definition: packet_channel.h:370
Definition: channel.h:583
Definition: packet_channel.h:106
Sibling & as()
Returns a reference to this as another compatible packet channel type.
Definition: packet_channel.h:173
auto & as()
Definition: packet_channel.h:187
Definition: packet_channel.h:46
void Stage(Packet &&packet)
Definition: packet_channel.h:68
Definition: packet_channel.h:585
Definition: packet_channel.h:614
constexpr uint16_t kNoFlowControl
Definition: packet_channel.h:91
constexpr Status OkStatus()
Definition: status.h:234