libqi-api  2.8.7.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
executioncontext.hpp
Go to the documentation of this file.
1 #pragma once
2 /*
3 ** Copyright (C) 2012 Aldebaran Robotics
4 ** See COPYING for the license
5 */
6 
7 #ifndef _QI_EXECUTION_CONTEXT_HPP_
8 #define _QI_EXECUTION_CONTEXT_HPP_
9 
10 #include <type_traits>
11 #include <boost/function.hpp>
12 #include <qi/api.hpp>
13 #include <qi/clock.hpp>
14 #include <ka/typetraits.hpp>
15 
16 namespace qi
17 {
18 
19 template <typename T>
20 class Future;
21 
22 namespace detail
23 {
24 
25  // This class is kind of a hack to deprecate the old versions of async/post etc without deprecating the correct use of
26  // the new ones. This class is just a strong alias to boost::function
27  template <typename T>
28  struct Function : boost::function<T>
29  {
30  template<class Arg>
31  Function(Arg&& arg,
32  typename std::enable_if<!std::is_same<typename std::decay<Arg>::type, Function>::value>::type* = nullptr)
33  : boost::function<T>(std::forward<Arg>(arg))
34  {}
35 
36  Function(const Function&) = default;
37  };
38 
39 }
40 
41 enum class CancelOption
45 };
46 
49 {
54 };
55 
56 BOOST_CONSTEXPR
58 {
60 }
61 
62 
64 {
65 public:
66  virtual ~ExecutionContext() {}
67 
68  // DEPRECATED STUFF
71  QI_API_DEPRECATED_MSG(Use 'asyncAt' instead)
72  virtual qi::Future<void> async(const boost::function<void()>& callback, qi::SteadyClockTimePoint tp) = 0;
75  QI_API_DEPRECATED_MSG(Use 'asyncDelay' instead)
76  virtual qi::Future<void> async(const boost::function<void()>& callback, qi::Duration delay) = 0;
77 
80  template <typename R>
81  QI_API_DEPRECATED_MSG(Use 'asyncDelay' instead)
82  typename boost::disable_if<std::is_same<R, void>, qi::Future<R> >::type
83  async(const boost::function<R()>& callback, qi::Duration delay);
86  template <typename R>
87  QI_API_DEPRECATED_MSG(Use 'asyncAt' instead)
88  typename boost::disable_if<std::is_same<R, void>, qi::Future<R> >::type
89  async(const boost::function<R()>& callback, qi::SteadyClockTimePoint tp);
90 
92  template <typename R>
93  QI_API_DEPRECATED_MSG(Use 'async' without explicit return type template arguement instead)
94  qi::Future<R> async(const detail::Function<R()>& callback)
95  {
96  return asyncDelay(callback, qi::Duration(0));
97  }
98  // END OF DEPRECATED STUFF
99 
101  template <typename F>
102  void post(F&& callback, ExecutionOptions options = defaultExecutionOptions());
103 
105  template <typename F, typename R = ka::Decay<decltype(std::declval<F>()())>>
108  template <typename F, typename R = ka::Decay<decltype(std::declval<F>()())>>
110 
111  template <typename F>
112  auto async(F&& callback, ExecutionOptions options = defaultExecutionOptions())
113  -> decltype(asyncDelay(std::forward<F>(callback), qi::Duration(0), options))
114  {
115  return asyncDelay(std::forward<F>(callback), qi::Duration(0), options);
116  }
117 
119  virtual bool isInThisContext() const = 0;
120 
121 protected:
122  virtual void postImpl(boost::function<void()> callback, ExecutionOptions options) = 0;
123  virtual qi::Future<void> asyncAtImpl(boost::function<void()> cb, qi::SteadyClockTimePoint tp, ExecutionOptions options) = 0;
124  virtual qi::Future<void> asyncDelayImpl(boost::function<void()> cb, qi::Duration delay, ExecutionOptions options) = 0;
125 };
126 
127 }
128 
129 #include <qi/detail/future_fwd.hpp>
130 
131 namespace qi
132 {
133 
134 namespace detail
135 {
136 
137 template <typename T>
138 class DelayedPromise: public Promise<T>
139 {
140 public:
141  void setup(boost::function<void (qi::Promise<T>)> cancelCallback, FutureCallbackType async = FutureCallbackType_Async)
142  {
143  Promise<T>::setup(cancelCallback, async);
144  }
145 };
146 
147 template <typename R>
148 void setValue(qi::Promise<R>& p, const boost::function<R()>& f)
149 {
150  p.setValue(f());
151 }
152 
153 template <>
154 inline void setValue<void>(qi::Promise<void>& p, const boost::function<void()>& f)
155 {
156  f();
157  p.setValue(0);
158 }
159 
160 template <typename R>
161 void callAndSet(qi::Promise<R> p, boost::function<R()> f)
162 {
163  try
164  {
165  setValue<R>(p, f);
166  }
167  catch (const std::exception& e)
168  {
169  p.setError(e.what());
170  }
171  catch(...)
172  {
173  p.setError("unknown exception");
174  }
175 }
176 template <typename R>
178 {
179  switch (f.wait())
180  {
181  case FutureState_Canceled: p.setCanceled(); break;
182  case FutureState_FinishedWithError: p.setError(f.error()); break;
183  case FutureState_None: // Nothing to do for these states.
184  case FutureState_Running:
185  case FutureState_FinishedWithValue: break;
186  }
187 }
188 
189 }
190 
191 template <typename R>
192 typename boost::disable_if<std::is_same<R, void>,
193  qi::Future<R> >::type
194  ExecutionContext::async(const boost::function<R()>& callback,
195  qi::Duration delay)
196 {
198  qi::Future<void> f = async(boost::function<void()>(boost::bind(
199  detail::callAndSet<R>, promise, callback)),
200  delay);
201  promise.setup(
202  boost::bind(&detail::futureCancelAdapter<void>,
203  boost::weak_ptr<detail::FutureBaseTyped<void> >(f.impl())));
204  f.connect(boost::bind(&detail::forwardError<R>, _1, promise), FutureCallbackType_Sync);
205  return promise.future();
206 }
207 
208 template <typename R>
209 typename boost::disable_if<std::is_same<R, void>,
210  qi::Future<R> >::type
211  ExecutionContext::async(const boost::function<R()>& callback,
213 {
215  qi::Future<void> f = async(boost::function<void()>(boost::bind(
216  detail::callAndSet<R>, promise, callback)),
217  tp);
218  promise.setup(
219  boost::bind(&detail::futureCancelAdapter<void>,
220  boost::weak_ptr<detail::FutureBaseTyped<void> >(f.impl())));
221  f.connect(boost::bind(&detail::forwardError<R>, _1, promise), FutureCallbackType_Sync);
222  return promise.future();
223 }
224 
225 template <typename F>
226 void ExecutionContext::post(F&& callback, ExecutionOptions options)
227 {
228  postImpl(std::forward<F>(callback), options);
229 }
230 
231 template <typename ReturnType, typename Callback>
232 struct ToPost
233 {
235  Callback callback;
236 
237  ToPost(Callback cb) :
238  callback(std::move(cb))
239  {}
240 
241  void operator()()
242  {
243  detail::callAndSet<ReturnType>(std::move(promise), std::move(callback));
244  }
245 };
246 
247 template <typename F, typename R>
249 {
250  ToPost<R, typename std::decay<F>::type> topost(std::forward<F>(callback));
251  auto promise = topost.promise;
252  qi::Future<void> f = asyncAtImpl(std::move(topost), tp, options);
253  promise.setup(boost::bind(&detail::futureCancelAdapter<void>,
254  boost::weak_ptr<detail::FutureBaseTyped<void> >(f.impl())));
255  f.connect(boost::bind(&detail::forwardError<R>, _1, promise), FutureCallbackType_Sync);
256  return promise.future();
257 }
258 
259 template <typename F, typename R>
261 {
262  ToPost<R, typename std::decay<F>::type> topost(std::forward<F>(callback));
263  auto promise = topost.promise;
264  qi::Future<void> f = asyncDelayImpl(std::move(topost), delay, options);
265  promise.setup(boost::bind(&detail::futureCancelAdapter<void>,
266  boost::weak_ptr<detail::FutureBaseTyped<void> >(f.impl())));
267  f.connect(boost::bind(&detail::forwardError<R>, _1, promise), FutureCallbackType_Sync);
268  return promise.future();
269 }
270 }
271 
272 #endif
void setValue(qi::Promise< R > &p, const boost::function< R()> &f)
void setup(boost::function< void(qi::Promise< T >)> cancelCallback, FutureCallbackType async=FutureCallbackType_Async)
detail::DelayedPromise< ReturnType > promise
auto asyncDelay(F &&callback, qi::Duration delay) -> decltype(detail::asyncMaybeActor(std::forward< F >(callback), delay))
Definition: async.hpp:46
void setValue< void >(qi::Promise< void > &p, const boost::function< void()> &f)
void setup(boost::function< void(qi::Promise< T > &)> cancelCallback, FutureCallbackType async=FutureCallbackType_Auto)
Definition: future_fwd.hpp:915
void connect(const AF &fun, FutureCallbackType type=FutureCallbackType_Auto)
Definition: future_fwd.hpp:545
BOOST_CONSTEXPR ExecutionOptions defaultExecutionOptions() BOOST_NOEXCEPT
The future has been canceled.
Definition: future_fwd.hpp:85
#define QI_API
Definition: api.hpp:33
... the execution context must not execute the task.
SteadyClock::time_point SteadyClockTimePoint
Steady clock time point.
Definition: clock.hpp:211
CancelOption onCancelRequested
virtual qi::Future< void > asyncAtImpl(boost::function< void()> cb, qi::SteadyClockTimePoint tp, ExecutionOptions options)=0
virtual qi::Future< void > async(const boost::function< void()> &callback, qi::SteadyClockTimePoint tp)=0
void setError(const std::string &msg)
Definition: future_fwd.hpp:862
virtual void postImpl(boost::function< void()> callback, ExecutionOptions options)=0
Function(Arg &&arg, typename std::enable_if<!std::is_same< typename std::decay< Arg >::type, Function >::value >::type *=nullptr)
dll import/export and compiler message
... the executino context must still execute the task.
qi::Future< R > asyncDelay(F &&callback, qi::Duration delay, ExecutionOptions options=defaultExecutionOptions())
call a callback asynchronously to be executed in delay
NanoSeconds Duration
Definition: clock.hpp:32
void forwardError(qi::Future< void > f, qi::Promise< R > p)
void callAndSet(qi::Promise< R > p, boost::function< R()> f)
virtual qi::Future< void > asyncDelayImpl(boost::function< void()> cb, qi::Duration delay, ExecutionOptions options)=0
Future< T > future() const
Get a future linked to this promise. Can be called multiple times.
Definition: future_fwd.hpp:881
ToPost(Callback cb)
CancelOption
< If cancel have been requested for the associated scheduled task...
... allow the execution context to not execute the task.
Future is not tied to a promise.
Definition: future_fwd.hpp:83
auto async(F &&callback, ExecutionOptions options=defaultExecutionOptions()) -> decltype(asyncDelay(std::forward< F >(callback), qi::Duration(0), options))
Operation pending.
Definition: future_fwd.hpp:84
#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
auto asyncAt(F &&callback, qi::SteadyClockTimePoint timepoint) -> decltype(qi::getEventLoop() ->asyncAt(std::forward< F >(callback), timepoint))
Definition: async.hpp:39
The operation is finished with an error.
Definition: future_fwd.hpp:86
qi::Future< R > asyncAt(F &&callback, qi::SteadyClockTimePoint tp, ExecutionOptions options=defaultExecutionOptions())
call a callback asynchronously to be executed on tp
void setCanceled()
Definition: future_fwd.hpp:869
void post(F &&callback, ExecutionOptions options=defaultExecutionOptions())
post a callback to be executed as soon as possible
FutureState wait(int msecs=FutureTimeout_Infinite) const
Definition: future_fwd.hpp:296
const std::string & error(int msecs=FutureTimeout_Infinite) const
Definition: future_fwd.hpp:367
FutureCallbackType
Definition: future_fwd.hpp:104
void setValue(const ValueType &value)
Definition: future_fwd.hpp:855
boost::shared_ptr< detail::FutureBaseTyped< T > > impl()
An accessor to the shared state. TODO: remove it, it should not exist.
Definition: future_fwd.hpp:588
The operation is finished with a value.
Definition: future_fwd.hpp:87
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)
Definition: trackable.hxx:308
Represent execution behaviour options attached to a task that must be interpreted by an ExecutionCont...