C/C++ API Reference
Loading...
Searching...
No Matches
pendable.h
1// Copyright 2025 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 <tuple>
17#include <type_traits>
18
19#include "pw_async2/context.h"
20#include "pw_async2/poll.h"
21
22namespace pw::async2 {
23namespace internal {
24
27template <typename T, typename... Args>
28using PendableFunction = Poll<T>(Context&, Args...);
29
30template <typename Func>
32 using Function = Func;
33 static constexpr bool kIsPendable = false;
34};
35
36template <typename T, typename... Args>
37struct PendableTraits<PendableFunction<T, Args...>*> {
38 using Output = T;
39 using Arguments = std::tuple<Args...>;
40 static constexpr bool kIsPendable = true;
41};
42
43template <typename T, typename C, typename... Args>
44struct PendableTraits<PendableFunction<T, Args...>(C::*)> {
45 using Class = C;
46 using Output = T;
47 using Arguments = std::tuple<Args...>;
48 static constexpr bool kIsPendable = true;
49};
50
51template <auto Func>
52inline constexpr bool IsPendable = PendableTraits<decltype(Func)>::kIsPendable;
53
54} // namespace internal
55
57
60template <auto Func>
62 public:
63 using FuncType = decltype(Func);
65 using Class = typename Traits::Class;
66 using Output = typename Traits::Output;
67 using Arguments = typename Traits::Arguments;
68
70 MemberPendableWrapper& operator=(const MemberPendableWrapper&) = delete;
71
73 : object_(other.object_), args_(std::move(other.args_)) {
74 other.object_ = nullptr;
75 }
76
78 object_ = other.object_;
79 args_ = std::move(other.args_);
80 other.object_ = nullptr;
81 return *this;
82 }
83
84 ~MemberPendableWrapper() = default;
85
86 Poll<Output> Pend(Context& cx) {
87 PW_ASSERT(object_ != nullptr);
88 auto func = [&](auto&&... args) -> Poll<Output> {
89 return std::invoke(
90 Func, object_, cx, std::forward<decltype(args)>(args)...);
91 };
92 Poll<Output> result = std::apply(func, args_);
93 if (result.IsReady()) {
94 object_ = nullptr;
95 }
96 return result;
97 }
98
99 constexpr bool completed() const { return object_ == nullptr; }
100
101 private:
102 template <auto MemberFuncParam,
103 typename TraitsParam,
104 typename EnableIfParam,
105 typename... ArgsParam>
106 friend constexpr MemberPendableWrapper<MemberFuncParam> PendableFor(
107 typename TraitsParam::Class& obj, ArgsParam&&... args);
108
109 template <
110 typename... Args,
111 typename = std::enable_if_t<std::is_member_function_pointer_v<FuncType> &&
112 std::is_constructible_v<Arguments, Args...>>>
113 constexpr MemberPendableWrapper(Class& obj, Args&&... args)
114 : object_(&obj), args_(std::forward<Args>(args)...) {
115 static_assert(std::conjunction_v<std::is_copy_constructible<Args>...>,
116 "Arguments stored in a PendableWrapper must be copyable");
117 }
118 Class* object_;
119 Arguments args_;
120};
121
124template <auto Func>
126 public:
127 using FuncType = decltype(Func);
129 using Output = typename Traits::Output;
130 using Arguments = typename Traits::Arguments;
131
133 FreePendableWrapper& operator=(const FreePendableWrapper&) = delete;
134
136 FreePendableWrapper& operator=(FreePendableWrapper&&) = default;
137
138 ~FreePendableWrapper() = default;
139
140 Poll<Output> Pend(Context& cx) {
141 auto func = [&](auto&&... args) -> Poll<Output> {
142 return std::invoke(Func, cx, std::forward<decltype(args)>(args)...);
143 };
144 Poll<Output> result = std::apply(func, args_);
145 completed_ = result.IsReady();
146 return result;
147 }
148
149 constexpr bool completed() const { return completed_; }
150
151 private:
152 template <auto FreeFuncParam,
153 typename TraitsParam,
154 typename EnableIfParam,
155 typename... ArgsParam>
156 friend constexpr FreePendableWrapper<FreeFuncParam> PendableFor(
157 ArgsParam&&... args);
158
159 template <typename... Args,
160 typename =
161 std::enable_if_t<!std::is_member_function_pointer_v<FuncType> &&
162 std::is_constructible_v<Arguments, Args...>>>
163 constexpr FreePendableWrapper(Args&&... args)
164 : args_(std::forward<Args>(args)...), completed_(false) {
165 static_assert(std::conjunction_v<std::is_copy_constructible<Args>...>,
166 "Arguments stored in a PendableWrapper must be copyable");
167 }
168
169 Arguments args_;
170 bool completed_;
171};
172
181template <auto MemberFunc,
182 typename Traits = internal::PendableTraits<decltype(MemberFunc)>,
183 typename = std::enable_if_t<
184 Traits::kIsPendable &&
185 std::is_member_function_pointer_v<decltype(MemberFunc)>>,
186 typename... Args>
188 typename Traits::Class& obj, Args&&... args) {
189 return MemberPendableWrapper<MemberFunc>(obj, std::forward<Args>(args)...);
190}
191
200template <auto FreeFunc,
201 typename Traits = internal::PendableTraits<decltype(FreeFunc)>,
202 typename = std::enable_if_t<
203 Traits::kIsPendable &&
204 !std::is_member_function_pointer_v<decltype(FreeFunc)>>,
205 typename... Args>
206inline constexpr FreePendableWrapper<FreeFunc> PendableFor(Args&&... args) {
207 return FreePendableWrapper<FreeFunc>(std::forward<Args>(args)...);
208}
209
211
212} // namespace pw::async2
Definition: context.h:55
Definition: pendable.h:125
Definition: pendable.h:61
Definition: poll.h:60
constexpr MemberPendableWrapper< MemberFunc > PendableFor(typename Traits::Class &obj, Args &&... args)
Definition: pendable.h:187
constexpr bool IsReady() const noexcept
Returns whether or not this value is Ready.
Definition: poll.h:133
Definition: pendable.h:31