7 #ifndef _QI_DETAILS_FUTURE_HXX_
8 #define _QI_DETAILS_FUTURE_HXX_
12 #include <boost/bind.hpp>
23 template <
typename T,
typename R>
27 const boost::function<R(
const T&)>& func)
37 const boost::function<
void(
const T&)>& func)
44 template <
typename T,
typename R>
46 const boost::function<R(
const Future<T>&)>& func,
53 catch (std::exception& e)
59 promise.
setError(
"unknown exception");
63 template <
typename T,
typename R>
80 catch (std::exception& e)
86 promise.
setError(
"unknown exception");
95 boost::shared_ptr<FutureBaseTyped<T> > futureb = wfutureb.lock();
103 template <
typename T>
104 template <
typename R>
107 const boost::function<R(
const Future<T>&)>& func)
114 _p->connect(*
this,
boost::bind(&detail::continuateThen<T, R>, _1,
115 func, promise), type);
119 template <
typename T>
120 template <
typename R>
132 _p->connect(*
this,
boost::bind(&detail::continuateAndThen<T, R>, _1,
133 func, promise), type);
137 template <
typename T>
138 template <
typename Arg>
140 const boost::function<
void(
const boost::function<
void()>&)>& poster,
141 const boost::function<
void(
const Arg&)>& callback,
const Arg& fut)
146 template <
typename T>
147 template <
typename Arg>
148 inline boost::function<void(const Arg&)>
149 Future<T>::transformStrandedCallback(
151 const boost::function<
void(
const Arg&)>& cb)
154 &Future<T>::binder<Arg>,
155 boost::function<
void(
const boost::function<
void()>&)>(
162 template <
typename T>
163 template <
typename ARG0>
164 inline typename boost::enable_if<
165 boost::is_base_of<Actor, typename detail::Unwrap<ARG0>::type>,
167 Future<T>::_connectMaybeActor(
168 const ARG0& arg0,
const boost::function<
void(
const Future<T>&)>& cb,
173 boost::function<
void()>(),
175 detail::Unwrap<ARG0>::unwrap(arg0)->strand(), cb),
179 template <
typename T>
180 template <
typename ARG0>
181 inline typename boost::disable_if<
182 boost::is_base_of<Actor, typename detail::Unwrap<ARG0>::type>,
184 Future<T>::_connectMaybeActor(
185 const ARG0& arg0,
const boost::function<
void(
const Future<T>&)>& cb,
188 _p->connect(*
this, cb, type);
191 template <
typename T>
192 template <
typename R,
typename ARG0,
typename AF>
193 typename boost::enable_if<
194 boost::is_base_of<Actor, typename detail::Unwrap<ARG0>::type>,
196 Future<T>::_thenMaybeActor(
const ARG0& arg0,
201 boost::function<
void()>(),
203 detail::Unwrap<ARG0>::unwrap(arg0)->strand(), cb),
206 template <
typename T>
207 template <
typename R,
typename ARG0,
typename AF>
208 typename boost::disable_if<
209 boost::is_base_of<Actor, typename detail::Unwrap<ARG0>::type>,
211 Future<T>::_thenMaybeActor(
const ARG0& arg0,
215 return thenR(type, cb);
218 template <
typename T>
219 void Future<T>::_weakCancelCb(
const boost::weak_ptr<detail::FutureBaseTyped<T> >& wfuture)
221 if (boost::shared_ptr<detail::FutureBaseTyped<T> > fbt = wfuture.lock())
223 Future<T> future(fbt);
229 template <
typename T>
233 throw std::runtime_error(
"future is not cancelable");
239 class FutureBasePrivate;
249 bool isRunning()
const;
250 bool isFinished()
const;
251 bool isCanceled()
const;
252 bool isCancelRequested()
const;
253 bool hasError(
int msecs)
const;
254 bool hasValue(
int msecs)
const;
255 const std::string &error(
int msecs)
const;
261 void reportError(
const std::string &message);
262 void requestCancel();
263 void reportCanceled();
264 boost::recursive_mutex& mutex();
268 FutureBasePrivate *
_p;
273 template <
typename T>
287 _onDestroyed(_value);
292 return static_cast<bool>(_onCancel);
299 boost::recursive_mutex::scoped_lock lock(
mutex());
305 onCancel = _onCancel;
313 bool doCancel =
false;
315 boost::recursive_mutex::scoped_lock lock(
mutex());
316 _onCancel = onCancel;
326 for(
unsigned i = 0; i<_onResult.size(); ++i)
332 _onResult[i](future);
334 }
catch(
const std::exception& e) {
335 qiLogError(
"qi.future") <<
"Exception caught in future callback "
339 <<
"Unknown exception caught in future callback";
351 boost::recursive_mutex::scoped_lock lock(
mutex());
368 boost::recursive_mutex::scoped_lock lock(
mutex());
378 boost::recursive_mutex::scoped_lock lock(
mutex());
388 boost::recursive_mutex::scoped_lock lock(
mutex());
391 reportError(
"Promise broken (all promises are destroyed)");
396 boost::recursive_mutex::scoped_lock lock(
mutex());
415 boost::recursive_mutex::scoped_lock lock(
mutex());
419 _onResult.push_back(s);
432 }
catch(const ::qi::PointerLockException&)
451 typedef std::vector<boost::function<void (qi::Future<T>)> > Callbacks;
455 boost::function<void (ValueType)> _onDestroyed;
459 void clearCallbacks()
469 template <
typename T>
473 if (!prom.future().isFinished() && !fut.
hasError())
487 if (!prom.future().isFinished())
493 prom.setValue(makeFutureError<T>(
"No future returned successfully."));
502 template <
typename T>
517 return promise.future();
533 const boost::weak_ptr<FutureBaseTyped<
Future<T> > >& wfuture)
535 if (boost::shared_ptr<FutureBaseTyped<
Future<T> > > fbt =
547 template <
typename T>
556 template<
typename FT,
typename PT,
typename CONV>
568 catch (
const std::exception& e)
570 p.
setError(std::string(
"futureAdapter conversion error: ") + e.what());
577 template<
typename FT>
593 template <
typename T>
601 template <
typename T>
620 template<
typename FT,
typename PT>
630 template<
typename FT,
typename PT,
typename CONV>
642 #endif // _QI_DETAILS_FUTURE_HXX_
static void * _callfunc(const T &future, const boost::function< void(const T &)> &func)
void setError(qi::Future< T > &future, const std::string &message)
void forwardCancel(const boost::weak_ptr< FutureBaseTyped< T > > &wfutureb)
when the promise is already set.
The future has been canceled.
FutureState wait(int msecs) const
void continuateThen(const Future< T > &future, const boost::function< R(const Future< T > &)> &func, qi::Promise< R > &promise)
void operator()(const T &in, void *out)
void operator()(void *in, void *out)
boost::function< RF > bind(const AF &fun,...)
void setCanceled(qi::Future< T > &future)
boost::chrono::duration< int64_t, boost::nano > Duration
Convenience typedefs.
The future has been canceled.
void setup(boost::function< void(qi::Promise< T >)> cancelCallback, FutureCallbackType async=FutureCallbackType_Async)
void setValue(qi::Future< T > &future, const ValueType &value)
void setError(const std::string &msg)
void reportError(const std::string &message)
void set(qi::Future< T > &future)
void callCbNotify(qi::Future< T > &future)
bool hasValue(int msecs) const
boost::function< void()> makeCanceler()
Get a functor that will cancel the future.
Specialize this struct to provide conversion between future values.
qi::Future< T > makeFutureError(const std::string &error)
Helper function to return a future with the error set.
FutureType< T >::type ValueType
bool isCancelRequested() const
void post(const boost::function< void()> &callback, uint64_t usDelay)
Similar to async() but without cancelation or notification.
void futureAdapter(Future< FT > f, Promise< PT > p, CONV converter)
void connect(const AF &fun, FutureCallbackType type=FutureCallbackType_Async)
void post(const boost::function< void()> &callback)
post a callback to be executed as soon as possible
Future< T > future() const
Get a future linked to this promise. Can be called multiple times.
bool isCancelable() const
boost::shared_ptr< detail::FutureBaseTyped< T > > _p
#define qiLogError(...)
Log in error mode.
boost::function< void(Promise< T >)> CancelCallback
void setOnDestroyed(boost::function< void(ValueType)> f)
bool isCancelable() const
EventLoop * getEventLoop()
Return the global eventloop, created on demand on first call.
void connect(qi::Future< T > future, const boost::function< void(qi::Future< T >)> &s, FutureCallbackType type)
The operation is finished with an error.
bool isCancelRequested() const
void waitForFirstHelper(qi::Promise< qi::Future< T > > &prom, qi::Future< T > &fut, qi::Atomic< int > *count)
detail::FutureType< T >::type ValueType
boost::function< F > trackWithFallback(boost::function< void()> onFail, const boost::function< F > &f, const ARG0 &arg0)
Wrap given function f with a tracking check on arg0, which must be a weak pointer or a Trackable inst...
boost::recursive_mutex & mutex()
void cancel(qi::Future< T > &future)
const std::string & error(int msecs) const
void adaptFuture(const Future< FT > &f, Promise< PT > &p)
Feed a promise from a future of possibly different type.
void futureCancelAdapter(boost::weak_ptr< FutureBaseTyped< FT > > wf)
const std::string & error(int msecs=FutureTimeout_Infinite) const
const ValueType & value(int msecs=FutureTimeout_Infinite) const
Return the value associated to a Future.
FutureState state() const
void setBroken(qi::Future< T > &future)
void setValue(const ValueType &value)
boost::chrono::time_point< SteadyClock > time_point
The future is not cancelable.
Future< R > andThenR(FutureCallbackType type, const boost::function< R(const typename Future< T >::ValueType &)> &func)
Future< R > thenR(FutureCallbackType type, const boost::function< R(const Future< T > &)> &func)
void setOnCancel(qi::Promise< T > &promise, CancelCallback onCancel)
static R _callfunc(const T &arg, const boost::function< R(const T &)> &func)
const ValueType & value(int msecs) const
void continuateAndThen(const Future< T > &future, const boost::function< R(const typename Future< T >::ValueType &)> &func, qi::Promise< R > &promise)
void operator()(void *in, const T &out)
void adaptFutureUnwrap(Future< AnyReference > &f, Promise< R > &p)
Feed a promise from a generic future which may be unwrapped if it contains itself a future...
bool hasError(int msecs=FutureTimeout_Infinite) const