libkazv
Loading...
Searching...
No Matches
asio-promise-handler.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 <boost/asio.hpp>
10
11#include <promise-interface.hpp>
12
13namespace Kazv
14{
15 template<class Exec, class T>
16 class AsioPromise;
17
18 namespace detail
19 {
20 template<class Exec>
21 struct AsioPromiseHelper
22 {
23 template<class T>
24 using PromiseType = AsioPromise<Exec, T>;
25 };
26
27 struct IdentityFunc
28 {
29 template<class T>
30 constexpr T &&operator()(T &&t) const {
31 return std::forward<T>(t);
32 }
33 };
34 }
35
36 template<class Exec, class T>
37 class AsioPromise : public AbstractPromise<detail::AsioPromiseHelper<Exec>::template PromiseType, T>
38 {
40
41 template<class FuncT, class PromiseT, class ResolveT>
42 struct WaitHelper
43 {
44 void wait() const {
45 if (p.ready()) {
46 auto res = func(p.get());
47 using ResT = decltype(res);
48 if constexpr (isPromise<ResT>) {
49 boost::asio::post(
50 executor,
51 [w=WaitHelper<detail::IdentityFunc, ResT, ResolveT>{
52 executor,
53 res,
54 detail::IdentityFunc{},
55 resolve,
56 }]() mutable {
57 w.wait();
58 });
59 } else {
60 resolve(res);
61 }
62 } else {
63 boost::asio::post(
64 executor,
65 [*this]() mutable {
66 wait();
67 }
68 );
69 }
70 }
71
72 Exec executor;
73 PromiseT p;
74 FuncT func;
75 ResolveT resolve;
76 };
77
78 struct ResolveHelper
79 {
80 template<class ValT>
81 void operator()(ValT val) const {
82 using ResT = std::decay_t<decltype(val)>;
83 if constexpr (isPromise<ResT>) {
84 auto w = WaitHelper<detail::IdentityFunc, ResT, ResolveHelper>{
85 executor,
86 val,
87 detail::IdentityFunc{},
88 *this
89 };
90 w.wait();
91 } else {
92 p->set_value(std::move(val));
93 }
94 }
95
96 Exec executor;
97 std::shared_ptr<std::promise<T>> p;
98 };
99 public:
100 AsioPromise(Exec executor, T value)
101 : BaseT(this)
102 , m_executor(std::move(executor)) {
103 std::promise<T> p;
104 m_val = p.get_future().share();
105 p.set_value(std::move(value));
106 }
107
108 template<class Func>
109 AsioPromise(Exec executor, Func &&callback)
110 : BaseT(this)
111 , m_executor(std::move(executor)) {
112 auto p = std::make_shared<std::promise<T>>();
113 m_val = p->get_future().share();
114 auto resolve = ResolveHelper{m_executor, p};
115
116 boost::asio::post(
117 m_executor,
118 [=, callback=std::forward<Func>(callback),
119 resolve=std::move(resolve),
120 guard=boost::asio::make_work_guard(m_executor)]() {
121 callback(resolve);
122 });
123 }
124
125 // FuncT: (DataT) -> AnotherDataT
126 // where AnotherDataT = PromiseThenResult<FuncT, typename BaseT::DataT>
127 template<class FuncT>
128 auto then(FuncT &&func)
129 -> AsioPromise<Exec,
131 return AsioPromise<Exec,
133 m_executor,
134 [=, func=std::forward<FuncT>(func), *this](auto resolve) {
135 auto waitHelper = WaitHelper<std::decay_t<FuncT>,
137 std::decay_t<decltype(resolve)>>{
138 m_executor,
139 *this,
140 func,
141 resolve
142 };
143 waitHelper.wait();
144 });
145 }
146
147 bool ready() const {
148 return m_val.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
149 }
150
151 T get() const {
152 return m_val.get();
153 }
154 private:
155 Exec m_executor;
156 std::shared_future<T> m_val;
157 };
158
159 template<class Exec>
160 class AsioPromiseHandler : public PromiseInterface<AsioPromiseHandler<Exec>,
161 detail::AsioPromiseHelper<Exec>::template PromiseType>
162 {
164 detail::AsioPromiseHelper<Exec>::template PromiseType>;
165 public:
166 template<class T>
168
169 AsioPromiseHandler(Exec executor)
170 : BaseT(this)
171 , m_executor(executor)
172 {}
173
175 : BaseT(this)
176 , m_executor(that.m_executor)
177 {}
178
180 : BaseT(this)
181 , m_executor(std::move(that.m_executor))
182 {}
183
185 m_executor = that.m_executor;
186 return *this;
187 }
188
190 m_executor = std::move(that.m_executor);
191 return *this;
192 }
193
194 template<class T, class FuncT>
195 PromiseT<T> create(FuncT &&func) {
196 return PromiseT<T>(m_executor, std::forward<FuncT>(func));
197 }
198
199 template<class T>
201 return PromiseT<T>(m_executor, std::move(val));
202 }
203
204 private:
205 Exec m_executor;
206 };
207
208 template<class Exec>
210}
Definition promise-interface.hpp:74
Definition asio-promise-handler.hpp:162
AsioPromiseHandler(Exec executor)
Definition asio-promise-handler.hpp:169
PromiseT< T > createResolved(T val)
Definition asio-promise-handler.hpp:200
AsioPromiseHandler & operator=(AsioPromiseHandler &&that)
Definition asio-promise-handler.hpp:189
AsioPromiseHandler(const AsioPromiseHandler &that)
Definition asio-promise-handler.hpp:174
PromiseT< T > create(FuncT &&func)
Definition asio-promise-handler.hpp:195
AsioPromiseHandler(AsioPromiseHandler &&that)
Definition asio-promise-handler.hpp:179
AsioPromiseHandler & operator=(const AsioPromiseHandler &that)
Definition asio-promise-handler.hpp:184
Definition asio-promise-handler.hpp:38
auto then(FuncT &&func) -> AsioPromise< Exec, PromiseThenResult< FuncT, typename BaseT::DataT > >
Definition asio-promise-handler.hpp:128
bool ready() const
Definition asio-promise-handler.hpp:147
T get() const
Definition asio-promise-handler.hpp:151
AsioPromise(Exec executor, Func &&callback)
Definition asio-promise-handler.hpp:109
AsioPromise(Exec executor, T value)
Definition asio-promise-handler.hpp:100
Definition promise-interface.hpp:210
Definition location.hpp:10
typename detail::PromiseThenResultT< T, P >::type PromiseThenResult
Definition promise-interface.hpp:67
Definition clientutil.hpp:140