libqi-api  2.8.7.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
async.hxx
Go to the documentation of this file.
1 #pragma once
2 
7 #ifndef _QI_DETAIL_ASYNC_HXX_
8 #define _QI_DETAIL_ASYNC_HXX_
9 
10 #include <qi/async.hpp>
11 #include <functional>
12 
13 namespace qi
14 {
15 namespace detail
16 {
17  template <typename F>
18  inline auto asyncMaybeActor(F&& cb, qi::Duration delay) ->
19  typename std::enable_if<detail::IsAsyncBind<F>::value, typename std::decay<decltype(cb())>::type>::type
20  {
21  if (delay != qi::Duration::zero())
22  return qi::getEventLoop()->asyncDelay(cb, delay).unwrap();
23  else
24  return cb();
25  }
26 
27  template <typename F>
28  inline auto asyncMaybeActor(F&& cb, qi::Duration delay) ->
29  typename std::enable_if<!detail::IsAsyncBind<F>::value,
31  {
32  return qi::getEventLoop()->asyncDelay(cb, delay);
33  }
34 
35  template <typename F>
36  inline auto asyncMaybeActor(F&& cb, qi::SteadyClockTimePoint timepoint) ->
37  typename std::enable_if<detail::IsAsyncBind<F>::value, typename std::decay<decltype(cb())>::type>::type
38  {
39  return qi::getEventLoop()->asyncAt(cb, timepoint).unwrap();
40  }
41  template <typename F>
42  inline auto asyncMaybeActor(F&& cb, qi::SteadyClockTimePoint timepoint) ->
43  typename std::enable_if<!detail::IsAsyncBind<F>::value,
45  {
46  return qi::getEventLoop()->asyncAt(cb, timepoint);
47  }
48 
49  // this function is used by qilang generation to call something regardless of if it's an actor or not
50  // it is very specific to qilang's generated code, I don't think it's a good idea to use it elsewhere
51  // this function may or may not return a future (the other overload does not)
52  template <typename F, typename Arg0, typename... Args>
53  auto invokeMaybeActor(F&& cb, Arg0* arg0, Args&&... args) ->
54  typename std::enable_if<std::is_base_of<Actor, typename std::decay<Arg0>::type>::value,
55  decltype(tryUnwrap(arg0->async(boost::bind(cb, arg0, std::forward<Args>(args)...)), 0))>::type
56  {
57  // this is an actor, we must async to strand the call
58  return tryUnwrap(arg0->async(boost::bind(cb, arg0, std::forward<Args>(args)...)), 0);
59  }
60  template <typename F, typename Arg0, typename... Args>
61  auto invokeMaybeActor(F&& cb, Arg0* arg0, Args&&... args) ->
62  typename std::enable_if<!std::is_base_of<Actor, typename std::decay<Arg0>::type>::value,
63  typename std::decay<decltype((arg0->*cb)(std::forward<Args>(args)...))>::type>::type
64  {
65  QI_ASSERT(arg0 && "the pointer on which the member is called is null");
66  return (arg0->*cb)(std::forward<Args>(args)...);
67  }
68 } // detail
69 
72 template<typename R>
73 QI_API_DEPRECATED_MSG(Use 'asyncDelay' instead)
74 inline Future<R> async(boost::function<R()> callback, uint64_t usDelay)
75 {
76  return qi::getEventLoop()->asyncDelay(callback, qi::MicroSeconds(usDelay));
77 }
78 template<typename R>
79 QI_API_DEPRECATED_MSG(Use 'asyncDelay' instead)
80 inline Future<R> async(boost::function<R()> callback, qi::Duration delay)
81 {
82  return qi::getEventLoop()->asyncDelay(callback, delay);
83 }
84 template<typename R>
85 QI_API_DEPRECATED_MSG(Use 'asyncAt' instead)
86 inline Future<R> async(boost::function<R()> callback, qi::SteadyClockTimePoint timepoint)
87 {
88  return qi::getEventLoop()->asyncAt(callback, timepoint);
89 }
90 template<typename R>
91 QI_API_DEPRECATED_MSG(Use 'async' without explicit return type template arguement instead)
92 inline Future<R> async(detail::Function<R()> callback)
93 {
94  return qi::getEventLoop()->async(callback);
95 }
96 
97 #ifdef DOXYGEN
98 template<typename R, typename Func, typename ArgTrack>
100 QI_API_DEPRECATED qi::Future<R> async(const Func& f, const ArgTrack& toTrack, ...);
101 #else
102 #define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma) \
103 template <typename R, typename AF, typename ARG0 comma ATYPEDECL> \
104 inline QI_API_DEPRECATED Future<R> async(const AF& fun, const ARG0& arg0 comma ADECL, qi::Duration delay = qi::Duration(0)) \
105 { \
106  return detail::asyncMaybeActor(qi::bind(fun, arg0 comma AUSE), delay); \
107 } \
108 template <typename R, typename AF, typename ARG0 comma ATYPEDECL> \
109 inline QI_API_DEPRECATED Future<R> async(const AF& fun, const ARG0& arg0 comma ADECL, qi::SteadyClockTimePoint timepoint) \
110 { \
111  return detail::asyncMaybeActor(qi::bind(fun, arg0 comma AUSE), timepoint); \
112 }
114 #undef genCall
115 #endif
116 
117 namespace detail
118 {
119  template<typename T>
120  void tryCancel(Future<T>& fut, const char* errorMsg)
121  {
122  try
123  {
124  // This condition is racy, but the goal is to avoid useless logs
125  // (in the catch clauses).
126  if (fut.isRunning())
127  {
128  fut.cancel();
129  }
130  }
131  catch (const std::runtime_error& e)
132  {
133  qiLogVerbose("qi.Future") << errorMsg << "detail=" << e.what();
134  }
135  catch (...)
136  {
137  qiLogVerbose("qi.Future") << errorMsg << "No detail.";
138  }
139  }
140 }
141 
146 template<typename T, typename Duration>
148 {
149  auto cancelFut = asyncDelay(
150  [=]() mutable {
151  detail::tryCancel(fut, "cancelOnTimeout: timeout task failed to cancel the running task: ");
152  },
153  timeout);
154  fut.then([=](const Future<T>&) mutable {
155  detail::tryCancel(cancelFut, "cancelOnTimeout: running task failed to cancel the timeout task");
156  });
157  return fut;
158 }
159 
160 } // qi
161 #endif // _QI_DETAIL_ASYNC_HXX_
auto asyncDelay(F &&callback, qi::Duration delay) -> decltype(detail::asyncMaybeActor(std::forward< F >(callback), delay))
Definition: async.hpp:46
DurationType< int64_t, boost::micro > MicroSeconds
Definition: clock.hpp:26
SteadyClock::time_point SteadyClockTimePoint
Steady clock time point.
Definition: clock.hpp:211
#define qiLogVerbose(...)
Log in verbose mode. This level is not shown by default.
Definition: log.hpp:87
#define QI_ASSERT(expr__)
Definition: assert.hpp:27
void tryCancel(Future< T > &fut, const char *errorMsg)
Definition: async.hxx:120
Future< R > async(const boost::function< R()> &callback, uint64_t usDelay)
Calls given function once after given delay in microseconds.
Definition: eventloop.hxx:19
qi::Future< R > asyncDelay(F &&callback, qi::Duration delay, ExecutionOptions options=defaultExecutionOptions())
call a callback asynchronously to be executed in delay
auto then(FutureCallbackType type, F &&func) -> Future< typename std::result_of< F(Future< T >)>::type >
Execute a callback when the future is finished.
Definition: future_fwd.hpp:453
NanoSeconds Duration
Definition: clock.hpp:32
auto asyncMaybeActor(F &&cb, qi::Duration delay) -> typename std::enable_if< detail::IsAsyncBind< F >::value, typename std::decay< decltype(cb())>::type >::type
Definition: async.hxx:18
#define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma)
Definition: session.hpp:175
#define QI_API_DEPRECATED_MSG(msg__)
Compiler flags to mark a function as deprecated. It will generate a compiler warning.
Definition: macro.hpp:55
auto async(F &&callback) -> decltype(asyncDelay(std::forward< F >(callback), qi::Duration(0)))
Definition: async.hpp:53
T tryUnwrap(T anything)
bool isRunning() const
Definition: future_fwd.hpp:330
void cancel()
Definition: future_fwd.hpp:383
EventLoop * getEventLoop()
Returns the global eventloop, created on demand on first call.
qi::Future< R > asyncAt(F &&callback, qi::SteadyClockTimePoint tp, ExecutionOptions options=defaultExecutionOptions())
call a callback asynchronously to be executed on tp
#define QI_API_DEPRECATED
Compiler flags to mark a function as deprecated. It will generate a compiler warning.
Definition: macro.hpp:41
auto invokeMaybeActor(F &&cb, Arg0 *arg0, Args &&...args) -> typename std::enable_if< std::is_base_of< Actor, typename std::decay< Arg0 >::type >::value, decltype(tryUnwrap(arg0->async(boost::bind(cb, arg0, std::forward< Args >(args)...)), 0))>::type
Definition: async.hxx:53
uint64_t uint64_t
Definition: types.hpp:66
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)
Definition: trackable.hxx:308
#define QI_GEN(f)
Definition: preproc.hpp:476
Future< T > cancelOnTimeout(Future< T > fut, Duration timeout)
Definition: async.hxx:147