C/C++ API Reference
Loading...
Searching...
No Matches
box.h
1// Copyright 2026 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 <utility>
17
18#include "pw_allocator/allocator.h"
19#include "pw_allocator/unique_ptr.h"
20#include "pw_async2/future.h"
21#include "pw_async2/poll.h"
22
23namespace pw::async2 {
24
25namespace internal {
26
27template <typename T>
29 public:
30 using value_type = T;
31
32 BoxedFutureBase() = default;
33 BoxedFutureBase(const BoxedFutureBase&) = delete;
34 BoxedFutureBase& operator=(const BoxedFutureBase&) = delete;
36 BoxedFutureBase& operator=(BoxedFutureBase&&) = default;
37
38 virtual ~BoxedFutureBase() = default;
39 virtual bool is_pendable() const = 0;
40 virtual bool is_complete() const = 0;
41 virtual Poll<T> Pend(Context& cx) = 0;
42};
43
44template <typename T, typename FutureType>
45class BoxedFutureImpl final : public BoxedFutureBase<T> {
46 public:
47 explicit BoxedFutureImpl(FutureType&& future) : future_(std::move(future)) {}
48
49 bool is_pendable() const override { return future_.is_pendable(); }
50 bool is_complete() const override { return future_.is_complete(); }
51 Poll<T> Pend(Context& cx) override { return future_.Pend(cx); }
52
53 private:
54 FutureType future_;
55};
56
57} // namespace internal
58
64template <typename T>
65class BoxedFuture final {
66 public:
67 using value_type = T;
68
70 BoxedFuture() : future_(nullptr) { state_.completed = false; }
71
72 BoxedFuture(const BoxedFuture&) = delete;
73 BoxedFuture& operator=(const BoxedFuture&) = delete;
74
75 BoxedFuture(BoxedFuture&& other) noexcept : future_(other.future_) {
76 MoveFrom(other);
77 }
78
79 BoxedFuture& operator=(BoxedFuture&& other) noexcept {
80 Destroy();
81 future_ = other.future_;
82 MoveFrom(other);
83 return *this;
84 }
85
86 ~BoxedFuture() { Destroy(); }
87
89 bool is_pendable() const {
90 return future_ != nullptr && future_->is_pendable();
91 }
92
94 bool is_complete() const {
95 return future_ == nullptr ? state_.completed : future_->is_complete();
96 }
97
100 PW_ASSERT(future_ != nullptr);
101 Poll<T> result = future_->Pend(cx);
102 if (result.IsReady()) {
103 Destroy();
104 future_ = nullptr;
105 state_.completed = true;
106 }
107 return result;
108 }
109
110 private:
111 template <typename FutureType>
113 Allocator& alloc, FutureType&& future);
114
116 Allocator* allocator)
117 : future_(future) {
118 state_.allocator = allocator;
119 }
120
121 void MoveFrom(BoxedFuture& other) {
122 if (future_ != nullptr) {
123 state_.allocator = other.state_.allocator;
124 } else {
125 state_.completed = other.state_.completed;
126 }
127 other.future_ = nullptr;
128 other.state_.completed = false;
129 }
130
131 void Destroy() {
132 if (future_ != nullptr) {
133 Allocator* alloc = state_.allocator;
134 future_->~BoxedFutureBase();
135 alloc->Deallocate(future_);
136 }
137 }
138
139 internal::BoxedFutureBase<T>* future_;
140 union State {
141 Allocator* allocator;
142 bool completed;
143 } state_;
144};
145
159template <typename FutureType>
161 Allocator& alloc, FutureType&& future) {
162 static_assert(!std::is_lvalue_reference_v<FutureType>);
163 using ValueType = typename std::decay_t<FutureType>::value_type;
164 using ImplType =
166 auto ptr = alloc.New<ImplType>(std::forward<FutureType>(future));
167 if (ptr == nullptr) {
168 return BoxedFuture<ValueType>();
169 }
170 return BoxedFuture<ValueType>(ptr, &alloc);
171}
172
173} // namespace pw::async2
Definition: allocator.h:45
std::enable_if_t<!std::is_array_v< T >, T * > New(Args &&... args)
Definition: allocator.h:66
Definition: box.h:65
bool is_complete() const
Returns whether the future has completed.
Definition: box.h:94
bool is_pendable() const
Returns whether Pend() can be called.
Definition: box.h:89
Poll< T > Pend(Context &cx)
Advances the future.
Definition: box.h:99
BoxedFuture()
Constructs an empty BoxedFuture.
Definition: box.h:70
friend BoxedFuture< typename std::decay_t< FutureType >::value_type > BoxFuture(Allocator &alloc, FutureType &&future)
Definition: box.h:160
Definition: context.h:46
Definition: poll.h:138
constexpr bool IsReady() const noexcept
Returns whether or not this value is Ready.
Definition: poll.h:211