libqi-api  release-2.5.3-2016-11-18
 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 <boost/function.hpp>
11 #include <qi/clock.hpp>
12 #include <qi/api.hpp>
13 #include <type_traits>
14 
15 namespace qi
16 {
17 
18 template <typename T>
19 class Future;
20 
21 namespace detail
22 {
23 
24  // This class is kind of a hack to deprecate the old versions of async/post etc without deprecating the correct use of
25  // the new ones. This class is just a strong alias to boost::function
26  template <typename T>
27  struct Function : boost::function<T>
28  {
29  template<class Arg>
30  Function(Arg&& arg,
31  typename std::enable_if<!std::is_same<typename std::decay<Arg>::type, Function>::value>::type* = nullptr)
32  : boost::function<T>(std::forward<Arg>(arg))
33  {}
34 
35  Function(const Function&) = default;
36  };
37 
38 }
39 
41 {
42 public:
43  virtual ~ExecutionContext() {}
44 
45  // DEPRECATED STUFF
48  QI_API_DEPRECATED_MSG(Use 'asyncAt' instead)
49  virtual qi::Future<void> async(const boost::function<void()>& callback, qi::SteadyClockTimePoint tp) = 0;
52  QI_API_DEPRECATED_MSG(Use 'asyncDelay' instead)
53  virtual qi::Future<void> async(const boost::function<void()>& callback, qi::Duration delay) = 0;
54 
57  template <typename R>
58  QI_API_DEPRECATED_MSG(Use 'asyncDelay' instead)
59  typename boost::disable_if<std::is_same<R, void>, qi::Future<R> >::type
60  async(const boost::function<R()>& callback, qi::Duration delay);
63  template <typename R>
64  QI_API_DEPRECATED_MSG(Use 'asyncAt' instead)
65  typename boost::disable_if<std::is_same<R, void>, qi::Future<R> >::type
66  async(const boost::function<R()>& callback, qi::SteadyClockTimePoint tp);
67 
69  template <typename R>
70  QI_API_DEPRECATED_MSG(Use 'async' without explicit return type template arguement instead)
71  qi::Future<R> async(const detail::Function<R()>& callback)
72  {
73  return asyncDelay(callback, qi::Duration(0));
74  }
75  // END OF DEPRECATED STUFF
76 
78  template <typename F>
79  void post(F&& callback);
81  template <typename F>
84  template <typename F>
86 
87  template <typename F>
88  auto async(F&& callback) -> decltype(asyncDelay(std::forward<F>(callback), qi::Duration(0)))
89  {
90  return asyncDelay(std::forward<F>(callback), qi::Duration(0));
91  }
92 
94  virtual bool isInThisContext() = 0;
95 
96 protected:
97  virtual void postImpl(boost::function<void()> callback) = 0;
98  virtual qi::Future<void> asyncAtImpl(boost::function<void()> cb, qi::SteadyClockTimePoint tp) = 0;
99  virtual qi::Future<void> asyncDelayImpl(boost::function<void()> cb, qi::Duration delay) = 0;
100 };
101 
102 }
103 
104 #include <qi/detail/future_fwd.hpp>
105 
106 namespace qi
107 {
108 
109 namespace detail
110 {
111 
112 template <typename T>
113 class DelayedPromise: public Promise<T>
114 {
115 public:
116  void setup(boost::function<void (qi::Promise<T>)> cancelCallback, FutureCallbackType async = FutureCallbackType_Async)
117  {
118  Promise<T>::setup(cancelCallback, async);
119  }
120 };
121 
122 template <typename R>
123 void setValue(qi::Promise<R>& p, const boost::function<R()>& f)
124 {
125  p.setValue(f());
126 }
127 
128 template <>
129 inline void setValue<void>(qi::Promise<void>& p, const boost::function<void()>& f)
130 {
131  f();
132  p.setValue(0);
133 }
134 
135 template <typename R>
136 void callAndSet(qi::Promise<R> p, boost::function<R()> f)
137 {
138  try
139  {
140  setValue<R>(p, f);
141  }
142  catch (const std::exception& e)
143  {
144  p.setError(e.what());
145  }
146  catch(...)
147  {
148  p.setError("unknown exception");
149  }
150 }
151 template <typename R>
153 {
154  if (f.wait() == FutureState_Canceled)
155  p.setCanceled();
156  // Nothing to do for other states.
157 }
158 
159 }
160 
161 template <typename R>
162 typename boost::disable_if<std::is_same<R, void>,
163  qi::Future<R> >::type
164  ExecutionContext::async(const boost::function<R()>& callback,
165  qi::Duration delay)
166 {
168  qi::Future<void> f = async(boost::function<void()>(boost::bind(
169  detail::callAndSet<R>, promise, callback)),
170  delay);
171  promise.setup(
172  boost::bind(&detail::futureCancelAdapter<void>,
173  boost::weak_ptr<detail::FutureBaseTyped<void> >(f.impl())));
174  f.connect(boost::bind(&detail::checkCanceled<R>, _1, promise), FutureCallbackType_Sync);
175  return promise.future();
176 }
177 
178 template <typename R>
179 typename boost::disable_if<std::is_same<R, void>,
180  qi::Future<R> >::type
181  ExecutionContext::async(const boost::function<R()>& callback,
183 {
185  qi::Future<void> f = async(boost::function<void()>(boost::bind(
186  detail::callAndSet<R>, promise, callback)),
187  tp);
188  promise.setup(
189  boost::bind(&detail::futureCancelAdapter<void>,
190  boost::weak_ptr<detail::FutureBaseTyped<void> >(f.impl())));
191  f.connect(boost::bind(&detail::checkCanceled<R>, _1, promise), FutureCallbackType_Sync);
192  return promise.future();
193 }
194 
195 template <typename F>
196 void ExecutionContext::post(F&& callback)
197 {
198  postImpl(std::forward<F>(callback));
199 }
200 
201 template <typename ReturnType, typename Callback>
202 struct ToPost
203 {
205  Callback callback;
206 
207  ToPost(Callback cb) :
208  callback(std::move(cb))
209  {}
210 
211  void operator()()
212  {
213  detail::callAndSet<ReturnType>(std::move(promise), std::move(callback));
214  }
215 };
216 
217 template <typename F>
219 {
220  using ReturnType = typename std::decay<decltype(callback())>::type;
221 
222  ToPost<ReturnType, typename std::decay<F>::type> topost(std::move(callback));
223  auto promise = topost.promise;
224  qi::Future<void> f = asyncAtImpl(std::move(topost), tp);
225  promise.setup(boost::bind(&detail::futureCancelAdapter<void>,
226  boost::weak_ptr<detail::FutureBaseTyped<void> >(f.impl())));
227  f.connect(boost::bind(&detail::checkCanceled<ReturnType>, _1, promise), FutureCallbackType_Sync);
228  return promise.future();
229 }
230 
231 template <typename F>
233 {
234  using ReturnType = typename std::decay<decltype(callback())>::type;
235 
236  ToPost<ReturnType, typename std::decay<F>::type> topost(std::move(callback));
237  auto promise = topost.promise;
238  qi::Future<void> f = asyncDelayImpl(std::move(topost), delay);
239  promise.setup(boost::bind(&detail::futureCancelAdapter<void>,
240  boost::weak_ptr<detail::FutureBaseTyped<void> >(f.impl())));
241  f.connect(boost::bind(&detail::checkCanceled<ReturnType>, _1, promise), FutureCallbackType_Sync);
242  return promise.future();
243 }
244 }
245 
246 #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: eventloop.hpp:210
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:820
void connect(const AF &fun, FutureCallbackType type=FutureCallbackType_Auto)
Definition: future_fwd.hpp:484
The future has been canceled.
Definition: future_fwd.hpp:78
#define QI_API
Definition: api.hpp:33
virtual void postImpl(boost::function< void()> callback)=0
SteadyClock::time_point SteadyClockTimePoint
Steady clock time point.
Definition: clock.hpp:211
virtual qi::Future< void > async(const boost::function< void()> &callback, qi::SteadyClockTimePoint tp)=0
void setError(const std::string &msg)
Definition: future_fwd.hpp:767
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
auto asyncDelay(F &&callback, qi::Duration delay) -> qi::Future< typename std::decay< decltype(callback())>::type >
call a callback asynchronously to be executed in delay
NanoSeconds Duration
Definition: clock.hpp:32
void callAndSet(qi::Promise< R > p, boost::function< R()> f)
typename detail::FunctionImpl< A >::type Function
Definition: traits.hpp:133
Future< T > future() const
Get a future linked to this promise. Can be called multiple times.
Definition: future_fwd.hpp:786
ToPost(Callback cb)
Future< R > async(boost::function< R()> callback, uint64_t usDelay)
Definition: eventloop.hpp:186
void post(F &&callback)
post a callback to be executed as soon as possible
#define QI_API_DEPRECATED_MSG(msg__)
Compiler flags to mark a function as deprecated. It will generate a compiler warning.
Definition: macro.hpp:53
auto async(F &&callback) -> decltype(asyncDelay(std::forward< F >(callback), qi::Duration(0)))
auto asyncAt(F &&callback, qi::SteadyClockTimePoint timepoint) -> decltype(qi::getEventLoop() ->asyncAt(std::forward< F >(callback), timepoint))
Definition: eventloop.hpp:216
void setCanceled()
Definition: future_fwd.hpp:774
FutureState wait(int msecs=FutureTimeout_Infinite) const
Definition: future_fwd.hpp:226
auto asyncAt(F &&callback, qi::SteadyClockTimePoint tp) -> qi::Future< typename std::decay< decltype(callback())>::type >
call a callback asynchronously to be executed on tp
void checkCanceled(qi::Future< void > f, qi::Promise< R > p)
FutureCallbackType
Definition: future_fwd.hpp:83
void setValue(const ValueType &value)
Definition: future_fwd.hpp:760
boost::shared_ptr< detail::FutureBaseTyped< T > > impl()
Definition: future_fwd.hpp:524
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)
Definition: trackable.hxx:327