C/C++ API Reference
Loading...
Searching...
No Matches
poll.h
1// Copyright 2023 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 <optional>
17
18#include "pw_async2/internal/poll_internal.h"
19#include "pw_polyfill/language_feature_macros.h"
20#include "pw_string/to_string.h"
21
22namespace pw {
23
24template <typename>
25class Result;
26
27namespace async2 {
28
30
36struct ReadyType {};
37
42 "`Poll`-returning functions may or may not have completed. Their "
43 "return value should be examined.") PendingType {};
44
57template <typename T = ReadyType>
59 "`Poll`-returning functions may or may not have completed. Their "
60 "return value should be examined.") Poll {
61 public:
62 using value_type = T;
63
65 Poll() = delete;
66 constexpr Poll(const Poll&) = default;
67 constexpr Poll& operator=(const Poll&) = default;
68 constexpr Poll(Poll&&) = default;
69 constexpr Poll& operator=(Poll&&) = default;
70
79 template <
80 typename U,
81 internal_poll::EnableIfImplicitlyConvertible<value_type, const U&> = 0>
82 constexpr Poll(const Poll<U>& other) : value_(other.value_) {}
83 template <
84 typename U,
85 internal_poll::EnableIfExplicitlyConvertible<value_type, const U&> = 0>
86 explicit constexpr Poll(const Poll<U>& other) : value_(other.value_) {}
87
88 template <typename U,
89 internal_poll::EnableIfImplicitlyConvertible<value_type, U&&> = 0>
90 constexpr Poll(Poll<U>&& other) // NOLINT
91 : value_(std::move(other.value_)) {}
92 template <typename U,
93 internal_poll::EnableIfExplicitlyConvertible<value_type, U&&> = 0>
94 explicit constexpr Poll(Poll<U>&& other) : value_(std::move(other.value_)) {}
95
96 // Constructs the inner value `T` in-place using the provided args, using the
97 // `T(U)` (direct-initialization) constructor. This constructor is only valid
98 // if `T` can be constructed from a `U`. Can accept move or copy constructors.
99 //
100 // This constructor is explicit if `U` is not convertible to `T`. To avoid
101 // ambiguity, this constructor is disabled if `U` is a `Poll<J>`, where
102 // `J` is convertible to `T`.
103 template <typename U = value_type,
104 internal_poll::EnableIfImplicitlyInitializable<value_type, U> = 0>
105 constexpr Poll(U&& u) // NOLINT
106 : Poll(std::in_place, std::forward<U>(u)) {}
107
108 template <typename U = value_type,
109 internal_poll::EnableIfExplicitlyInitializable<value_type, U> = 0>
110 explicit constexpr Poll(U&& u) // NOLINT
111 : Poll(std::in_place, std::forward<U>(u)) {}
112
113 // In-place construction of ``Ready`` variant.
114 template <typename... Args>
115 constexpr Poll(std::in_place_t, Args&&... args)
116 : value_(std::in_place, std::move(args)...) {}
117
118 // Convert from `T`
119 constexpr Poll(value_type&& value) : value_(std::move(value)) {}
120 constexpr Poll& operator=(value_type&& value) {
121 value_ = std::optional<value_type>(std::move(value));
122 return *this;
123 }
124
125 // Convert from `Pending`
126 constexpr Poll(PendingType) noexcept : value_() {}
127 constexpr Poll& operator=(PendingType) noexcept {
128 value_ = std::nullopt;
129 return *this;
130 }
131
133 constexpr bool IsReady() const noexcept { return value_.has_value(); }
134
136 constexpr bool IsPending() const noexcept { return !value_.has_value(); }
137
140 constexpr Poll<> Readiness() const noexcept {
141 if (IsReady()) {
142 return ReadyType();
143 } else {
144 return PendingType();
145 }
146 }
147
151 constexpr value_type& value() & noexcept { return *value_; }
152 constexpr const value_type& value() const& noexcept { return *value_; }
153 constexpr value_type&& value() && noexcept { return std::move(*value_); }
154 constexpr const value_type&& value() const&& noexcept {
155 return std::move(*value_);
156 }
157
161 constexpr const value_type* operator->() const noexcept { return &*value_; }
162 constexpr value_type* operator->() noexcept { return &*value_; }
163
167 constexpr const value_type& operator*() const& noexcept { return *value_; }
168 constexpr value_type& operator*() & noexcept { return *value_; }
169 constexpr const value_type&& operator*() const&& noexcept {
170 return std::move(*value_);
171 }
172 constexpr value_type&& operator*() && noexcept { return std::move(*value_); }
173
178 constexpr void IgnorePoll() const {}
179
180 private:
181 template <typename U>
182 friend class Poll;
183 std::optional<value_type> value_;
184};
185
186// Deduction guide to allow ``Poll(v)`` rather than ``Poll<T>(v)``.
187template <typename T>
188Poll(T value) -> Poll<T>;
189
191template <typename T>
193
195template <typename T>
197
203template <typename T>
204constexpr bool operator==(const Poll<T>& lhs, const Poll<T>& rhs) {
205 if (lhs.IsReady() && rhs.IsReady()) {
206 return *lhs == *rhs;
207 }
208 return lhs.IsReady() == rhs.IsReady();
209}
210
216template <typename T>
217constexpr bool operator!=(const Poll<T>& lhs, const Poll<T>& rhs) {
218 return !(lhs == rhs);
219}
220
222template <typename T>
223constexpr bool operator==(const Poll<T>& lhs, PendingType) {
224 return lhs.IsPending();
225}
226
228template <typename T>
229constexpr bool operator!=(const Poll<T>& lhs, PendingType) {
230 return !lhs.IsPending();
231}
232
234template <typename T>
235constexpr bool operator==(PendingType, const Poll<T>& rhs) {
236 return rhs.IsPending();
237}
238
240template <typename T>
241constexpr bool operator!=(PendingType, const Poll<T>& rhs) {
242 return !rhs.IsPending();
243}
244
245// ``ReadyType`` is the value type for `Poll<T>` and has no value,
246// so it should always compare equal.
247constexpr bool operator==(ReadyType, ReadyType) { return true; }
248constexpr bool operator!=(ReadyType, ReadyType) { return false; }
249
250// The ``Pending`` case holds no value, so is always equal.
251constexpr bool operator==(PendingType, PendingType) { return true; }
252constexpr bool operator!=(PendingType, PendingType) { return false; }
253
255inline constexpr Poll<> Ready() { return Poll(ReadyType{}); }
256
259template <typename T, typename... Args>
260constexpr Poll<T> Ready(std::in_place_t, Args&&... args) {
261 return Poll<T>(std::in_place, std::forward<Args>(args)...);
262}
263
265template <typename T>
267 return Poll<std::remove_reference_t<T>>(std::forward<T>(value));
268}
269
271inline constexpr PendingType Pending() { return PendingType(); }
272
273template <typename T>
275 using Type = T;
276};
277
278template <typename T>
279struct UnwrapPoll<Poll<T>> {
280 using Type = T;
281};
282
283} // namespace async2
284
285// --- ToString implementations for ``Poll`` types ---
286
287template <>
288inline StatusWithSize ToString(const async2::ReadyType&, span<char> buffer) {
289 return ToString("Ready", buffer);
290}
291
292template <>
293inline StatusWithSize ToString(const async2::PendingType&, span<char> buffer) {
294 return ToString("Pending", buffer);
295}
296
297// Implement ``ToString`` for ``Poll<T>``.
298template <typename T>
299inline StatusWithSize ToString(const async2::Poll<T>& poll, span<char> buffer) {
300 if (poll.IsReady()) {
301 StatusWithSize s;
302 s.UpdateAndAdd(ToString("Ready(", buffer));
303 s.UpdateAndAdd(ToString(*poll, buffer.subspan(s.size())));
304 s.UpdateAndAdd(ToString(")", buffer.subspan(s.size())));
305 s.ZeroIfNotOk();
306 return s;
307 }
308 return ToString(async2::PendingType{}, buffer);
309}
310
311template <>
312inline StatusWithSize ToString(const async2::Poll<>& poll, span<char> buffer) {
313 if (poll.IsReady()) {
314 return ToString(async2::ReadyType{}, buffer);
315 }
316 return ToString(async2::PendingType{}, buffer);
317}
318
320
321} // namespace pw
Definition: poll.h:25
Definition: status_with_size.h:51
constexpr void UpdateAndAdd(StatusWithSize new_status_with_size)
Definition: status_with_size.h:128
Definition: poll.h:60
Definition: span_impl.h:235
constexpr const value_type & operator*() const &noexcept
Definition: poll.h:167
constexpr bool operator!=(const Poll< T > &lhs, const Poll< T > &rhs)
Definition: poll.h:217
constexpr bool IsReady() const noexcept
Returns whether or not this value is Ready.
Definition: poll.h:133
constexpr bool operator==(const Poll< T > &lhs, const Poll< T > &rhs)
Definition: poll.h:204
constexpr Poll Readiness() const noexcept
Definition: poll.h:140
constexpr const value_type * operator->() const noexcept
Definition: poll.h:161
constexpr bool IsPending() const noexcept
Returns whether or not this value is Pending.
Definition: poll.h:136
constexpr Poll(const Poll< U > &other)
Definition: poll.h:82
constexpr PendingType Pending()
Returns a value indicating that an operation was not yet able to complete.
Definition: poll.h:271
constexpr value_type & value() &noexcept
Definition: poll.h:151
Poll()=delete
Basic constructors.
constexpr void IgnorePoll() const
Definition: poll.h:178
constexpr Poll Ready()
Returns a value indicating completion.
Definition: poll.h:255
#define PW_NODISCARD_STR(str)
Definition: language_feature_macros.h:61
The Pigweed namespace.
Definition: alignment.h:27
Definition: poll.h:43
Definition: poll.h:36
Definition: poll.h:274