7 #ifndef _QI_FUTURE_HPP_
8 # define _QI_FUTURE_HPP_
10 # include <type_traits>
15 # include <qi/config.hpp>
20 # include <boost/shared_ptr.hpp>
21 # include <boost/make_shared.hpp>
22 # include <boost/function.hpp>
23 # include <boost/bind.hpp>
24 # include <boost/thread/recursive_mutex.hpp>
27 # pragma warning( push )
28 # pragma warning( disable: 4251 )
29 # pragma warning( disable: 4275 ) //std::runtime_error: no dll interface
62 template <
typename T>
class Future;
115 : std::runtime_error(stateToString(es) + str)
121 std::string stateToString(
const ExceptionState &es);
127 ExceptionState _state;
148 template <
typename T>
149 class Future :
public detail::AddUnwrap<T> {
150 static_assert(!std::is_const<T>::value,
"can't create a future of const");
158 :
_p(boost::make_shared<detail::FutureBaseTyped<T> >())
168 return _p.get() == other._p.get();
177 bool operator < (const Future<T>& b)
const
179 return _p.get() < b._p.get();
215 {
return _p->value(msecs); }
227 {
return _p->wait(msecs); }
234 {
return _p->wait(duration); }
237 {
return this->
wait(duration); }
244 {
return _p->wait(timepoint); }
247 {
return this->
wait(timepoint); }
254 {
return _p->isFinished(); }
261 {
return _p->isRunning(); }
270 {
return _p->isCanceled(); }
279 {
return _p->hasError(msecs); }
289 {
return _p->hasValue(msecs); }
298 {
return _p->error(msecs); }
343 template <
typename R,
typename AF>
352 template <
typename R,
typename AF>
362 template <
typename R,
typename AF,
typename Arg0,
typename... Args>
368 qi::bind(std::forward<AF>(func), std::forward<Arg0>(arg0), std::forward<Args>(args)...));
374 template <
typename R,
typename AF,
typename Arg0,
typename... Args>
380 qi::bind(std::forward<AF>(func), arg0, std::forward<Args>(args)...));
393 template <
typename AF>
397 return thenRImpl<typename detail::DecayAsyncResult<AF, qi::Future<T>>::type>(type, std::forward<AF>(func));
403 template <
typename AF>
420 template <
typename R,
typename AF>
429 template <
typename R,
typename AF>
444 template <
typename AF>
448 return this->andThenRImpl<typename detail::DecayAsyncResult<AF, ValueType>::type>(type, std::forward<AF>(func));
454 template <
typename AF>
483 template<
typename AF>
487 _p->connect(*
this, fun, type);
496 template<
typename FUNCTYPE,
typename ARG0>
497 void connect(FUNCTYPE fun, ARG0 tracked, ...,
500 #define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma) \
501 template <typename AF, typename ARG0 comma ATYPEDECL> \
502 inline void connect(const AF& fun, const ARG0& arg0 comma ADECL, \
503 FutureCallbackType type = FutureCallbackType_Auto) \
505 this->then(type, qi::bind(fun, arg0 comma AUSE)); \
514 const boost::function<
void(
const Future<T>&)>& cb);
516 const boost::function<
void(
const Future<T>&)>& cb);
519 inline void _connect(
const boost::function<
void()>& s)
524 boost::shared_ptr<detail::FutureBaseTyped<T> >
impl() {
return _p;}
533 boost::shared_ptr< detail::FutureBaseTyped<T> >
_p;
539 template<
typename FT,
typename PT>
541 template<
typename FT,
typename PT,
typename CONV>
547 template<
typename FT>
555 template <
typename R,
typename AF>
559 template <
typename R,
typename AF>
563 void setOnDestroyed(boost::function<
void(
ValueType)> cb)
565 _p->setOnDestroyed(cb);
639 bool operator < (const FutureSync<T>& b)
const
641 return _future._p.get() < b._future._p.get();
675 template<
typename FUNCTYPE,
typename ARG0>
676 void connect(FUNCTYPE fun, ARG0 tracked, ...);
678 #define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma) \
679 template<typename AF, typename ARG0 comma ATYPEDECL> \
680 inline void connect(const AF& fun, const ARG0& arg0 comma ADECL) \
683 connect(::qi::bind<void(FutureSync<T>)>(fun, arg0 comma AUSE)); \
705 template <
typename T>
716 _f._p->reportStart();
718 ++
_f._p->_promiseCount;
726 template <
typename FUNC,
727 typename std::enable_if<!std::is_same<
728 typename std::decay<FUNC>::type,
729 typename std::decay<qi::Promise<T> >::type
735 setup(std::forward<FUNC>(cancelCallback),
async);
736 ++
_f._p->_promiseCount;
743 ++
_f._p->_promiseCount;
749 ++
_f._p->_promiseCount;
761 _f._p->setValue(
_f, value);
768 _f._p->setError(
_f, msg);
775 _f._p->setCanceled(
_f);
782 return _f._p->isCancelRequested();
805 this->
_f._p->setOnCancel(*
this, cancelCallback);
810 if (
_f._p == rhs.
_f._p)
815 ++
_f._p->_promiseCount;
822 this->
_f._p->reportStart();
823 this->
_f._p->setOnCancel(*
this, cancelCallback);
827 ++
_f._p->_promiseCount;
829 template<
typename>
friend class ::qi::detail::FutureBaseTyped;
834 template<
typename FT,
typename PT>
836 template<
typename FT,
typename PT,
typename CONV>
849 if (--
_f._p->_promiseCount == 0 &&
_f.isRunning())
850 _f._p->setBroken(
_f);
856 class FutureBasePrivate;
866 bool isRunning()
const;
867 bool isFinished()
const;
868 bool isCanceled()
const;
869 bool isCancelRequested()
const;
870 bool hasError(
int msecs)
const;
871 bool hasValue(
int msecs)
const;
872 const std::string &error(
int msecs)
const;
877 void reportError(
const std::string &message);
878 void requestCancel();
879 void reportCanceled();
880 boost::recursive_mutex& mutex();
884 FutureBasePrivate *
_p;
889 template <
typename T>
921 using CallbackType = boost::function<void(qi::Future<T>)>;
924 CallbackType callback;
932 using Callbacks = std::vector<Callback>;
936 boost::function<void (ValueType)> _onDestroyed;
940 void clearCallbacks();
948 template <
typename T>
952 template <
typename T>
958 template<
typename FT,
typename PT>
977 template<
typename FT,
typename PT>
981 void adaptFuture(Future<AnyReference>& f, Promise<R>& p);
984 template<
typename FT,
typename PT,
typename CONV>
985 void adaptFuture(
const Future<FT>& f, Promise<PT>& p, CONV converter,
989 template <
typename T>
992 return future.makeCanceler();
997 # pragma warning( pop )
1000 #endif // _QI_FUTURE_HPP_
asked for error, but there is no error
void setError(qi::Future< T > &future, const std::string &message)
when the promise is already set.
void operator()(const FT &vIn, PT &vOut)
void setup(boost::function< void(qi::Promise< T > &)> cancelCallback, FutureCallbackType async=FutureCallbackType_Auto)
void connect(const AF &fun, FutureCallbackType type=FutureCallbackType_Auto)
The future has been canceled.
friend void adaptFuture(const Future< FT > &f, Promise< PT > &p, AdaptFutureOption option)
Feed a promise from a future of possibly different type.
void PromiseNoop(qi::Promise< T > &)
Helper function that does nothing on future cancelation.
void setCanceled(qi::Future< T > &future)
void connect(const Connection &s)
typename Future< T >::Connection Connection
FutureState waitFor(qi::Duration duration) const
The future has been canceled.
auto andThen(FutureCallbackType type, AF &&func) -> qi::Future< typename detail::DecayAsyncResult< AF, ValueType >::type >
Same as then(), but the callback is called only if this future finishes with a value.
void _connect(const boost::function< void()> &s)
void setValue(qi::Future< T > &future, const ValueType &value)
friend 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...
TimePoint< SteadyClock > time_point
void setError(const std::string &msg)
FutureState wait(qi::Duration duration) const
void set(qi::Future< T > &future)
friend 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...
void callCbNotify(qi::Future< T > &future)
#define QI_ASSERT(expr__)
ExceptionState state() const
const ValueType & value(int msecs=FutureTimeout_Infinite) const
FutureUserException(const std::string &str=std::string())
FutureState wait(qi::SteadyClock::time_point timepoint) const
dll import/export and compiler message
FutureSync(const Future< T > &b)
boost::function< void()> makeCanceler()
Get a functor that will cancel the future.
typename Future< T >::ValueType ValueType
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.
void _connect(const boost::function< void()> &s)
const std::string & error(int msecs=FutureTimeout_Infinite) const
bool isCancelRequested() const
#define QI_NOEXCEPT(cond)
Specify that a function may throw or not.
typename detail::FutureType< void >::type ValueType
Future< T > future() const
Get a future linked to this promise. Can be called multiple times.
typename Future< T >::ValueTypeCast ValueTypeCast
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
virtual ~FutureUserException()
boost::function< void(Future< void >)> Connection
the future is not associated to a promise
const ValueType & value(int msecs) const
FutureState wait(qi::SteadyClock::time_point timepoint) const
Future< R > async(boost::function< R()> callback, uint64_t usDelay)
typename FutureType< T >::type ValueType
#define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma)
friend class ServiceBoundObject
Future is not tied to a promise.
boost::function< void()> makeCanceler(Future< T > &future)
#define QI_API_DEPRECATED_MSG(msg__)
Compiler flags to mark a function as deprecated. It will generate a compiler warning.
FutureState waitUntil(qi::SteadyClock::time_point timepoint) const
FutureException(const ExceptionState &es, const std::string &str=std::string())
void setOnDestroyed(boost::function< void(ValueType)> f)
~FutureSync() QI_NOEXCEPT(false)
Promise(FutureCallbackType async=FutureCallbackType_Auto)
bool operator==(const Future< T > &other) const
bool isCancelable() const
typename detail::FutureType< void >::type ValueType
Future(const Future< T > &b)
auto then(AF &&func) -> qi::Future< typename detail::DecayAsyncResult< AF, qi::Future< T >>::type >
Same as then(), but with type defaulted to FutureCallbackType_Auto.
void connect(qi::Future< T > future, const boost::function< void(qi::Future< T >)> &s, FutureCallbackType type)
FutureState wait(qi::Duration duration) const
auto then(FutureCallbackType type, AF &&func) -> qi::Future< typename detail::DecayAsyncResult< AF, qi::Future< T >>::type >
Execute a callback when the future is finished.
bool isCancelable() const
The operation is finished with an error.
Future< R > thenR(FutureCallbackType type, AF &&func)
Execute a callback when the future is finished.
FutureSync< T > & operator=(const Future< T > &b)
auto andThen(AF &&func) -> qi::Future< typename detail::DecayAsyncResult< AF, ValueType >::type >
Same as andThen(), but with type defaulted to FutureCallbackType_Auto.
FutureState waitFor(qi::Duration duration) const
boost::function< void(Promise< T > &)> CancelCallback
FutureState wait(int msecs=FutureTimeout_Infinite) const
virtual ~FutureException()
FutureState wait(int msecs=FutureTimeout_Infinite) const
void cancel(qi::Future< T > &future)
bool hasValue(int msecs=FutureTimeout_Infinite) const
void setOnCancel(boost::function< void(qi::Promise< T > &)> cancelCallback)
friend void adaptFuture(const Future< FT > &f, Promise< PT > &p, AdaptFutureOption option)
Feed a promise from a future of possibly different type.
void futureCancelAdapter(boost::weak_ptr< FutureBaseTyped< FT > > wf)
Promise(FUNC &&cancelCallback, FutureCallbackType async=FutureCallbackType_Auto)
const std::string & error(int msecs=FutureTimeout_Infinite) const
Promise< T > & operator=(const Promise< T > &rhs)
bool hasValue(int msecs=FutureTimeout_Infinite) const
const ValueType & value(int msecs=FutureTimeout_Infinite) const
Return the value associated to a Future.
FutureSync(const FutureSync< T > &b)
FutureUniqueId uniqueId() const
Promise(const qi::Promise< T > &rhs)
FutureUniqueId uniqueId() const
void setBroken(qi::Future< T > &future)
void setValue(const ValueType &value)
FutureSync< T > & operator=(const FutureSync< T > &b)
Promise(boost::function< void(qi::Promise< T >)> cancelCallback, FutureCallbackType async=FutureCallbackType_Auto)
Future< T > & operator=(const Future< T > &b)
void setOnCancel(qi::Promise< T > &promise, CancelCallback onCancel)
bool hasError(int msecs=FutureTimeout_Infinite) const
void adaptFuture(const Future< FT > &f, Promise< PT > &p, AdaptFutureOption option)
Feed a promise from a future of possibly different type.
boost::shared_ptr< detail::FutureBaseTyped< T > > impl()
FutureState waitUntil(qi::SteadyClock::time_point timepoint) const
void connectWithStrand(qi::Strand *strand, const boost::function< void(const Future< T > &)> &cb)
The operation is finished with a value.
typename detail::FutureType< void >::typecast ValueTypeCast
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)
Future(boost::shared_ptr< detail::FutureBaseTyped< T > > p)
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