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;
280 return DoPendRead(cx);
378 template <
typename, Property...>
381 template <
typename, Property...>
388 : available_writes_(available_writes),
389 properties_(properties),
390 read_write_open_{uint8_t{kReadable} | uint8_t{kWritable}} {}
396 virtual void DoStageWrite(Packet&& packet) = 0;
402 uint16_t available_writes_;
404 uint8_t read_write_open_;
413template <
typename Packet>
419template <
typename Packet>
425template <
typename Packet>
431template <
typename ChannelType>
434template <
typename Packet, Property... kProperties>
438 explicit constexpr Implement() =
default;
443template <
typename Packet>
446 PW_DASSERT(num > 0u);
448 if (!is_write_open()) {
449 return Status::FailedPrecondition();
452 if (GetAvailableWrites() < num) {
463template <
typename Packet>
465 if (!is_write_open()) {
469 if (GetAvailableWrites() == 0u) {
471 cx, write_waker_,
"waiting for writes to be acknowledged");
477 available_writes_ -= 1;
483template <
typename Packet>
485 if (available_writes > available_writes_) {
486 std::move(write_waker_).Wake();
488 available_writes_ = available_writes;
491template <
typename Packet>
493 PW_DASSERT(num_completed > 0u);
496 uint32_t new_available_writes = uint32_t{available_writes_} + num_completed;
499 available_writes_ =
static_cast<uint16_t
>(new_available_writes);
501 std::move(write_waker_).Wake();
504template <
typename Packet>
506 if (!is_read_or_write_open()) {
509 auto result = DoPendClose(cx);
510 if (result.IsReady()) {
511 set_read_write_closed();
513 std::move(write_waker_).Wake();
520template <
typename Packet, Property... kProperties>
526template <
typename Packet, Property... kProperties>
527constexpr bool PacketChannel<Packet, kProperties...>::is_write_open()
const {
529 static_cast<const AnyPacketChannel<Packet>*
>(
this)->is_write_open();
532template <
typename Packet, Property... kProperties>
533async2::PollResult<Packet> PacketChannel<Packet, kProperties...>::PendRead(
534 async2::Context& cx) {
535 static_assert(readable(),
"PendRead may only be called on readable channels");
536 return static_cast<AnyPacketChannel<Packet>*
>(
this)->PendRead(cx);
539template <
typename Packet, Property... kProperties>
540async2::PollResult<PendingWrite<Packet>>
541PacketChannel<Packet, kProperties...>::PendReadyToWrite(async2::Context& cx,
543 static_assert(writable(),
544 "PendReadyToWrite may only be called on writable channels");
545 return static_cast<AnyPacketChannel<Packet>*
>(
this)->PendReadyToWrite(cx,
548template <
typename Packet, Property... kProperties>
549async2::Poll<> PacketChannel<Packet, kProperties...>::PendWrite(
550 async2::Context& cx) {
551 static_assert(writable(),
552 "PendWrite may only be called on writable channels");
553 return static_cast<AnyPacketChannel<Packet>*
>(
this)->PendWrite(cx);
555template <
typename Packet, Property... kProperties>
556uint16_t PacketChannel<Packet, kProperties...>::GetAvailableWrites()
const {
557 static_assert(writable(),
558 "GetAvailableWrites may only be called on writable channels");
559 return static_cast<const AnyPacketChannel<Packet>&
>(*this)
560 .GetAvailableWrites();
562template <
typename Packet, Property... kProperties>
563void PacketChannel<Packet, kProperties...>::SetAvailableWrites(
564 uint16_t available_writes) {
565 static_assert(writable(),
566 "SetAvailableWrites may only be called on writable channels");
567 return static_cast<AnyPacketChannel<Packet>*
>(
this)->SetAvailableWrites(
570template <
typename Packet, Property... kProperties>
571void PacketChannel<Packet, kProperties...>::AcknowledgeWrites(
572 uint16_t num_completed) {
573 static_assert(writable(),
574 "AcknowledgeWrites may only be called on writable channels");
575 return static_cast<AnyPacketChannel<Packet>*
>(
this)->AcknowledgeWrites(
579template <
typename Packet, Property... kProperties>
580async2::Poll<Status> PacketChannel<Packet, kProperties...>::PendClose(
581 async2::Context& cx) {
582 return static_cast<AnyPacketChannel<Packet>*
>(
this)->PendClose(cx);
589template <
typename Packet, Property... kProperties>
594 Channel& channel() {
return *
this; }
595 const Channel& channel()
const {
return *
this; }
601 using Channel::PendRead;
603 using Channel::AcknowledgeWrites;
604 using Channel::GetAvailableWrites;
605 using Channel::PendReadyToWrite;
606 using Channel::PendWrite;
607 using Channel::SetAvailableWrites;
609 using Channel::PendClose;
618template <
typename Packet, Property... kProperties>
620 static_assert(PacketChannelPropertiesAreValid<kProperties...>());
624template <
typename Packet>
631 void DoStageWrite(Packet&&)
final { PW_ASSERT(
false); }
636template <
typename Packet>
646template <
typename Packet>
constexpr bool ok() const
Definition: status.h:158
Definition: packet_channel.h:222
Definition: channel.h:583
Definition: packet_channel.h:111
auto & as()
Definition: packet_channel.h:192
Definition: packet_channel.h:48
Definition: packet_channel.h:590
Definition: packet_channel.h:619
#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:365
async2::Poll PendWrite(async2::Context &cx)
Definition: packet_channel.h:464
void SetAvailableWrites(uint16_t available_writes)
Definition: packet_channel.h:484
uint16_t GetAvailableWrites() const
Definition: packet_channel.h:353
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:273
async2::Poll< Status > PendClose(async2::Context &cx)
Definition: packet_channel.h:505
constexpr bool is_write_open() const
Definition: packet_channel.h:246
void set_read_closed()
Definition: packet_channel.h:359
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:492
void set_read_write_closed()
Definition: packet_channel.h:372
async2::PollResult< PendingWrite< Packet > > PendReadyToWrite(async2::Context &cx, size_t num=1)
Definition: packet_channel.h:445
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:375
constexpr Status OkStatus()
Definition: status.h:235