Pigweed
 
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 {
23namespace async2 {
24
30struct ReadyType {};
31
35struct PW_NODISCARD_STR(
36 "`Poll`-returning functions may or may not have completed. Their "
37 "return value should be examined.") PendingType {};
38
51template <typename T = ReadyType>
52class PW_NODISCARD_STR(
53 "`Poll`-returning functions may or may not have completed. Their "
54 "return value should be examined.") Poll {
55 public:
56 using OutputType = T;
57
59 Poll() = delete;
60 constexpr Poll(const Poll&) = default;
61 constexpr Poll& operator=(const Poll&) = default;
62 constexpr Poll(Poll&&) = default;
63 constexpr Poll& operator=(Poll&&) = default;
64
73 template <typename U,
74 internal_poll::EnableIfImplicitlyConvertible<T, const U&> = 0>
75 constexpr Poll(const Poll<U>& other) : value_(other.value_) {}
76 template <typename U,
77 internal_poll::EnableIfExplicitlyConvertible<T, const U&> = 0>
78 explicit constexpr Poll(const Poll<U>& other) : value_(other.value_) {}
79
80 template <typename U,
81 internal_poll::EnableIfImplicitlyConvertible<T, U&&> = 0>
82 constexpr Poll(Poll<U>&& other) // NOLINT
83 : value_(std::move(other.value_)) {}
84 template <typename U,
85 internal_poll::EnableIfExplicitlyConvertible<T, U&&> = 0>
86 explicit constexpr Poll(Poll<U>&& other) : value_(std::move(other.value_)) {}
87
88 // Constructs the inner value `T` in-place using the provided args, using the
89 // `T(U)` (direct-initialization) constructor. This constructor is only valid
90 // if `T` can be constructed from a `U`. Can accept move or copy constructors.
91 //
92 // This constructor is explicit if `U` is not convertible to `T`. To avoid
93 // ambiguity, this constructor is disabled if `U` is a `Poll<J>`, where
94 // `J` is convertible to `T`.
95 template <typename U = T,
96 internal_poll::EnableIfImplicitlyInitializable<T, U> = 0>
97 constexpr Poll(U&& u) // NOLINT
98 : Poll(std::in_place, std::forward<U>(u)) {}
99
100 template <typename U = T,
101 internal_poll::EnableIfExplicitlyInitializable<T, U> = 0>
102 explicit constexpr Poll(U&& u) // NOLINT
103 : Poll(std::in_place, std::forward<U>(u)) {}
104
105 // In-place construction of ``Ready`` variant.
106 template <typename... Args>
107 constexpr Poll(std::in_place_t, Args&&... args)
108 : value_(std::in_place, std::move(args)...) {}
109
110 // Convert from `T`
111 constexpr Poll(T&& value) : value_(std::move(value)) {}
112 constexpr Poll& operator=(T&& value) {
113 value_ = std::optional<T>(std::move(value));
114 return *this;
115 }
116
117 // Convert from `Pending`
118 constexpr Poll(PendingType) noexcept : value_() {}
119 constexpr Poll& operator=(PendingType) noexcept {
120 value_ = std::nullopt;
121 return *this;
122 }
123
125 constexpr bool IsReady() const noexcept { return value_.has_value(); }
126
128 constexpr bool IsPending() const noexcept { return !value_.has_value(); }
129
132 constexpr Poll<> Readiness() const noexcept {
133 if (IsReady()) {
134 return ReadyType();
135 } else {
136 return PendingType();
137 }
138 }
139
143 constexpr T& value() & noexcept { return *value_; }
144 constexpr const T& value() const& noexcept { return *value_; }
145 constexpr T&& value() && noexcept { return std::move(*value_); }
146 constexpr const T&& value() const&& noexcept { return std::move(*value_); }
147
151 constexpr const T* operator->() const noexcept { return &*value_; }
152 constexpr T* operator->() noexcept { return &*value_; }
153
157 constexpr const T& operator*() const& noexcept { return *value_; }
158 constexpr T& operator*() & noexcept { return *value_; }
159 constexpr const T&& operator*() const&& noexcept {
160 return std::move(*value_);
161 }
162 constexpr T&& operator*() && noexcept { return std::move(*value_); }
163
168 constexpr void IgnorePoll() const {}
169
170 private:
171 template <typename U>
172 friend class Poll;
173 std::optional<T> value_;
174};
175
176// Deduction guide to allow ``Poll(v)`` rather than ``Poll<T>(v)``.
177template <typename T>
178Poll(T value) -> Poll<T>;
179
185template <typename T>
186constexpr bool operator==(const Poll<T>& lhs, const Poll<T>& rhs) {
187 if (lhs.IsReady() && rhs.IsReady()) {
188 return *lhs == *rhs;
189 }
190 return lhs.IsReady() == rhs.IsReady();
191}
192
198template <typename T>
199constexpr bool operator!=(const Poll<T>& lhs, const Poll<T>& rhs) {
200 return !(lhs == rhs);
201}
202
204template <typename T>
205constexpr bool operator==(const Poll<T>& lhs, PendingType) {
206 return lhs.IsPending();
207}
208
210template <typename T>
211constexpr bool operator!=(const Poll<T>& lhs, PendingType) {
212 return !lhs.IsPending();
213}
214
216template <typename T>
217constexpr bool operator==(PendingType, const Poll<T>& rhs) {
218 return rhs.IsPending();
219}
220
222template <typename T>
223constexpr bool operator!=(PendingType, const Poll<T>& rhs) {
224 return !rhs.IsPending();
225}
226
227// ``ReadyType`` is the value type for `Poll<T>` and has no value,
228// so it should always compare equal.
229constexpr bool operator==(ReadyType, ReadyType) { return true; }
230constexpr bool operator!=(ReadyType, ReadyType) { return false; }
231
232// The ``Pending`` case holds no value, so is always equal.
233constexpr bool operator==(PendingType, PendingType) { return true; }
234constexpr bool operator!=(PendingType, PendingType) { return false; }
235
237inline constexpr Poll<> Ready() { return Poll(ReadyType{}); }
238
241template <typename T, typename... Args>
242constexpr Poll<T> Ready(std::in_place_t, Args&&... args) {
243 return Poll<T>(std::in_place, std::forward<Args>(args)...);
244}
245
247template <typename T>
248constexpr Poll<std::remove_reference_t<T>> Ready(T&& value) {
249 return Poll<std::remove_reference_t<T>>(std::forward<T>(value));
250}
251
253inline constexpr PendingType Pending() { return PendingType(); }
254
255} // namespace async2
256
257// --- ToString implementations for ``Poll`` types ---
258
259template <>
260inline StatusWithSize ToString(const async2::ReadyType&, span<char> buffer) {
261 return ToString("Ready", buffer);
262}
263
264template <>
265inline StatusWithSize ToString(const async2::PendingType&, span<char> buffer) {
266 return ToString("Pending", buffer);
267}
268
269// Implement ``ToString`` for ``Poll<T>``.
270template <typename T>
271inline StatusWithSize ToString(const async2::Poll<T>& poll, span<char> buffer) {
272 if (poll.IsReady()) {
273 StatusWithSize s;
274 s.UpdateAndAdd(ToString("Ready(", buffer));
275 s.UpdateAndAdd(ToString(*poll, buffer.subspan(s.size())));
276 s.UpdateAndAdd(ToString(")", buffer.subspan(s.size())));
277 s.ZeroIfNotOk();
278 return s;
279 }
280 return ToString(async2::PendingType{}, buffer);
281}
282
283template <>
284inline StatusWithSize ToString(const async2::Poll<>& poll, span<char> buffer) {
285 if (poll.IsReady()) {
286 return ToString(async2::ReadyType{}, buffer);
287 }
288 return ToString(async2::PendingType{}, buffer);
289}
290
291} // namespace pw
constexpr void UpdateAndAdd(StatusWithSize new_status_with_size)
Definition: status_with_size.h:126
Definition: poll.h:54
constexpr bool IsReady() const noexcept
Returns whether or not this value is Ready.
Definition: poll.h:125
constexpr const T * operator->() const noexcept
Definition: poll.h:151
constexpr Poll Readiness() const noexcept
Definition: poll.h:132
constexpr bool IsPending() const noexcept
Returns whether or not this value is Pending.
Definition: poll.h:128
constexpr T & value() &noexcept
Definition: poll.h:143
constexpr Poll(const Poll< U > &other)
Definition: poll.h:75
Poll()=delete
Basic constructors.
constexpr void IgnorePoll() const
Definition: poll.h:168
constexpr const T & operator*() const &noexcept
Definition: poll.h:157
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27
Definition: poll.h:37
Definition: poll.h:30