9 #ifndef SAW_ALL_AMFUTURE_H
10 #define SAW_ALL_AMFUTURE_H
14 #include <type_traits>
17 #if defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)
34 template<
class Callback,
class AvailCallback,
class Function,
class TCF,
class... Args>
35 AMFuture<std::invoke_result_t<std::decay_t<Callback>, TCF,
void *>>
36 AMAsync(AMLaunch policy, Callback &&callback, AvailCallback &&a, Function &&f, TCF &&tcf, Args &&... args);
38 template<
class Result>
39 class _AMLaunchFnHolderBase
42 _AMLaunchFnHolderBase(Result (*_sget)(
void*,
void*),
bool (*_savail)(
void*,
void*),
void* _holder)
48 Result SGet(
void* mem)
50 return sget(holder, mem);
52 bool SIsAvail(
void* mem)
54 return savail(holder, mem);
56 virtual ~_AMLaunchFnHolderBase()
61 Result (*sget)(
void* holder,
void* mem);
62 bool (*savail)(
void* holder,
void* mem);
66 template<
class AvailCallback,
class Callback,
class TObject>
67 class _AMLaunchFnHolder:
public _AMLaunchFnHolderBase<std::invoke_result_t<std::decay_t<Callback>, TObject, void*>> {
69 _AMLaunchFnHolder(TObject& _obj, AvailCallback&& _ac, Callback&& _c)
70 : _AMLaunchFnHolderBase<std::invoke_result_t<std::decay_t<Callback>, TObject, void*>>(_AMLaunchFnHolder::SGetS, _AMLaunchFnHolder::SIsAvailS,(void*)this), obj(_obj), ac(std::move(_ac)), c(std::move(_c))
77 static bool SIsAvailS(
void* _holder,
void* mem)
79 _AMLaunchFnHolder* holder = (_AMLaunchFnHolder*)_holder;
80 return std::invoke(holder->ac, holder->obj, mem);
82 static std::invoke_result_t<std::decay_t<Callback>, TObject,
void*> SGetS(
void* _holder,
void* mem)
84 _AMLaunchFnHolder* holder = (_AMLaunchFnHolder*)_holder;
85 return std::invoke(holder->c, holder->obj, mem);
92 template<
class T>
class AMFuture
103 bool valid() const noexcept;
111 template< class Rep, class Period >
112 AMFutureStatus wait_for( const std::chrono::duration<Rep,Period>& timeout_duration ) const;
115 template<class Callback, class AvailCallback, class Function, class TCF, class... Args>
117 AMFuture<std::invoke_result_t<std::decay_t<Callback>, TCF,
void *>>
118 AMAsync(AMLaunch policy, Callback &&callback, AvailCallback &&a, Function &&f, TCF &&tcf, Args &&... args);
121 template< class Callback, class AvailCallback, class Function, class TCF, class... Args > friend
122 AMFuture<std::invoke_result_t<std::decay_t<Callback>, TCF,
void*>>
123 AMAsync( AMLaunch policy, Callback&& callback, AvailCallback&& a, Function&& f, TCF&& tcf, Args&&... args );
128 _AMLaunchFnHolderBase<T>* holder;
129 AMFuture(
void*, _AMLaunchFnHolderBase<T>* holder) noexcept;
133 validFlag(false), mem(), holder(
nullptr)
139 validFlag = other.validFlag;
140 other.validFlag =
false;
143 holder = other.holder;
144 other.holder =
nullptr;
149 validFlag = other.validFlag;
150 other.validFlag =
false;
153 holder = other.holder;
154 other.holder =
nullptr;
159 validFlag(
false), mem(_mem), holder(_holder)
168 template<
class T>
bool AMFuture<T>::valid() const noexcept
170 if (validFlag || (holder && holder->SIsAvail(mem))) {
175 template<
class T> T AMFuture<T>::get()
179 T rv = holder->SGet(mem);
199 template<
class T>
void AMFuture<T>::destroy()
208 template<
class T>
void AMFuture<T>::wait()
const
212 assert(holder->SIsAvail(mem));
218 template<
class Rep,
class Period >
219 AMFutureStatus AMFuture<T>::wait_for(
const std::chrono::duration<Rep,Period>& timeout_duration )
const
221 if (validFlag || (holder && holder->SIsAvail(mem))) {
222 return AMFutureStatus::ready;
224 return AMFutureStatus::timeout;
227 template<
class Function,
class... Args >
228 AMFuture<std::invoke_result_t<std::decay_t<Function>, std::decay_t<Args>...>>
229 AMAsync( Function&& f, Args&&... args )
231 return AMAsync(AMLaunch::async, f, args...);
234 template<
class Callback,
class AvailCallback,
class Function,
class TCF,
class... Args >
235 AMFuture<std::invoke_result_t<std::decay_t<Callback>, TCF,
void*>>
236 AMAsync( AMLaunch policy, Callback&& callback, AvailCallback&& a, Function&& f, TCF&& tcf, Args&&... args )
239 auto h =
new _AMLaunchFnHolder(tcf, std::move(a), std::move(callback));
240 void* mem = std::invoke(f, tcf, args...);
241 return AMFuture<std::invoke_result_t<std::decay_t<Callback>, std::decay_t<TCF>,
void*>>(mem, h);
246 class _AMFutureZombieBase
254 return _AMFutureZombieBase::checkZombies();
278 template<
class Callback,
class AvailCallback,
class Function,
class TCF,
class... Args>
280 AMAsync(
AMLaunch policy, Callback &&callback, AvailCallback &&a, Function &&f, TCF &&tcf, Args &&... args);
286 class AMFuture :
public std::future<T> {
325 template<class Callback, class AvailCallback, class Function, class TCF, class... Args>
327 AMFuture<std::invoke_result_t<std::decay_t<Callback>, TCF,
void *>>
328 AMAsync(
AMLaunch policy, Callback &&callback, AvailCallback &&a, Function &&f, TCF &&tcf, Args &&... args);
330 template<class Callback, class AvailCallback, class Function, class TCF, class... Args>
332 AMFuture<std::invoke_result_t<std::decay_t<Callback>, TCF,
void *>>
333 AMAsync(
AMLaunch policy, Callback &&callback, AvailCallback &&a, Function &&f, TCF &&tcf, Args &&... args);
335 template<class Function, class Callback, class TCF, class... Args>
336 static T perform(Function &&f, Callback &&c, TCF &&tcf, Args &&... args);
338 AMFuture(std::future<T> &&other) noexcept;
348 :std::future<T>(std::move(other)) {
353 :std::future<T>(std::move(other)) {
358 std::future<T>::operator=(std::move(other));
363 template<
class Function,
class Callback,
class TCF,
class... Args>
365 void *mem = std::invoke(f, tcf, args...);
366 return std::invoke(c, tcf, mem);
387 template<
class Callback,
class AvailCallback,
class Function,
class TCF,
class... Args>
388 AMFuture<std::invoke_result_t<std::decay_t<Callback>, TCF,
void *>>
389 AMAsync(
AMLaunch policy, Callback &&callback, AvailCallback &&a, Function &&f, TCF &&tcf, Args &&... args) {
392 std::future<std::invoke_result_t<std::decay_t<Callback>, TCF,
void *>> base =
396 std::forward<Function>(f),
397 std::forward<Callback>(callback),
398 std::forward<TCF>(tcf),
399 std::forward<Args>(args)...
402 AMFuture<std::invoke_result_t<std::decay_t<Callback>, std::decay_t<TCF>,
void *>>(std::move(base)));
405 class _AMFutureZombieBase {
407 static void add(_AMFutureZombieBase *p);
409 static bool checkZombies();
411 virtual ~_AMFutureZombieBase();
414 virtual bool valid() = 0;
416 virtual bool ready() = 0;
418 virtual void get() = 0;
420 static std::set<_AMFutureZombieBase *> m_zombies;
424 class _AMFutureZombie :
public _AMFutureZombieBase,
public AMFuture<T> {
426 _AMFutureZombie(AMFuture<T> &&other) noexcept;
428 ~_AMFutureZombie() {}
431 bool valid()
override;
432 bool ready()
override;
439 _AMFutureZombieBase::add(
new _AMFutureZombie<T>(std::move(*
this)));
444 bool _AMFutureZombie<T>::valid() {
449 bool _AMFutureZombie<T>::ready() {
450 return AMFuture<T>::wait_for(std::chrono::seconds(0)) == AMCore::AMFutureStatus::ready;
454 void _AMFutureZombie<T>::get() {
459 _AMFutureZombie<T>::_AMFutureZombie(AMFuture<T> &&other) noexcept
460 :AMFuture<T>(std::move(other)) {
470 return _AMFutureZombieBase::checkZombies();
476 #endif //SAW_ALL_AMFUTURE_H