libzypp 17.37.10

asyncresult.h
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8----------------------------------------------------------------------/
9*
10* This file contains private API, this might break at any time between releases.
11* You have been warned!
12*
13*/
14#ifndef ZYPPNG_MONADIC_ASYNCRESULT_H_INCLUDED
15#define ZYPPNG_MONADIC_ASYNCRESULT_H_INCLUDED
16
17#include <zypp-core/zyppng/meta/TypeTraits>
18#include <zypp-core/zyppng/meta/FunctionTraits>
19#include <zypp-core/zyppng/meta/Functional>
20#include <zypp-core/zyppng/async/AsyncOp>
21
22 namespace zyppng {
23
24
25 namespace detail {
26
27 template< typename Callback, typename MsgType, typename = std::void_t<> >
28 struct is_future_monad_cb : public std::false_type{};
29
30 template< typename Callback, typename MsgType >
31 struct is_future_monad_cb<Callback, MsgType,
32 std::void_t<
33 std::enable_if_t< is_async_op_v<Callback> >,
34 decltype ( std::declval<remove_smart_ptr_t<Callback>>()( std::declval<MsgType>()) )//check if the callback has a operator() member with the correct signature
35 >
36 > : public std::true_type{};
37
42 template< typename Callback, typename MsgType >
43 constexpr bool is_future_monad_cb_v = is_future_monad_cb<Callback, MsgType>::value;
44
45 template< typename Callback, typename MsgType, typename = std::void_t<> >
46 struct is_sync_monad_cb : public std::false_type{};
47
48 template< typename Callback, typename MsgType >
49 struct is_sync_monad_cb<Callback, MsgType
50 , std::void_t<
51 std::enable_if_t< !is_async_op_v<Callback> >,
52 std::enable_if_t< !std::is_same_v< void, decltype ( std::declval<Callback>()(std::declval<MsgType>())) > > > //check if the callback has the correct signature: cb( MsgType )
53 > : public std::true_type{};
54
58 template< typename Callback, typename MsgType, typename = std::void_t<> >
59 constexpr bool is_sync_monad_cb_v = is_sync_monad_cb<Callback, MsgType>::value;
60
61
62 template <typename Callback, typename Arg>
63 using callback_returns_async_op = is_async_op< std::invoke_result_t<Callback, Arg >>;
64
65
66 template< typename Callback, typename MsgType, typename = std::void_t<> >
67 struct is_sync_monad_cb_with_async_res : public std::false_type{};
68
69 template< typename Callback, typename MsgType >
70 struct is_sync_monad_cb_with_async_res<Callback, MsgType
71 , std::void_t<
72 std::enable_if_t< is_sync_monad_cb<Callback, MsgType>::value >,
73 std::enable_if_t< callback_returns_async_op<Callback, MsgType>::value >>
74 > : public std::true_type{};
75
76 template< typename Callback, typename MsgType, typename = std::void_t<> >
77 struct is_sync_monad_cb_with_sync_res : public std::false_type{};
78
79 template< typename Callback, typename MsgType >
80 struct is_sync_monad_cb_with_sync_res<Callback, MsgType
81 , std::void_t<
82 std::enable_if_t< is_sync_monad_cb<Callback, MsgType>::value >,
83 std::enable_if_t< !callback_returns_async_op<Callback, MsgType>::value > >
84 > : public std::true_type{};
85
89 template <typename Callback, typename Arg>
90 constexpr bool is_sync_monad_cb_with_async_res_v = is_sync_monad_cb_with_async_res<Callback, Arg>::value;
91
95 template <typename Callback, typename Arg>
96 constexpr bool is_sync_monad_cb_with_sync_res_v = is_sync_monad_cb_with_sync_res<Callback, Arg>::value;
97
98
116 //template <typename Prev, typename AOp, typename Enable = void>
117 //struct AsyncResult;
118
119 template <typename T>
120 struct is_nested_async : public std::false_type {};
121
122 template <typename T>
123 struct is_nested_async<AsyncOpRef<AsyncOpRef<T>>> : public std::true_type {};
124
125 template <typename T>
126 constexpr bool is_nested_async_v = is_nested_async<T>::value;
127
128
129 // case 1: connect async result to async callback
130 template <typename PrevRes, typename CallbackOp, typename AOpRes = typename CallbackOp::value_type >
131 struct AsyncToAsyncResult : public zyppng::AsyncOp< AOpRes > {
132
133 static_assert( !is_async_op_v<AOpRes>, "A AsyncResult can never return a async value" );
134 static_assert( !is_async_op_v<PrevRes>, "A incoming value can never be a async value" );
135
136 AsyncToAsyncResult ( AsyncOpRef<PrevRes> && prevTask, std::shared_ptr<CallbackOp> &&cb )
137 : _prevTask( std::move(prevTask) )
138 , _myTask( std::move(cb) ) {
139 connect();
140 }
141
142 AsyncToAsyncResult ( const AsyncToAsyncResult &other ) = delete;
143 AsyncToAsyncResult& operator= ( const AsyncToAsyncResult &other ) = delete;
144
145 AsyncToAsyncResult ( AsyncToAsyncResult &&other ) = delete;
146 AsyncToAsyncResult& operator= ( AsyncToAsyncResult &&other ) = delete;
147
148 virtual ~AsyncToAsyncResult() {}
149
150 void connect () {
151 //not using a lambda here on purpose, binding this into a lambda that is stored in the _prev
152 //object causes segfaults on gcc when the lambda is cleaned up with the _prev objects signal instance
153 _prevTask->onReady( std::bind( &AsyncToAsyncResult::readyWasCalled, this, std::placeholders::_1) );
154 _myTask->onReady( [this] ( AOpRes && res ){
155 this->setReady( std::move( res ) );
156 });
157 }
158
159 private:
160 // we need to store the passed argument in our stack, otherwise we
161 // run into memory issues if the argument is moved out of the _prevTask object
162 // so even though we std::move() the argument further we need to copy it here
163 void readyWasCalled ( PrevRes res ) {
164 //MIL << "Setting ready: " << typeid(this) << std::endl;
165 if ( _prevTask ) {
166 //dumpInfo();
167 _prevTask.reset();
168 }
169
170 _myTask->operator()(std::move(res));
171 }
172
173 AsyncOpRef<PrevRes> _prevTask;
174 std::shared_ptr<CallbackOp> _myTask;
175 };
176
177 template <typename PrevRes, typename Callback, typename Enable = void>
178 struct AsyncToSyncResult;
179
180 // case 2: connect async result to sync callback returning a sync value
181 template <typename PrevRes, typename Callback>
182 struct AsyncToSyncResult<PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_sync_res_v<Callback, PrevRes> >>
183 : public zyppng::AsyncOp< typename std::invoke_result_t<Callback, PrevRes> > {
184
185 using value_type = std::invoke_result_t<Callback, PrevRes>;
186 static_assert( !is_async_op_v<value_type>, "A AsyncResult can never return a async value" );
187 static_assert( !is_async_op_v<PrevRes>, "A incoming value can never be a async value" );
188
189 template <typename CBType = Callback>
190 AsyncToSyncResult ( AsyncOpRef<PrevRes> && prevTask, CBType &&cb )
191 : _prevTask( std::move(prevTask) )
192 , _myTask( std::forward<CBType>(cb) ) {
193 connect();
194 }
195
196 AsyncToSyncResult ( const AsyncToSyncResult &other ) = delete;
197 AsyncToSyncResult& operator= ( const AsyncToSyncResult &other ) = delete;
198
199 AsyncToSyncResult ( AsyncToSyncResult &&other ) = delete;
200 AsyncToSyncResult& operator= ( AsyncToSyncResult &&other ) = delete;
201
202 virtual ~AsyncToSyncResult() {}
203
204 void connect () {
205 //not using a lambda here on purpose, binding this into a lambda that is stored in the _prev
206 //object causes segfaults on gcc when the lambda is cleaned up with the _prev objects signal instance
207 _prevTask->onReady( std::bind( &AsyncToSyncResult::readyWasCalled, this, std::placeholders::_1) );
208 }
209
210 private:
211 // we need to store the passed argument in our stack, otherwise we
212 // run into memory issues if the argument is moved out of the _prevTask object
213 // so even though we std::move() the argument further we need to copy it here
214 void readyWasCalled ( PrevRes res ) {
215 //MIL << "Setting ready: " << typeid(this) << std::endl;
216 if ( _prevTask ) {
217 _prevTask.reset();
218 }
219
220 this->setReady( std::invoke( _myTask, std::move( res )) );
221 }
222 AsyncOpRef<PrevRes> _prevTask;
223 Callback _myTask;
224 };
225
226
227 // case 3: connect async result to sync callback returning a async value
228 template <typename PrevRes, typename Callback>
229 struct AsyncToSyncResult<PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_async_res_v<Callback, PrevRes> >>
230 : public zyppng::AsyncOp< typename remove_smart_ptr_t<std::invoke_result_t<Callback, PrevRes>>::value_type> {
231
232 using value_type = typename remove_smart_ptr_t<std::invoke_result_t<Callback, PrevRes>>::value_type;
233 static_assert(!is_async_op_v< value_type >, "A AsyncResult can never return a async value" );
234
235 template <typename CBType = Callback>
236 AsyncToSyncResult ( AsyncOpRef<PrevRes> && prevTask, CBType &&cb )
237 : _prevTask( std::move(prevTask) )
238 , _myTask( std::forward<CBType>(cb) ) {
239 connect();
240 }
241
242 AsyncToSyncResult ( const AsyncToSyncResult &other ) = delete;
243 AsyncToSyncResult& operator= ( const AsyncToSyncResult &other ) = delete;
244
245 AsyncToSyncResult ( AsyncToSyncResult &&other ) = delete;
246 AsyncToSyncResult& operator= ( AsyncToSyncResult &&other ) = delete;
247
248 virtual ~AsyncToSyncResult() {}
249
250 void connect () {
251 //not using a lambda here on purpose, binding this into a lambda that is stored in the _prev
252 //object causes segfaults on gcc when the lambda is cleaned up with the _prev objects signal instance
253 _prevTask->onReady( std::bind( &AsyncToSyncResult::readyWasCalled, this, std::placeholders::_1) );
254 }
255
256 private:
257 // we need to store the passed argument in our stack, otherwise we
258 // run into memory issues if the argument is moved out of the _prevTask object
259 // so even though we std::move() the argument further we need to copy it here
260 void readyWasCalled ( PrevRes res ) {
261
262 //MIL << "Setting ready "<<this<<" step 1: " << typeid(this) << std::endl;
263 if ( _prevTask ) {
264 _prevTask.reset();
265 }
266
267 _asyncResult = std::invoke( _myTask, std::move(res) );
268 _asyncResult->onReady( [this]( value_type &&val ) {
269 //MIL << "Setting ready "<<this<<" step 2: " << typeid(this) << std::endl;
270 this->setReady( std::move(val) );
271 });
272 }
273 AsyncOpRef<PrevRes> _prevTask;
274 Callback _myTask;
275 AsyncOpRef<value_type> _asyncResult;
276 };
277 }
278
279 namespace operators {
280
281 template< typename PrevOp , typename Callback,
282 std::enable_if_t< detail::is_async_op_v<PrevOp>, int > = 0,
283 std::enable_if_t< detail::is_future_monad_cb_v<Callback, typename PrevOp::value_type>, int > = 0 >
284 auto operator| ( std::shared_ptr<PrevOp> &&in, std::shared_ptr<Callback>&& c ) -> AsyncOpRef<typename Callback::value_type>
285 {
286 using PrevOpRes = typename PrevOp::value_type;
287 return std::make_shared<detail::AsyncToAsyncResult<PrevOpRes, Callback>>( std::move(in), std::move(c) );
288 }
289
290 template< typename PrevOp , typename Callback,
291 std::enable_if_t< detail::is_async_op_v<PrevOp>, int > = 0,
292 std::enable_if_t< detail::is_sync_monad_cb_with_async_res_v<Callback, typename PrevOp::value_type>, int > = 0
293 >
294 auto operator| ( std::shared_ptr<PrevOp> &&in, Callback &&c )
295 {
296 using PrevOpRes = typename PrevOp::value_type;
297 using CbType = std::remove_reference_t<Callback>;
298 using Ret = typename detail::AsyncToSyncResult<PrevOpRes, CbType>::value_type;
299 if ( in->isReady() )
300 return AsyncOpRef<Ret>( std::invoke( std::forward<Callback>(c), std::move(in->get()) ) );
301 return AsyncOpRef<Ret>( new detail::AsyncToSyncResult<PrevOpRes, CbType>( std::move(in), std::forward<Callback>(c) ) );
302 }
303
304 template< typename PrevOp , typename Callback,
305 std::enable_if_t< detail::is_async_op_v<PrevOp>, int > = 0,
306 std::enable_if_t< detail::is_sync_monad_cb_with_sync_res_v<Callback, typename PrevOp::value_type>, int > = 0
307 >
308 auto operator| ( std::shared_ptr<PrevOp> &&in, Callback &&c )
309 {
310 using PrevOpRes = typename PrevOp::value_type;
311 using CbType = std::remove_reference_t<Callback>;
312 using Ret = typename detail::AsyncToSyncResult<PrevOpRes, CbType>::value_type;
313
314 if ( in->isReady() )
315 return makeReadyResult( std::invoke( std::forward<Callback>(c), std::move(in->get()) ) );
316 return AsyncOpRef<Ret>( new detail::AsyncToSyncResult<PrevOpRes, CbType>( std::move(in), std::forward<Callback>(c) ) );
317 }
318
319 template< typename PrevRes , typename CallbackOp,
320 std::enable_if_t< !detail::is_async_op_v<PrevRes>, int > = 0 ,
321 std::enable_if_t< detail::is_future_monad_cb_v<CallbackOp, PrevRes>, int > = 0 >
322 auto operator| ( PrevRes &&in, CallbackOp &&c ) -> AsyncOpRef<typename remove_smart_ptr_t<CallbackOp>::value_type>
323 {
324 // sync message to async callback case
325 std::forward<CallbackOp>(c)->operator()( std::forward<PrevRes>(in) );
326 return c;
327 }
328
329 // sync to sync callback case, we do not need to differentiate between a callback with a async result or a normal one
330 // in both cases we simply can use the return type of the callback function
331 template< typename SyncRes
332 , typename Callback
333 , std::enable_if_t< !detail::is_async_op_v< SyncRes >, int > = 0
334 , std::enable_if_t< detail::is_sync_monad_cb_v< Callback, SyncRes >, int > = 0
335 >
336 auto operator| ( SyncRes &&in, Callback &&c )
337 {
338 return std::forward<Callback>(c)(std::forward<SyncRes>(in));
339 }
340 }
341}
342
343#endif
std
Definition Arch.h:364
std::enable_if_t
typename enable_if< B, T >::type enable_if_t
Definition TypeTraits.h:45
std::remove_reference_t
typename remove_reference< T >::type remove_reference_t
Definition TypeTraits.h:48
std::invoke
std::enable_if< std::is_member_pointer< typenamestd::decay< Functor >::type >::value, typenamestd::result_of< Functor &&(Args &&...)>::type >::type invoke(Functor &&f, Args &&... args)
Definition functional.h:32
zyppng::detail
Definition reporthelper.h:31
zyppng::detail::is_nested_async_v
constexpr bool is_nested_async_v
Definition asyncresult.h:126
zyppng::detail::is_sync_monad_cb_with_sync_res_v
constexpr bool is_sync_monad_cb_with_sync_res_v
Definition asyncresult.h:96
zyppng::detail::is_future_monad_cb_v
constexpr bool is_future_monad_cb_v
Definition asyncresult.h:43
zyppng::detail::is_async_op_v
constexpr bool is_async_op_v
Definition asyncop.h:61
zyppng::detail::is_async_op
std::conjunction< has_value_type< remove_smart_ptr_t< T > >, is_asyncop_type< remove_smart_ptr_t< T > > > is_async_op
Definition asyncop.h:55
zyppng::detail::is_sync_monad_cb_with_async_res_v
constexpr bool is_sync_monad_cb_with_async_res_v
Definition asyncresult.h:90
zyppng::detail::is_sync_monad_cb_v
constexpr bool is_sync_monad_cb_v
Definition asyncresult.h:59
zyppng::detail::callback_returns_async_op
is_async_op< std::invoke_result_t< Callback, Arg > > callback_returns_async_op
Definition asyncresult.h:63
zyppng::operators
Definition asyncresult.h:279
zyppng::operators::operator|
auto operator|(std::shared_ptr< PrevOp > &&in, std::shared_ptr< Callback > &&c) -> AsyncOpRef< typename Callback::value_type >
Definition asyncresult.h:284
zyppng
Definition MediaNetworkRequestExecutor.h:16
zyppng::makeReadyResult
std::conditional_t< isAsync, AsyncOpRef< T >, T > makeReadyResult(T &&result)
Definition asyncop.h:297
zyppng::AsyncOpRef
std::shared_ptr< AsyncOp< T > > AsyncOpRef
Definition asyncop.h:255
zyppng::remove_smart_ptr_t
typename remove_smart_ptr< T >::type remove_smart_ptr_t
Definition type_traits.h:133
zyppng::AsyncOp
Definition asyncop.h:161
zyppng::AsyncOp< typename CallbackOp::value_type >::setReady
void setReady(value_type &&val)
Definition asyncop.h:183
zyppng::detail::AsyncToAsyncResult::AsyncToAsyncResult
AsyncToAsyncResult(AsyncOpRef< PrevRes > &&prevTask, std::shared_ptr< CallbackOp > &&cb)
Definition asyncresult.h:136
zyppng::detail::AsyncToAsyncResult::~AsyncToAsyncResult
virtual ~AsyncToAsyncResult()
Definition asyncresult.h:148
zyppng::detail::AsyncToAsyncResult::AsyncToAsyncResult
AsyncToAsyncResult(AsyncToAsyncResult &&other)=delete
zyppng::detail::AsyncToAsyncResult::operator=
AsyncToAsyncResult & operator=(const AsyncToAsyncResult &other)=delete
zyppng::detail::AsyncToAsyncResult::AsyncToAsyncResult
AsyncToAsyncResult(const AsyncToAsyncResult &other)=delete
zyppng::detail::AsyncToAsyncResult::_myTask
std::shared_ptr< CallbackOp > _myTask
Definition asyncresult.h:174
zyppng::detail::AsyncToAsyncResult::readyWasCalled
void readyWasCalled(PrevRes res)
Definition asyncresult.h:163
zyppng::detail::AsyncToAsyncResult::_prevTask
AsyncOpRef< PrevRes > _prevTask
Definition asyncresult.h:173
zyppng::detail::AsyncToAsyncResult::connect
void connect()
Definition asyncresult.h:150
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_sync_res_v< Callback, PrevRes > > >::AsyncToSyncResult
AsyncToSyncResult(AsyncOpRef< PrevRes > &&prevTask, CBType &&cb)
Definition asyncresult.h:190
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_sync_res_v< Callback, PrevRes > > >::readyWasCalled
void readyWasCalled(PrevRes res)
Definition asyncresult.h:214
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_sync_res_v< Callback, PrevRes > > >::AsyncToSyncResult
AsyncToSyncResult(const AsyncToSyncResult &other)=delete
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_sync_res_v< Callback, PrevRes > > >::_prevTask
AsyncOpRef< PrevRes > _prevTask
Definition asyncresult.h:222
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_sync_res_v< Callback, PrevRes > > >::connect
void connect()
Definition asyncresult.h:204
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_sync_res_v< Callback, PrevRes > > >::_myTask
Callback _myTask
Definition asyncresult.h:223
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_sync_res_v< Callback, PrevRes > > >::AsyncToSyncResult
AsyncToSyncResult(AsyncToSyncResult &&other)=delete
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_sync_res_v< Callback, PrevRes > > >::~AsyncToSyncResult
virtual ~AsyncToSyncResult()
Definition asyncresult.h:202
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_sync_res_v< Callback, PrevRes > > >::value_type
std::invoke_result_t< Callback, PrevRes > value_type
Definition asyncresult.h:185
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_async_res_v< Callback, PrevRes > > >::_asyncResult
AsyncOpRef< value_type > _asyncResult
Definition asyncresult.h:275
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_async_res_v< Callback, PrevRes > > >::AsyncToSyncResult
AsyncToSyncResult(AsyncOpRef< PrevRes > &&prevTask, CBType &&cb)
Definition asyncresult.h:236
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_async_res_v< Callback, PrevRes > > >::connect
void connect()
Definition asyncresult.h:250
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_async_res_v< Callback, PrevRes > > >::_prevTask
AsyncOpRef< PrevRes > _prevTask
Definition asyncresult.h:273
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_async_res_v< Callback, PrevRes > > >::readyWasCalled
void readyWasCalled(PrevRes res)
Definition asyncresult.h:260
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_async_res_v< Callback, PrevRes > > >::value_type
typename remove_smart_ptr_t< std::invoke_result_t< Callback, PrevRes > >::value_type value_type
Definition asyncresult.h:232
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_async_res_v< Callback, PrevRes > > >::AsyncToSyncResult
AsyncToSyncResult(AsyncToSyncResult &&other)=delete
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_async_res_v< Callback, PrevRes > > >::~AsyncToSyncResult
virtual ~AsyncToSyncResult()
Definition asyncresult.h:248
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_async_res_v< Callback, PrevRes > > >::AsyncToSyncResult
AsyncToSyncResult(const AsyncToSyncResult &other)=delete
zyppng::detail::AsyncToSyncResult< PrevRes, Callback, std::enable_if_t< is_sync_monad_cb_with_async_res_v< Callback, PrevRes > > >::_myTask
Callback _myTask
Definition asyncresult.h:274
zyppng::detail::AsyncToSyncResult
Definition asyncresult.h:178
zyppng::detail::is_future_monad_cb
Definition asyncresult.h:28
zyppng::detail::is_nested_async
Definition asyncresult.h:120
zyppng::detail::is_sync_monad_cb_with_async_res
Definition asyncresult.h:67
zyppng::detail::is_sync_monad_cb_with_sync_res
Definition asyncresult.h:77
zyppng::detail::is_sync_monad_cb
Definition asyncresult.h:46