Pigweed
C/C++ API Reference
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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
58template <auto Func>
60 public:
61 using FuncType = decltype(Func);
63 using Class = typename Traits::Class;
64 using Output = typename Traits::Output;
65 using Arguments = typename Traits::Arguments;
66
68 MemberPendableWrapper& operator=(const MemberPendableWrapper&) = delete;
69
71 : object_(other.object_), args_(std::move(other.args_)) {
72 other.object_ = nullptr;
73 }
74
76 object_ = other.object_;
77 args_ = std::move(other.args_);
78 other.object_ = nullptr;
79 return *this;
80 }
81
82 ~MemberPendableWrapper() = default;
83
84 Poll<Output> Pend(Context& cx) {
85 PW_ASSERT(object_ != nullptr);
86 auto func = [&](auto&&... args) -> Poll<Output> {
87 return std::invoke(
88 Func, object_, cx, std::forward<decltype(args)>(args)...);
89 };
90 Poll<Output> result = std::apply(func, args_);
91 if (result.IsReady()) {
92 object_ = nullptr;
93 }
94 return result;
95 }
96
97 constexpr bool completed() const { return object_ == nullptr; }
98
99 private:
100 template <auto MemberFuncParam,
101 typename TraitsParam,
102 typename EnableIfParam,
103 typename... ArgsParam>
104 friend constexpr MemberPendableWrapper<MemberFuncParam> PendableFor(
105 typename TraitsParam::Class& obj, ArgsParam&&... args);
106
107 template <
108 typename... Args,
109 typename = std::enable_if_t<std::is_member_function_pointer_v<FuncType> &&
110 std::is_constructible_v<Arguments, Args...>>>
111 constexpr MemberPendableWrapper(Class& obj, Args&&... args)
112 : object_(&obj), args_(std::forward<Args>(args)...) {
113 static_assert(std::conjunction_v<std::is_copy_constructible<Args>...>,
114 "Arguments stored in a PendableWrapper must be copyable");
115 }
116 Class* object_;
117 Arguments args_;
118};
119
122template <auto Func>
124 public:
125 using FuncType = decltype(Func);
127 using Output = typename Traits::Output;
128 using Arguments = typename Traits::Arguments;
129
131 FreePendableWrapper& operator=(const FreePendableWrapper&) = delete;
132
134 FreePendableWrapper& operator=(FreePendableWrapper&&) = default;
135
136 ~FreePendableWrapper() = default;
137
138 Poll<Output> Pend(Context& cx) {
139 auto func = [&](auto&&... args) -> Poll<Output> {
140 return std::invoke(Func, cx, std::forward<decltype(args)>(args)...);
141 };
142 Poll<Output> result = std::apply(func, args_);
143 completed_ = result.IsReady();
144 return result;
145 }
146
147 constexpr bool completed() const { return completed_; }
148
149 private:
150 template <auto FreeFuncParam,
151 typename TraitsParam,
152 typename EnableIfParam,
153 typename... ArgsParam>
154 friend constexpr FreePendableWrapper<FreeFuncParam> PendableFor(
155 ArgsParam&&... args);
156
157 template <typename... Args,
158 typename =
159 std::enable_if_t<!std::is_member_function_pointer_v<FuncType> &&
160 std::is_constructible_v<Arguments, Args...>>>
161 constexpr FreePendableWrapper(Args&&... args)
162 : args_(std::forward<Args>(args)...), completed_(false) {
163 static_assert(std::conjunction_v<std::is_copy_constructible<Args>...>,
164 "Arguments stored in a PendableWrapper must be copyable");
165 }
166
167 Arguments args_;
168 bool completed_;
169};
170
173
182template <auto MemberFunc,
183 typename Traits = internal::PendableTraits<decltype(MemberFunc)>,
184 typename = std::enable_if_t<
185 Traits::kIsPendable &&
186 std::is_member_function_pointer_v<decltype(MemberFunc)>>,
187 typename... Args>
189 typename Traits::Class& obj, Args&&... args) {
190 return MemberPendableWrapper<MemberFunc>(obj, std::forward<Args>(args)...);
191}
192
201template <auto FreeFunc,
202 typename Traits = internal::PendableTraits<decltype(FreeFunc)>,
203 typename = std::enable_if_t<
204 Traits::kIsPendable &&
205 !std::is_member_function_pointer_v<decltype(FreeFunc)>>,
206 typename... Args>
207inline constexpr FreePendableWrapper<FreeFunc> PendableFor(Args&&... args) {
208 return FreePendableWrapper<FreeFunc>(std::forward<Args>(args)...);
209}
210
212
213} // namespace pw::async2
Definition: context.h:53
Definition: pendable.h:123
Definition: pendable.h:59
Definition: poll.h:54
constexpr bool IsReady() const noexcept
Returns whether or not this value is Ready.
Definition: poll.h:125
constexpr MemberPendableWrapper< MemberFunc > PendableFor(typename Traits::Class &obj, Args &&... args)
Definition: pendable.h:188
Definition: pendable.h:31