19#include "lib/stdcompat/type_traits.h"
20#include "pw_allocator/allocator.h"
21#include "pw_async2/callback_task.h"
22#include "pw_async2/dispatcher.h"
23#include "pw_async2/future.h"
24#include "pw_containers/deque.h"
25#include "pw_numeric/checked_arithmetic.h"
26#include "pw_result/result.h"
27#include "pw_sync/interrupt_spin_lock.h"
28#include "pw_sync/lock_annotations.h"
29#include "pw_sync/timed_thread_notification.h"
46class ReserveSendFuture;
51template <
typename T, u
int16_t kCapacity>
82 enum AllowClosed { kAllowClosed };
86 BaseChannelFuture(BaseChannel* channel, AllowClosed)
89 StoreAndAddRefIfNonnull(channel);
92 BaseChannelFuture(BaseChannelFuture&& other)
94 : channel_(other.channel_) {
98 BaseChannelFuture& MoveAssignFrom(BaseChannelFuture& other)
117 void StoreAndAddRefIfNonnull(BaseChannel* channel)
122 BaseChannel* channel_;
126 using List = FutureList<&BaseChannelFuture::core_>;
130template <
typename Derived,
typename T,
typename FutureValue>
156 return static_cast<Channel<T>*
>(base_channel());
160 using BaseChannelFuture::base_channel;
161 using BaseChannelFuture::MarkCompleted;
169 chrono::SystemClock::duration::max();
178 std::lock_guard lock(*
this);
179 return is_open_locked();
187 return ref_count_ != 0;
194 std::lock_guard lock(*
this);
201 send_futures_.Push(future);
207 receive_futures_.Push(future);
213 add_object(receiver_count_);
217 add_object(sender_count_);
221 add_object(handle_count_);
229 PW_DASSERT(reservations_ > 0);
234 remove_object(&sender_count_);
238 remove_object(&receiver_count_);
242 remove_object(&handle_count_);
255 receive_futures_.ResolveOneIfAvailable();
259 send_futures_.ResolveOneIfAvailable();
263 return reservations_;
268 if (is_open_locked()) {
285 return handle_count_ == 0 && (sender_count_ == 0 || receiver_count_ == 0);
291 virtual void Destroy() {}
317 using size_type = uint16_t;
325 template <
size_t kAlignment,
size_t kCapacity>
327 : dequeue_(storage) {}
330 [[nodiscard]] size_type capacity()
const {
return dequeue_.capacity(); }
331 [[nodiscard]] size_type size()
const {
return dequeue_.size(); }
332 [[nodiscard]]
bool empty()
const {
return dequeue_.empty(); }
333 [[nodiscard]]
auto deallocator()
const {
return dequeue_.deallocator(); }
334 [[nodiscard]] T& front() {
return dequeue_.front(); }
335 [[nodiscard]]
const T& front()
const {
return dequeue_.front(); }
337 void pop_front() { dequeue_.pop_front(); }
339 template <
typename U>
340 void push_back(U&& value) {
341 dequeue_.push_back(std::forward<U>(value));
344 template <
typename... Args>
345 void emplace_back(Args&&... args) {
346 dequeue_.emplace_back(std::forward<Args>(args)...);
357 using size_type = uint16_t;
366 explicit ChannelDeque(uint16_t capacity) : capacity_(capacity) {}
374 [[nodiscard]] size_type capacity()
const {
return capacity_; }
375 [[nodiscard]] size_type size()
const {
return size_; }
376 [[nodiscard]]
bool empty()
const {
return size_ == 0; }
377 [[nodiscard]]
Deallocator* deallocator()
const {
return deallocator_; }
380 PW_ASSERT(size_ < capacity_);
385 PW_ASSERT(size_ != 0);
391 : deallocator_(&alloc), capacity_(capacity) {}
394 uint16_t capacity_ = 0;
405 std::lock_guard guard(*
this);
406 if (is_open_locked()) {
415 std::lock_guard guard(*
this);
416 if (is_open_locked()) {
423 template <
typename U,
424 int&... kExplicitGuard,
425 std::enable_if_t<std::is_same_v<::cpp20::remove_cvref_t<U>, T>,
428 deque_.push_back(std::forward<U>(value));
432 template <
typename U,
433 int&... kExplicitGuard,
434 std::enable_if_t<!std::is_same_v<::cpp20::remove_cvref_t<U>, T> &&
435 std::is_constructible_v<T, U>,
438 PushAndWake(T(value));
446 template <
typename... Args>
448 deque_.emplace_back(std::forward<Args>(args)...);
453 if constexpr (std::is_void_v<T>) {
457 T value = std::move(deque_.front());
466 return remaining_capacity_locked() == 0;
470 std::lock_guard guard(*
this);
471 return remaining_capacity_locked();
474 uint16_t remaining_capacity_locked()
const
476 return deque_.capacity() - deque_.size() - reservations();
481 return deque_.capacity();
485 return deque_.empty();
488 template <
typename U,
489 int&... kExplicitGuard,
490 std::enable_if_t<std::is_same_v<::cpp20::remove_cvref_t<U>, T>,
493 std::lock_guard guard(*
this);
494 if (!is_open_locked()) {
500 PushAndWake(std::forward<U>(value));
504 template <
typename U,
505 int&... kExplicitGuard,
506 std::enable_if_t<!std::is_same_v<::cpp20::remove_cvref_t<U>, T> &&
507 std::is_constructible_v<T, U>,
510 return TrySend(T(value));
516 "TrySend() with no arguments is for notification channels only");
518 std::lock_guard guard(*
this);
519 if (!is_open_locked()) {
531 std::lock_guard guard(*
this);
532 if (deque_.empty()) {
536 if constexpr (std::is_void_v<T>) {
540 return Result(PopAndWake());
545 std::lock_guard guard(*
this);
546 if (!is_open_locked()) {
556 template <
typename... Args>
559 remove_reservation();
560 if (is_open_locked()) {
561 EmplaceAndWake(std::forward<Args>(args)...);
563 RemoveRefAndDestroyIfUnreferenced();
568 remove_reservation();
569 if (is_open_locked()) {
572 RemoveRefAndDestroyIfUnreferenced();
577 : deque_(std::move(deque)) {}
579 template <
size_t kAlignment,
size_t kCapacity>
587 return deque_.deallocator();
599 if (deque.capacity() == 0) {
612 Deallocator*
const deallocator = this->deallocator();
618template <
typename T, u
int16_t kCapacity>
628template <u
int16_t kCapacity>
651 return channel_ !=
nullptr && channel_->is_open();
669 : channel_(&channel) {
670 channel_->add_handle();
677 : channel_(std::exchange(other.channel_,
nullptr)) {}
679 BaseChannelHandle& operator=(BaseChannelHandle&& other)
noexcept
687 BaseChannel* channel_;
714 PW_ASSERT(channel() !=
nullptr);
721 PW_ASSERT(channel() !=
nullptr);
739 template <
typename U>
743 template <
typename U, u
int16_t kCapacity>
760 template <
typename U>
761 friend std::optional<std::tuple<MpscChannelHandle<U>,
Receiver<U>>>
764 template <
typename U, u
int16_t kCapacity>
781 template <
typename U>
782 friend std::optional<std::tuple<SpmcChannelHandle<U>,
Sender<U>>>
785 template <
typename U, u
int16_t kCapacity>
800 template <
typename U>
804 template <
typename U, u
int16_t kCapacity>
899template <
typename T, u
int16_t kCapacity>
903 template <
typename U, u
int16_t kCap>
907 template <
typename U, u
int16_t kCap>
908 friend std::tuple<MpscChannelHandle<U>,
Receiver<U>> CreateMpscChannel(
911 template <
typename U, u
int16_t kCap>
912 friend std::tuple<SpmcChannelHandle<U>,
Sender<U>> CreateSpmcChannel(
915 template <
typename U, u
int16_t kCap>
924 std::lock_guard lock(*
this);
925 return this->active_locked();
928 constexpr uint16_t capacity()
const {
return kCapacity; }
942 :
Base(std::move(other)) {}
947 return static_cast<ReceiveFuture&
>(this->MoveAssignFrom(other));
951 this->RemoveFromChannel();
958 template <
typename,
typename>
963 :
Base(channel, this->kAllowClosed) {}
966 if (this->channel() ==
nullptr) {
967 PW_DASSERT(this->is_pendable());
968 return Ready<std::optional<T>>(std::nullopt);
971 this->channel()->lock();
972 PW_DASSERT(this->is_pendable());
973 if (this->channel()->empty()) {
974 return this->StoreWakerForReceiveIfOpen(cx)
976 : Ready<std::optional<T>>(std::nullopt);
979 auto result =
Ready(this->channel()->PopAndWake());
996 :
Base(std::move(other)) {}
1001 return static_cast<ReceiveFuture&
>(this->MoveAssignFrom(other));
1005 this->RemoveFromChannel();
1012 template <
typename,
typename>
1017 :
Base(channel, this->kAllowClosed) {}
1020 if (this->channel() ==
nullptr) {
1021 PW_DASSERT(this->is_pendable());
1022 return Ready(
false);
1025 this->channel()->lock();
1026 PW_DASSERT(this->is_pendable());
1027 if (this->channel()->empty()) {
1028 return this->StoreWakerForReceiveIfOpen(cx) ?
Pending() :
Ready(
false);
1031 this->channel()->PopAndWake();
1038template <
typename T>
1041 constexpr Receiver() : channel_(
nullptr) {}
1047 : channel_(std::exchange(other.channel_,
nullptr)) {}
1050 if (
this == &other) {
1053 if (channel_ !=
nullptr) {
1054 channel_->remove_receiver();
1056 channel_ = std::exchange(other.channel_,
nullptr);
1061 if (channel_ !=
nullptr) {
1062 channel_->remove_receiver();
1079 if (channel_ ==
nullptr) {
1084 if constexpr (std::is_void_v<T>) {
1085 if (
Status result = channel_->TryReceive();
1086 result.ok() || result.IsFailedPrecondition()) {
1090 if (
Result<T> result = channel_->TryReceive();
1091 result.ok() || result.status().IsFailedPrecondition()) {
1097 std::conditional_t<std::is_void_v<T>, bool, std::optional<T>>;
1103 [&result, ¬ification](ReceiveType&& val) {
1104 result = std::move(val);
1108 dispatcher.Post(task);
1112 if constexpr (std::is_void_v<T>) {
1115 if (!result.has_value()) {
1126 if constexpr (std::is_void_v<T>) {
1129 if (!result.has_value()) {
1154 if (channel_ ==
nullptr) {
1158 return channel_->TryReceive();
1166 if (channel_ !=
nullptr) {
1167 channel_->remove_receiver();
1174 return channel_ !=
nullptr && channel_->is_open();
1178 template <
typename U>
1181 template <
typename U>
1182 friend std::optional<std::tuple<MpscChannelHandle<U>,
Receiver<U>>>
1185 template <
typename U, u
int16_t kCapacity>
1189 template <
typename U>
1193 template <
typename U, u
int16_t kCapacity>
1199 : channel_(&channel) {
1200 channel_->add_receiver();
1203 internal::Channel<T>* channel_;
1206template <
typename T>
1216 :
Base(
static_cast<Base&&
>(other)), value_(std::move(other.value_)) {}
1220 value_ = std::move(other.value_);
1222 return static_cast<SendFuture&
>(this->MoveAssignFrom(other));
1226 this->RemoveFromChannel();
1236 :
Base(channel), value_(value) {}
1240 :
Base(channel), value_(std::move(value)) {}
1243 if (this->channel() ==
nullptr) {
1244 PW_DASSERT(this->is_pendable());
1245 return Ready(
false);
1248 this->channel()->lock();
1249 PW_DASSERT(this->is_pendable());
1250 if (!this->channel()->is_open_locked()) {
1252 return Ready(
false);
1255 if (this->channel()->full()) {
1256 this->StoreWakerForSend(cx);
1260 this->channel()->PushAndWake(std::move(*value_));
1265 std::optional<T> value_;
1278 :
Base(
static_cast<Base&&
>(other)) {}
1283 return static_cast<SendFuture&
>(this->MoveAssignFrom(other));
1287 this->RemoveFromChannel();
1300 if (this->channel() ==
nullptr) {
1301 PW_DASSERT(this->is_pendable());
1302 return Ready(
false);
1305 this->channel()->lock();
1306 PW_DASSERT(this->is_pendable());
1307 if (!this->channel()->is_open_locked()) {
1309 return Ready(
false);
1312 if (this->channel()->full()) {
1313 this->StoreWakerForSend(cx);
1317 this->channel()->PushAndWake();
1329template <
typename T>
1336 : channel_(std::exchange(other.channel_,
nullptr)) {}
1339 if (
this == &other) {
1343 channel_ = std::exchange(other.channel_,
nullptr);
1350 template <
typename... Args>
1352 PW_ASSERT(channel_ !=
nullptr);
1353 channel_->CommitReservationAndRemoveRef(std::forward<Args>(args)...);
1357 void CommitNotification() {
1358 static_assert(std::is_void_v<T>,
1359 "CommitNotification() is for notification channels only.");
1360 PW_ASSERT(channel_ !=
nullptr);
1361 channel_->CommitNotificationReservationAndRemoveRef();
1367 if (channel_ !=
nullptr) {
1368 channel_->DropReservationAndRemoveRef();
1380 : channel_(&channel) {
1381 channel_->add_ref();
1384 internal::Channel<T>* channel_;
1387template <
typename T>
1391 std::optional<SendReservation<T>>> {
1393 using Base = internal::
1394 ChannelFuture<ReserveSendFuture, T, std::optional<SendReservation<T>>>;
1407 this->RemoveFromChannel();
1421 if (this->channel() ==
nullptr) {
1422 PW_DASSERT(this->is_pendable());
1423 return Ready<std::optional<SendReservation<T>>>(std::nullopt);
1426 this->channel()->lock();
1427 PW_DASSERT(this->is_pendable());
1428 if (!this->channel()->is_open_locked()) {
1430 return Ready<std::optional<SendReservation<T>>>(std::nullopt);
1433 if (this->channel()->remaining_capacity_locked() == 0) {
1434 this->StoreWakerForReserveSend(cx);
1438 this->channel()->add_reservation();
1446template <
typename T>
1449 constexpr Sender() : channel_(
nullptr) {}
1455 : channel_(std::exchange(other.channel_,
nullptr)) {}
1458 if (
this == &other) {
1461 if (channel_ !=
nullptr) {
1462 channel_->remove_sender();
1464 channel_ = std::exchange(other.channel_,
nullptr);
1469 if (channel_ !=
nullptr) {
1470 channel_->remove_sender();
1482 template <
typename U>
1488 static_assert(std::is_void_v<T>,
1489 "Send() with no arguments is for notification channels only");
1510 if (channel_ ==
nullptr) {
1513 return channel_->TryReserveSend();
1525 template <
typename U,
1526 int&... kExplicitGuard,
1527 std::enable_if_t<std::is_same_v<::cpp20::remove_cvref_t<U>, T>,
1530 if (channel_ ==
nullptr) {
1533 return channel_->TrySend(std::forward<U>(value));
1537 template <
typename U,
1538 int&... kExplicitGuard,
1539 std::enable_if_t<!std::is_same_v<::cpp20::remove_cvref_t<U>, T> &&
1540 std::is_constructible_v<T, U>,
1559 "TrySend() with no arguments is for notification channels only");
1560 if (channel_ ==
nullptr) {
1563 return channel_->TrySend();
1576 template <
typename U,
1577 int&... kExplicitGuard,
1578 std::enable_if_t<std::is_same_v<::cpp20::remove_cvref_t<U>, T>,
1584 return BlockingSendMoveOrCopy(dispatcher, std::forward<U>(value), timeout);
1588 template <
typename U,
1589 int&... kExplicitGuard,
1590 std::enable_if_t<!std::is_same_v<::cpp20::remove_cvref_t<U>, T> &&
1591 std::is_constructible_v<T, U>,
1597 return BlockingSendMoveOrCopy(dispatcher, T(value), timeout);
1613 return BlockingSendMoveOrCopy(dispatcher, timeout);
1621 if (channel_ !=
nullptr) {
1622 channel_->remove_sender();
1629 return channel_ !=
nullptr ? channel_->remaining_capacity() : 0;
1634 return channel_ !=
nullptr ? channel_->capacity() : 0;
1639 return channel_ !=
nullptr && channel_->is_open();
1643 template <
typename U>
1646 template <
typename U>
1647 friend std::optional<std::tuple<SpmcChannelHandle<U>,
Sender<U>>>
1650 template <
typename U, u
int16_t kCapacity>
1654 template <
typename U>
1658 template <
typename U, u
int16_t kCapacity>
1664 : channel_(&channel) {
1665 channel_->add_sender();
1668 template <
typename U>
1669 Status BlockingSendMoveOrCopy(Dispatcher& dispatcher,
1673 if (channel_ ==
nullptr) {
1677 if (Status status = channel_->TrySend(std::forward<U>(value));
1678 status.ok() || status.IsFailedPrecondition()) {
1682 return BlockingSendFuture(
1684 SendFuture<T>(channel_, std::forward<U>(value)),
1688 Status BlockingSendMoveOrCopy(Dispatcher& dispatcher,
1691 if (channel_ ==
nullptr) {
1695 if (Status status = channel_->TrySend();
1696 status.ok() || status.IsFailedPrecondition()) {
1700 return BlockingSendFuture(dispatcher, SendFuture<T>(channel_), timeout);
1703 Status BlockingSendFuture(Dispatcher& dispatcher,
1704 SendFuture<T>&& future,
1708 sync::TimedThreadNotification notification;
1711 [&status, ¬ification](
bool result) {
1712 status = result ?
OkStatus() : Status::FailedPrecondition();
1713 notification.release();
1716 dispatcher.Post(task);
1718 if (timeout == internal::Channel<T>::kWaitForever) {
1719 notification.acquire();
1723 if (!notification.try_acquire_for(timeout)) {
1730 internal::Channel<T>* channel_;
1746template <
typename T>
1748 uint16_t capacity) {
1750 if (channel ==
nullptr) {
1751 return std::nullopt;
1753 std::lock_guard lock(*channel);
1768template <
typename T, u
int16_t kCapacity>
1771 PW_DASSERT(!storage.active_locked());
1788template <
typename T>
1792 if (channel ==
nullptr) {
1793 return std::nullopt;
1795 std::lock_guard lock(*channel);
1810template <
typename T, u
int16_t kCapacity>
1814 PW_DASSERT(!storage.active_locked());
1831template <
typename T>
1835 if (channel ==
nullptr) {
1836 return std::nullopt;
1838 std::lock_guard lock(*channel);
1853template <
typename T, u
int16_t kCapacity>
1857 PW_DASSERT(!storage.active_locked());
1874template <
typename T>
1875std::optional<std::tuple<SpscChannelHandle<T>, Sender<T>, Receiver<T>>>
1878 if (channel ==
nullptr) {
1879 return std::nullopt;
1881 std::lock_guard lock(*channel);
1898template <
typename T, u
int16_t kCapacity>
1902 PW_DASSERT(!storage.active_locked());
1903 return std::make_tuple(
1912 channel_->RemoveRefAndDestroyIfUnreferenced();
Definition: allocator.h:42
T * New(Args &&... args)
Definition: allocator.h:66
Abstract interface for releasing memory.
Definition: deallocator.h:30
static constexpr Status DeadlineExceeded()
Definition: status.h:177
static constexpr Status Unavailable()
Definition: status.h:304
static constexpr Status FailedPrecondition()
Definition: status.h:243
Definition: callback_task.h:44
Channel handle for a particular type T.
Definition: channel.h:696
Sender< T > CreateSender()
Definition: channel.h:713
Receiver< T > CreateReceiver()
Definition: channel.h:720
Definition: channel.h:901
bool active() const
Definition: channel.h:923
Definition: dispatcher.h:74
constexpr bool is_pendable() const
Definition: future.h:255
void MarkComplete()
Definition: future.h:306
constexpr bool is_complete() const
Definition: future.h:260
Definition: channel.h:856
Definition: channel.h:813
A handle to a multi-producer, multi-consumer channel.
Definition: channel.h:728
friend std::optional< MpmcChannelHandle< U > > CreateMpmcChannel(Allocator &, uint16_t)
Definition: channel.h:1747
A handle to a multi-producer, single-consumer channel.
Definition: channel.h:750
friend std::optional< std::tuple< MpscChannelHandle< U >, Receiver< U > > > CreateMpscChannel(Allocator &, uint16_t)
Definition: channel.h:1789
Definition: channel.h:933
A receiver which reads values from an asynchronous channel.
Definition: channel.h:1039
friend std::optional< std::tuple< MpscChannelHandle< U >, Receiver< U > > > CreateMpscChannel(Allocator &, uint16_t)
Definition: channel.h:1789
bool is_open() const
Returns true if the channel is open.
Definition: channel.h:1173
std::conditional_t< std::is_void_v< T >, Status, Result< T > > TryReceive()
Definition: channel.h:1153
friend std::optional< std::tuple< SpscChannelHandle< U >, Sender< U >, Receiver< U > > > CreateSpscChannel(Allocator &, uint16_t)
Definition: channel.h:1876
void Disconnect()
Definition: channel.h:1165
std::conditional_t< std::is_void_v< T >, Status, Result< T > > BlockingReceive(Dispatcher &dispatcher, chrono::SystemClock::duration timeout=internal::Channel< T >::kWaitForever)
Definition: channel.h:1075
ReceiveFuture< T > Receive()
Definition: channel.h:1143
Definition: channel.h:1391
Definition: channel.h:1208
Definition: channel.h:1330
void Cancel()
Releases the reservation, making the space available for other senders.
Definition: channel.h:1366
void Commit(Args &&... args)
Commits a value to a reserved slot.
Definition: channel.h:1351
A sender which writes values to an asynchronous channel.
Definition: channel.h:1447
SendFuture< T > Send(U &&value)
Definition: channel.h:1483
Status TrySend(U &&value)
Definition: channel.h:1529
Result< SendReservation< T > > TryReserveSend()
Definition: channel.h:1509
friend std::optional< std::tuple< SpmcChannelHandle< U >, Sender< U > > > CreateSpmcChannel(Allocator &, uint16_t)
Definition: channel.h:1832
friend std::optional< std::tuple< SpscChannelHandle< U >, Sender< U >, Receiver< U > > > CreateSpscChannel(Allocator &, uint16_t)
Definition: channel.h:1876
ReserveSendFuture< T > ReserveSend()
Definition: channel.h:1498
uint16_t capacity() const
Returns the maximum capacity of the channel.
Definition: channel.h:1633
Status BlockingSend(Dispatcher &dispatcher, chrono::SystemClock::duration timeout=internal::Channel< T >::kWaitForever)
Definition: channel.h:1610
Status BlockingSend(Dispatcher &dispatcher, U &&value, chrono::SystemClock::duration timeout=internal::Channel< T >::kWaitForever)
Definition: channel.h:1580
uint16_t remaining_capacity() const
Returns the remaining capacity of the channel.
Definition: channel.h:1628
void Disconnect()
Definition: channel.h:1620
bool is_open() const
Returns true if the channel is open.
Definition: channel.h:1638
Status TrySend()
Definition: channel.h:1556
A handle to a single-producer, multi-consumer channel.
Definition: channel.h:771
friend std::optional< std::tuple< SpmcChannelHandle< U >, Sender< U > > > CreateSpmcChannel(Allocator &, uint16_t)
Definition: channel.h:1832
A handle to a single-producer, single-consumer channel.
Definition: channel.h:792
friend std::optional< std::tuple< SpscChannelHandle< U >, Sender< U >, Receiver< U > > > CreateSpscChannel(Allocator &, uint16_t)
Definition: channel.h:1876
bool is_complete() const
True if the future has returned Ready().
Definition: channel.h:75
bool is_pendable() const
True if the Pend can be called on the future.
Definition: channel.h:72
Definition: channel.h:642
Definition: channel.h:166
Definition: channel.h:620
Definition: channel.h:316
Definition: channel.h:131
Definition: channel.h:401
Definition: channel.h:595
Definition: interrupt_spin_lock.h:50
Definition: timed_thread_notification.h:40
bool try_acquire_for(chrono::SystemClock::duration timeout)
void Deallocate(void *ptr)
Definition: deallocator.h:314
std::optional< std::tuple< SpmcChannelHandle< T >, Sender< T > > > CreateSpmcChannel(Allocator &alloc, uint16_t capacity)
Definition: channel.h:1832
std::optional< std::tuple< MpscChannelHandle< T >, Receiver< T > > > CreateMpscChannel(Allocator &alloc, uint16_t capacity)
Definition: channel.h:1789
std::optional< MpmcChannelHandle< T > > CreateMpmcChannel(Allocator &alloc, uint16_t capacity)
Definition: channel.h:1747
std::optional< std::tuple< SpscChannelHandle< T >, Sender< T >, Receiver< T > > > CreateSpscChannel(Allocator &alloc, uint16_t capacity)
Definition: channel.h:1876
std::conditional_t< std::is_void_v< typename T::value_type >, ReadyType, typename T::value_type > FutureValue
Definition: future.h:110
constexpr bool IsReady() const noexcept
Returns whether or not this value is Ready.
Definition: poll.h:211
constexpr PendingType Pending()
Returns a value indicating that an operation was not yet able to complete.
Definition: poll.h:353
constexpr Poll Ready()
Returns a value indicating completion.
Definition: poll.h:337
std::chrono::duration< rep, period > duration
Alias for durations representable with this clock.
Definition: system_clock.h:91
constexpr bool CheckedIncrement(T &base, Inc inc)
Definition: checked_arithmetic.h:118
constexpr Status OkStatus()
Definition: status.h:450
#define PW_LOCKABLE(name)
Definition: lock_annotations.h:210
#define PW_GUARDED_BY(x)
Definition: lock_annotations.h:60
#define PW_NO_LOCK_SAFETY_ANALYSIS
Definition: lock_annotations.h:296
#define PW_EXCLUSIVE_LOCK_FUNCTION(...)
Definition: lock_annotations.h:232
#define PW_EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: lock_annotations.h:147
#define PW_LOCK_RETURNED(x)
Definition: lock_annotations.h:199
#define PW_UNLOCK_FUNCTION(...)
Definition: lock_annotations.h:249
#define PW_LOCKS_EXCLUDED(...)
Definition: lock_annotations.h:178