libkazv
Loading...
Searching...
No Matches
promise-interface.hpp
Go to the documentation of this file.
1/*
2 * This file is part of libkazv.
3 * SPDX-FileCopyrightText: 2021 Tusooa Zhu <tusooa@kazv.moe>
4 * SPDX-License-Identifier: AGPL-3.0-or-later
5 */
6
7#pragma once
8
9#include <memory>
10#include <type_traits>
11#include <functional>
12
13namespace Kazv
14{
16 {
17 };
18
19 template<template<class> class DeriveT, class T>
20 class AbstractPromise;
21
22 namespace detail
23 {
24 template<class T, class = void>
25 struct PromiseParameterT
26 {
27 using type = T;
28 };
29
30 template<class PromiseT>
31 struct PromiseParameterT<PromiseT,
32 std::void_t<std::enable_if_t<std::is_base_of_v<TypelessPromise, PromiseT>, int>>>
33 {
34 using type = typename PromiseT::DataT;
35 };
36
37 template<class T>
38 using PromiseParameter = typename PromiseParameterT<T>::type;
39
40 template<class T, class = void>
41 struct PromiseResult
42 {
43 };
44
45 template<class T>
46 struct PromiseResult<T, std::void_t<std::invoke_result_t<T>>>
47 {
48 using Res = std::invoke_result_t<T>;
49
50 using type = PromiseParameter<Res>;
51 };
52
53 template<class T>
54 using PromiseResultT = typename PromiseResult<T>::type;
55
56
57 template<class T, class P>
58 struct PromiseThenResultT
59 {
60 using Res = std::invoke_result_t<T, PromiseParameter<P>>;
61
62 using type = PromiseParameter<Res>;
63 };
64 }
65
66 template<class T, class P>
67 using PromiseThenResult = typename detail::PromiseThenResultT<T, P>::type;
68
69 template<class T>
70 constexpr auto isPromise = std::is_base_of_v<TypelessPromise, T>;
71
72 template<template<class> class DeriveT, class T>
74 {
75 public:
76 using DataT = T;
77
78 static_assert(!isPromise<DataT>, "Cannot create a promise of promise");
79
80 AbstractPromise(DeriveT<T> *obj) : m_derived(obj) {}
81
82 template<class FuncT>
83 auto then(FuncT &&func)
84 -> DeriveT<PromiseThenResult<FuncT, DataT>> {
85 return m_derived->then(std::forward<FuncT>(func));
86 }
87
88 private:
89 DeriveT<T> *m_derived;
90 };
91
92 namespace PromiseCombination
93 {
94 constexpr bool createDefaultForPromiseThen(bool) { return true; }
95 constexpr bool dataCombine(bool a, bool b) { return a && b; }
96 constexpr bool dataCombineNone(bool) { return true; }
97
98 template<class T, class = void>
99 struct DefaultForPromiseT
100 {
101 constexpr T operator()() const { return T(); }
102 };
103
104 template<class T>
105 struct DefaultForPromiseT<
106 T,
107 std::void_t<decltype(createDefaultForPromiseThen(std::declval<T>()))>>
108 {
109 constexpr T operator()() const { return createDefaultForPromiseThen(T()); }
110 };
111
112 template<class T>
113 constexpr T defaultForPromiseThen(T)
114 {
115 return DefaultForPromiseT<T>{}();
116 }
117 }
118
119
120 template<class T>
122 {
123 public:
124 using DataT = T;
125
126 template<class DeriveT>
127 SingleTypePromise(DeriveT obj)
128 : m_d(std::unique_ptr<Concept>(new Model<DeriveT>(std::move(obj)))) {}
129
131 : m_d(that.m_d->clone())
132 {}
133
135 : m_d(std::move(that.m_d))
136 {}
137
139 m_d = that.m_d->clone();
140 return *this;
141 }
142
144 m_d = std::move(that.m_d);
145 return *this;
146 }
147
148 template<class F>
150 if constexpr (std::is_same_v<std::invoke_result_t<F, DataT>, void>) {
151 return m_d->thenVoid(f);
152 } else if constexpr(isPromise<std::invoke_result_t<F, DataT>>) {
153 return m_d->thenPromise(f);
154 } else {
155 return m_d->thenData(f);
156 }
157 }
158
159 bool ready() const { return m_d->ready(); }
160 DataT get() const { return m_d->get(); }
161
162 private:
163 struct Concept
164 {
165 virtual ~Concept() = default;
166 virtual SingleTypePromise thenVoid(std::function<void(DataT)> f) = 0;
167 virtual SingleTypePromise thenData(std::function<DataT(DataT)> f) = 0;
168 virtual SingleTypePromise thenPromise(std::function<SingleTypePromise(DataT)> f) = 0;
169 virtual std::unique_ptr<Concept> clone() const = 0;
170 virtual bool ready() const = 0;
171 virtual DataT get() const = 0;
172 };
173
174 template<class DeriveT>
175 struct Model : public Concept
176 {
177 Model(DeriveT obj) : instance(std::move(obj)) {}
178 ~Model() override = default;
179 SingleTypePromise thenVoid(std::function<void(DataT)> f) override {
180 return instance.then([=](DataT v) {
181 f(v);
182 return PromiseCombination::defaultForPromiseThen(DataT());
183 });
184 }
185 SingleTypePromise thenData(std::function<DataT(DataT)> f) override {
186 return instance.then([=](DataT v) { return f(v); });
187 }
188 SingleTypePromise thenPromise(std::function<SingleTypePromise(DataT)> f) override {
189 return instance.then([=](DataT v) { return f(v); });
190 }
191 std::unique_ptr<Concept> clone() const override {
192 return std::unique_ptr<Concept>(new Model<DeriveT>(instance));
193 }
194 bool ready() const override {
195 return instance.ready();
196 }
197 DataT get() const override {
198 return instance.get();
199 }
200 DeriveT instance;
201 };
202
203 std::unique_ptr<Concept> m_d;
204 };
205
207
208 template<class DeriveT, template<class> class PromiseT>
210 {
211 public:
212 PromiseInterface(DeriveT *obj) : m_derived(obj) {}
213
214 template<class T, class FuncT>
215 auto create(FuncT &&func) -> PromiseT<T>;
216
217 template<class T>
218 auto createResolved(T &&val) -> PromiseT<T>;
219
220 private:
221 DeriveT *m_derived;
222 };
223
224 template<class DeriveT, template<class> class PromiseT>
225 template<class T, class FuncT>
226 auto PromiseInterface<DeriveT, PromiseT>::create(FuncT &&func) -> PromiseT<T> {
227 return m_derived->create(std::forward<FuncT>(func));
228 }
229
230 template<class DeriveT, template<class> class PromiseT>
231 template<class T>
233 return m_derived->createResolved(std::forward<T>(val));
234 }
235
236 template<class T>
238 {
239 public:
240 using DataT = T;
242 using ResolveT = std::function<void(DataT)>;
243 using ResolveToPromiseT = std::function<void(PromiseT)>;
244
245 template<class DeriveT>
247 : m_d(std::unique_ptr<Concept>(new Model<std::decay_t<DeriveT>>(std::move(obj)))) {
248 if (! m_d) {
249 throw std::logic_error("promise handler is empty");
250 }
251 }
252
254 : m_d(that.m_d) {
255 if (! m_d) {
256 throw std::logic_error("promise handler is empty");
257 }
258 }
260 : m_d(std::move(that.m_d)) {
261 if (! m_d) {
262 throw std::logic_error("promise handler is empty");
263 }
264 }
265
267 m_d = that.m_d;
268 return *this;
269 }
270
272 m_d = std::move(that.m_d);
273 return *this;
274 }
275
276 PromiseT create(std::function<void(ResolveT)> f) const {
277 return m_d->create(f);
278 }
279
280 PromiseT createResolveToPromise(std::function<void(ResolveToPromiseT)> f) const {
281 return m_d->createResolveToPromise(f);
282 }
283
285 return m_d->createResolved(v);
286 }
287
288 template<class RangeT>
289 PromiseT all(RangeT promises) const {
290 using PromiseCombination::dataCombine;
291 using PromiseCombination::dataCombineNone;
292 if (promises.empty()) {
294 }
295 auto p1 = *(promises.begin());
296 promises.erase(promises.begin());
297 if (promises.empty()) {
298 return p1;
299 }
300 return p1.then([*this, promises=std::move(promises)](DataT val) mutable {
301 return all(std::move(promises))
302 .then([=](DataT val2) {
303 return dataCombine(val, val2);
304 });
305 });
306 }
307
308 private:
309 struct Concept
310 {
311 virtual ~Concept() = default;
312 virtual PromiseT create(std::function<void(ResolveT)> f) = 0;
313 virtual PromiseT createResolveToPromise(std::function<void(ResolveToPromiseT)> f) = 0;
314 virtual PromiseT createResolved(DataT v) = 0;
315 };
316
317 template<class DeriveT>
318 struct Model : public Concept
319 {
320 static_assert(std::is_same_v<std::decay_t<DeriveT>, DeriveT>, "DeriveT must not be a reference");
321 Model(DeriveT obj) : instance(std::move(obj)) {}
322 ~Model() override = default;
323 PromiseT create(std::function<void(ResolveT)> f) override {
324 return instance.template create<DataT>(f);
325 }
326 PromiseT createResolveToPromise(std::function<void(ResolveToPromiseT)> f) override {
327 return instance.template create<DataT>(f);
328 }
329 PromiseT createResolved(DataT v) override {
330 return instance.createResolved(v);
331 }
332 DeriveT instance;
333 };
334
335 std::shared_ptr<Concept> m_d;
336 };
337
339}
Definition promise-interface.hpp:74
AbstractPromise(DeriveT< T > *obj)
Definition promise-interface.hpp:80
T DataT
Definition promise-interface.hpp:76
auto then(FuncT &&func) -> DeriveT< PromiseThenResult< FuncT, DataT > >
Definition promise-interface.hpp:83
Definition promise-interface.hpp:210
PromiseInterface(DeriveT *obj)
Definition promise-interface.hpp:212
auto create(FuncT &&func) -> PromiseT< T >
Definition promise-interface.hpp:226
auto createResolved(T &&val) -> PromiseT< T >
Definition promise-interface.hpp:232
Definition promise-interface.hpp:238
PromiseT all(RangeT promises) const
Definition promise-interface.hpp:289
SingleTypePromiseInterface(DeriveT obj)
Definition promise-interface.hpp:246
SingleTypePromiseInterface(SingleTypePromiseInterface &&that)
Definition promise-interface.hpp:259
SingleTypePromiseInterface & operator=(const SingleTypePromiseInterface &that)
Definition promise-interface.hpp:266
PromiseT createResolveToPromise(std::function< void(ResolveToPromiseT)> f) const
Definition promise-interface.hpp:280
PromiseT create(std::function< void(ResolveT)> f) const
Definition promise-interface.hpp:276
PromiseT createResolved(DataT v) const
Definition promise-interface.hpp:284
SingleTypePromise< DataT > PromiseT
Definition promise-interface.hpp:241
std::function< void(DataT)> ResolveT
Definition promise-interface.hpp:242
std::function< void(PromiseT)> ResolveToPromiseT
Definition promise-interface.hpp:243
SingleTypePromiseInterface & operator=(SingleTypePromiseInterface &&that)
Definition promise-interface.hpp:271
SingleTypePromiseInterface(const SingleTypePromiseInterface &that)
Definition promise-interface.hpp:253
T DataT
Definition promise-interface.hpp:240
Definition promise-interface.hpp:122
SingleTypePromise & operator=(const SingleTypePromise &that)
Definition promise-interface.hpp:138
DataT get() const
Definition promise-interface.hpp:160
T DataT
Definition promise-interface.hpp:124
bool ready() const
Definition promise-interface.hpp:159
SingleTypePromise & operator=(SingleTypePromise &&that)
Definition promise-interface.hpp:143
SingleTypePromise(const SingleTypePromise &that)
Definition promise-interface.hpp:130
SingleTypePromise then(F &&f)
Definition promise-interface.hpp:149
SingleTypePromise(DeriveT obj)
Definition promise-interface.hpp:127
SingleTypePromise(SingleTypePromise &&that)
Definition promise-interface.hpp:134
Definition promise-interface.hpp:16
A RangeT is an ordered collection that can be iterated through.
Definition range-t.hpp:21
auto begin() const
The beginning iterator of this range.
Definition location.hpp:10
EffectStatus dataCombineNone(EffectStatus)
Definition context.hpp:121
typename detail::PromiseThenResultT< T, P >::type PromiseThenResult
Definition promise-interface.hpp:67
constexpr auto isPromise
Definition promise-interface.hpp:70
EffectStatus dataCombine(EffectStatus a, EffectStatus b)
Definition context.hpp:105
Definition clientutil.hpp:140