libkazv
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 
13 namespace Kazv
14 {
16  {
17  };
18 
19  template<template<class> class DeriveT, class T>
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>
100  {
101  constexpr T operator()() const { return T(); }
102  };
103 
104  template<class T>
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);
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 {
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 }
Kazv::SingleTypePromiseInterface::createResolved
PromiseT createResolved(DataT v) const
Definition: promise-interface.hpp:284
Kazv::dataCombine
EffectStatus dataCombine(EffectStatus a, EffectStatus b)
Definition: context.hpp:105
Kazv::SingleTypePromise::SingleTypePromise
SingleTypePromise(const SingleTypePromise &that)
Definition: promise-interface.hpp:130
Kazv::SingleTypePromiseInterface::create
PromiseT create(std::function< void(ResolveT)> f) const
Definition: promise-interface.hpp:276
Kazv::PromiseInterface::createResolved
auto createResolved(T &&val) -> PromiseT< T >
Definition: promise-interface.hpp:232
Kazv::SingleTypePromiseInterface::operator=
SingleTypePromiseInterface & operator=(SingleTypePromiseInterface &&that)
Definition: promise-interface.hpp:271
Kazv::AbstractPromise
Definition: promise-interface.hpp:20
Kazv::AbstractPromise::AbstractPromise
AbstractPromise(DeriveT< T > *obj)
Definition: promise-interface.hpp:80
Kazv::AbstractPromise::DataT
T DataT
Definition: promise-interface.hpp:76
Kazv::SingleTypePromise::get
DataT get() const
Definition: promise-interface.hpp:160
Kazv::SingleTypePromiseInterface::SingleTypePromiseInterface
SingleTypePromiseInterface(const SingleTypePromiseInterface &that)
Definition: promise-interface.hpp:253
Kazv::SingleTypePromise::operator=
SingleTypePromise & operator=(SingleTypePromise &&that)
Definition: promise-interface.hpp:143
Kazv::SingleTypePromise::SingleTypePromise
SingleTypePromise(SingleTypePromise &&that)
Definition: promise-interface.hpp:134
Kazv::detail::PromiseResultT
typename PromiseResult< T >::type PromiseResultT
Definition: promise-interface.hpp:54
Kazv::SingleTypePromiseInterface< RetType >::ResolveT
std::function< void(DataT)> ResolveT
Definition: promise-interface.hpp:242
Kazv::PromiseCombination::createDefaultForPromiseThen
constexpr bool createDefaultForPromiseThen(bool)
Definition: promise-interface.hpp:94
Kazv::PromiseCombination::defaultForPromiseThen
constexpr T defaultForPromiseThen(T)
Definition: promise-interface.hpp:113
Kazv::PromiseCombination::dataCombine
constexpr bool dataCombine(bool a, bool b)
Definition: promise-interface.hpp:95
Kazv::SingleTypePromise::operator=
SingleTypePromise & operator=(const SingleTypePromise &that)
Definition: promise-interface.hpp:138
Kazv::PromiseCombination::DefaultForPromiseT
Definition: promise-interface.hpp:99
Kazv::SingleTypePromise::ready
bool ready() const
Definition: promise-interface.hpp:159
Kazv
Definition: location.hpp:10
Kazv::PromiseInterface
Definition: promise-interface.hpp:209
Kazv::detail::PromiseParameter
typename PromiseParameterT< T >::type PromiseParameter
Definition: promise-interface.hpp:38
Kazv::SingleTypePromiseInterface< RetType >::ResolveToPromiseT
std::function< void(PromiseT)> ResolveToPromiseT
Definition: promise-interface.hpp:243
Kazv::dataCombineNone
EffectStatus dataCombineNone(EffectStatus)
Definition: context.hpp:121
Kazv::isPromise
constexpr auto isPromise
Definition: promise-interface.hpp:70
Kazv::AbstractPromise::then
auto then(FuncT &&func) -> DeriveT< PromiseThenResult< FuncT, DataT >>
Definition: promise-interface.hpp:83
Kazv::PromiseCombination::DefaultForPromiseT< T, std::void_t< decltype(createDefaultForPromiseThen(std::declval< T >()))> >::operator()
constexpr T operator()() const
Definition: promise-interface.hpp:109
Kazv::SingleTypePromiseInterface::SingleTypePromiseInterface
SingleTypePromiseInterface(DeriveT obj)
Definition: promise-interface.hpp:246
Kazv::SingleTypePromise::SingleTypePromise
SingleTypePromise(DeriveT obj)
Definition: promise-interface.hpp:127
Kazv::SingleTypePromiseInterface::PromiseT
SingleTypePromise< DataT > PromiseT
Definition: promise-interface.hpp:241
RangeT
A RangeT is an ordered collection that can be iterated through.
Definition: range-t.hpp:20
RangeT::begin
auto begin() const
The beginning iterator of this range.
Kazv::SingleTypePromise::then
SingleTypePromise then(F &&f)
Definition: promise-interface.hpp:149
Kazv::TypelessPromise
Definition: promise-interface.hpp:15
Kazv::PromiseThenResult
typename detail::PromiseThenResultT< T, P >::type PromiseThenResult
Definition: promise-interface.hpp:67
Kazv::SingleTypePromiseInterface::all
PromiseT all(RangeT promises) const
Definition: promise-interface.hpp:289
Kazv::SingleTypePromiseInterface::createResolveToPromise
PromiseT createResolveToPromise(std::function< void(ResolveToPromiseT)> f) const
Definition: promise-interface.hpp:280
Kazv::SingleTypePromiseInterface< RetType >::DataT
RetType DataT
Definition: promise-interface.hpp:240
std
Definition: clientutil.hpp:216
Kazv::SingleTypePromise::DataT
T DataT
Definition: promise-interface.hpp:124
Kazv::SingleTypePromise
Definition: promise-interface.hpp:121
Kazv::PromiseCombination::dataCombineNone
constexpr bool dataCombineNone(bool)
Definition: promise-interface.hpp:96
Kazv::PromiseCombination::DefaultForPromiseT::operator()
constexpr T operator()() const
Definition: promise-interface.hpp:101
Kazv::SingleTypePromiseInterface::SingleTypePromiseInterface
SingleTypePromiseInterface(SingleTypePromiseInterface &&that)
Definition: promise-interface.hpp:259
Kazv::SingleTypePromiseInterface
Definition: promise-interface.hpp:237
Kazv::PromiseInterface::PromiseInterface
PromiseInterface(DeriveT *obj)
Definition: promise-interface.hpp:212
Kazv::SingleTypePromiseInterface::operator=
SingleTypePromiseInterface & operator=(const SingleTypePromiseInterface &that)
Definition: promise-interface.hpp:266
Kazv::PromiseInterface::create
auto create(FuncT &&func) -> PromiseT< T >
Definition: promise-interface.hpp:226