7 #ifndef _QI_DETAIL_FUTURE_HXX_
8 #define _QI_DETAIL_FUTURE_HXX_
12 #include <boost/bind.hpp>
22 template <
typename R,
typename F>
26 std::is_convertible<
typename std::result_of<F()>::type, R>::value,
27 "function return type is incompatible with promise");
38 template <
typename R,
typename F>
45 catch (std::exception& e)
57 template <
typename R,
typename AF>
60 return thenRImpl<R>(type, std::forward<AF>(func));
64 template <
typename R,
typename F>
67 boost::weak_ptr<detail::FutureBaseTyped<T> > weakp(_p);
69 if (
auto futureb = weakp.lock())
77 auto adaptedContinuation = [promise, continuation](
const Future<T>& future)
mutable
80 promise, [&continuation, &future]()
mutable {
return continuation(future); });
83 _p->connect(*
this, adaptedContinuation, callbackType);
84 return promise.future();
88 template <
typename R,
typename AF>
91 return andThenRImpl<R>(type, std::forward(func));
95 template <
typename R,
typename F>
98 boost::weak_ptr<detail::FutureBaseTyped<T> > weakp(_p);
100 if (
auto futureb = weakp.lock())
108 auto adaptedContinuation = [promise, continuation](
const Future<T>& future)
mutable
110 if (future.isCanceled())
111 promise.setCanceled();
112 else if (future.hasError())
113 promise.setError(future.error());
114 else if (promise.isCancelRequested())
115 promise.setCanceled();
118 promise, [&continuation, &future]()
mutable {
return continuation(future.value()); });
121 _p->connect(*
this, adaptedContinuation, callbackType);
122 return promise.future();
125 template <
typename T>
127 const boost::function<
void(
const Future<T>&)>& cb)
129 connectWithStrand(*strand, cb);
132 template <
typename T>
134 const boost::function<
void(
const Future<T>&)>& cb)
142 template <
typename T>
152 template <
typename T>
160 template <
typename T>
167 template <
typename T>
170 boost::recursive_mutex::scoped_lock lock(mutex());
172 _onDestroyed(_value);
175 template <
typename T>
180 boost::recursive_mutex::scoped_lock lock(mutex());
193 template <
typename T>
196 bool doCancel =
false;
198 boost::recursive_mutex::scoped_lock lock(mutex());
199 _onCancel = onCancel;
200 doCancel = isCancelRequested();
207 template <
typename T>
210 for (
const auto& callback : callbacks)
212 const bool async = [&]{
224 callback.callback(future);
229 catch (
const std::exception& e)
231 qiLogError(
"qi.future") <<
"Exception caught in future callback " << e.what();
235 qiLogError(
"qi.future") <<
"Unknown exception caught in future callback";
240 template <
typename T>
241 template <
typename F>
242 void FutureBaseTyped<T>::finish(
qi::Future<T>& future, F&& finishTask)
250 boost::recursive_mutex::scoped_lock lock(mutex());
256 onResult = takeOutResultCallbacks();
257 clearCancelCallback();
263 executeCallbacks(async, onResult, future);
266 template <
typename T>
269 finish(future, [
this, &value] {
275 template <
typename T>
278 finish(future, [
this] {
283 template <
typename T>
286 finish(future, [
this, &message] {
287 reportError(message);
291 template <
typename T>
294 finish(future, [
this] {
295 reportError(
"Promise broken (all promises are destroyed)");
299 template <
typename T>
302 finish(future, [
this] {
307 template <
typename T>
310 boost::recursive_mutex::scoped_lock lock(mutex());
314 template <
typename T>
324 boost::recursive_mutex::scoped_lock lock(mutex());
325 ready = isFinished();
327 _onResult.push_back(Callback(callback, type));
333 const bool async = [&]{
341 if (async && soCalledEventLoop)
343 soCalledEventLoop->post(
boost::bind(callback, future));
351 catch (const ::qi::PointerLockException&)
358 template <
typename T>
373 template <
typename T>
378 swap(onResult, _onResult);
382 template <
typename T>
383 void FutureBaseTyped<T>::clearCancelCallback()
388 template <
typename T>
392 if (!prom.future().isFinished() && !fut.
hasError())
406 if (!prom.future().isFinished())
412 prom.setValue(makeFutureError<T>(
"No future returned successfully."));
421 template <
typename T>
436 return promise.future();
452 const boost::weak_ptr<FutureBaseTyped<
Future<T> > >& wfuture)
454 if (boost::shared_ptr<FutureBaseTyped<
Future<T> > > fbt =
465 template <
typename T>
474 template<
typename FT,
typename PT,
typename CONV>
486 catch (
const std::exception& e)
488 p.
setError(std::string(
"futureAdapter conversion error: ") + e.what());
495 template<
typename FT>
511 template <
typename T>
519 template <
typename T>
536 template<
typename FT,
typename PT>
546 template<
typename FT,
typename PT,
typename CONV>
552 const_cast<Future<FT>&
>(f).connect(
boost::bind(detail::futureAdapter<FT, PT, CONV>, _1, p, converter));
555 template <
typename T>
567 return future.
andThen([](
void *) {
576 template <
typename T>
623 #endif // _QI_DETAIL_FUTURE_HXX_
void setError(qi::Future< T > &future, const std::string &message)
Future< AnyValue > toAnyValueFuture(Future< T > future)
when the promise is already set.
void setup(boost::function< void(qi::Promise< T > &)> cancelCallback, FutureCallbackType async=FutureCallbackType_Auto)
void connect(const AF &fun, FutureCallbackType type=FutureCallbackType_Auto)
FutureWrapper< T > & operator()()
The future has been canceled.
void futureAdapter(const Future< FT > &f, Promise< PT > p, CONV converter)
void operator()(const T &in, void *out)
void operator,(const T &val)
void operator()(void *in, void *out)
void setCanceled(qi::Future< T > &future)
The future has been canceled.
void setValue(qi::Future< T > &future, const ValueType &value)
void setError(const std::string &msg)
static AnyValue from(const T &r)
void set(qi::Future< T > &future)
boost::function< void()> makeCanceler()
Get a functor that will cancel the future.
Specialize this struct to provide conversion between future values.
FutureWrapper< void > & operator()()
qi::Future< T > makeFutureError(const std::string &error)
Helper function to return a future with the error set.
void connect(qi::Future< T > future, const boost::function< void(qi::Future< T >)> &callback, FutureCallbackType type)
void post(const boost::function< void()> &callback, uint64_t usDelay)
Similar to async() but without cancelation or notification.
Future< T > future() const
Get a future linked to this promise. Can be called multiple times.
Future< R > andThenR(FutureCallbackType type, AF &&func)
Same as thenR(), but the callback is called only if this future finishes with a value.
boost::shared_ptr< detail::FutureBaseTyped< T > > _p
#define qiLogError(...)
Log in error mode.
the future is not associated to a promise
const ValueType & value(int msecs) const
typename FutureType< T >::type ValueType
void setPromiseFromCallWithExceptionSupport(Promise< R > &p, F &&f)
qi::Future< void > future
Future is not tied to a promise.
void setPromiseFromCall(Promise< R > &p, F &&f)
void swap(::qi::AnyFunction &a,::qi::AnyFunction &b)
void setOnDestroyed(boost::function< void(ValueType)> f)
void operator,(const Future< void > &val)
auto async(F &&callback) -> decltype(asyncDelay(std::forward< F >(callback), qi::Duration(0)))
typename detail::FutureType< T >::type ValueType
EventLoop * getEventLoop()
Returns the global eventloop, created on demand on first call.
The operation is finished with an error.
Future< R > thenR(FutureCallbackType type, AF &&func)
Execute a callback when the future is finished.
void waitForFirstHelper(qi::Promise< qi::Future< T > > &prom, qi::Future< T > &fut, qi::Atomic< int > *count)
auto andThen(FutureCallbackType type, F &&func) -> Future< typename std::decay< typename std::result_of< F(ValueType)>::type >::type >
Same as then(), but the callback is called only if this future finishes with a value.
auto schedulerFor(F &&func, boost::function< void()> onFail={}, ExecutionOptions options=defaultExecutionOptions()) -> detail::Stranded< typename std::decay< F >::type >
boost::function< void(Promise< T > &)> CancelCallback
void cancel(qi::Future< T > &future)
void futureCancelAdapter(boost::weak_ptr< FutureBaseTyped< FT > > wf)
void operator,(const Future< T > &val)
const std::string & error(int msecs=FutureTimeout_Infinite) const
const ValueType & value(int msecs=FutureTimeout_Infinite) const
Return the value associated to a Future.
void setBroken(qi::Future< T > &future)
void setValue(const ValueType &value)
void setOnCancel(const qi::Promise< T > &promise, CancelCallback onCancel)
void adaptFuture(const Future< FT > &f, Promise< PT > &p, AdaptFutureOption option)
Feed a promise from a future of possibly different type.
void connectWithStrand(qi::Strand *strand, const boost::function< void(const Future< T > &)> &cb)
The operation is finished with a value.
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)
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