libqi-api  2.1.0.18
/home/opennao/work/master/sdk/libqi/qi/future.hpp
Go to the documentation of this file.
00001 #pragma once
00002 /*
00003 **  Copyright (C) 2012 Aldebaran Robotics
00004 **  See COPYING for the license
00005 */
00006 
00007 #ifndef _QI_FUTURE_HPP_
00008 #define _QI_FUTURE_HPP_
00009 
00010 #include <qi/api.hpp>
00011 #include <vector>
00012 #include <qi/atomic.hpp>
00013 #include <qi/config.hpp>
00014 #include <qi/trackable.hpp>
00015 
00016 #include <boost/shared_ptr.hpp>
00017 #include <boost/make_shared.hpp>
00018 #include <boost/function.hpp>
00019 #include <boost/bind.hpp>
00020 #include <boost/thread/recursive_mutex.hpp>
00021 
00022 #ifdef _MSC_VER
00023 #  pragma warning( push )
00024 #  pragma warning( disable: 4251 )
00025 #  pragma warning( disable: 4275 ) //std::runtime_error: no dll interface
00026 #endif
00027 
00028 namespace qi {
00029 
00030   template<typename T>
00031   struct FutureType
00032   {
00033     typedef T type;
00034     typedef T typecast;
00035   };
00036 
00037   struct FutureHasNoValue {};
00038   // Hold a void* for Future<void>
00039   template<>
00040   struct FutureType<void>
00041   {
00042     typedef void* type;
00043     typedef FutureHasNoValue typecast;
00044   };
00045 
00046   template <typename T> class FutureInterface;
00047   template <typename T> class Future;
00048   template <typename T> class FutureSync;
00049   template <typename T> class Promise;
00050 
00051   namespace detail {
00052     template <typename T> class FutureBaseTyped;
00053 
00054     template<typename FT>
00055     void futureCancelAdapter(
00056         boost::weak_ptr<detail::FutureBaseTyped<FT> > wf);
00057   }
00058 
00061   enum FutureState {
00062     FutureState_None,               
00063     FutureState_Running,            
00064     FutureState_Canceled,           
00065     FutureState_FinishedWithError,  
00066     FutureState_FinishedWithValue,  
00067   };
00068 
00069   enum FutureCallbackType {
00070     FutureCallbackType_Sync  = 0,
00071     FutureCallbackType_Async = 1
00072   };
00073 
00074   enum FutureTimeout {
00075     FutureTimeout_Infinite = ((int) 0x7fffffff),
00076     FutureTimeout_None     = 0,
00077   };
00078 
00081   class QI_API FutureException : public std::runtime_error {
00082   public:
00083     enum ExceptionState {
00084       //No result ready
00085       ExceptionState_FutureTimeout,
00086       //The future has been canceled
00087       ExceptionState_FutureCanceled,
00088       //The future is not cancelable
00089       ExceptionState_FutureNotCancelable,
00090       //asked for error, but there is no error
00091       ExceptionState_FutureHasNoError,
00092       //real future error
00093       ExceptionState_FutureUserError,
00094       //when the promise is already set.
00095       ExceptionState_PromiseAlreadySet,
00096     };
00097 
00098     explicit FutureException(const ExceptionState &es, const std::string &str = std::string())
00099       : std::runtime_error(stateToString(es) + str)
00100       , _state(es)
00101     {}
00102 
00103     inline ExceptionState state() const { return _state; }
00104 
00105     std::string stateToString(const ExceptionState &es);
00106 
00107     virtual ~FutureException() throw()
00108     {}
00109 
00110   private:
00111     ExceptionState _state;
00112   };
00113 
00117   class QI_API FutureUserException : public FutureException {
00118   public:
00119 
00120     explicit FutureUserException(const std::string &str = std::string())
00121       : FutureException(ExceptionState_FutureUserError, str)
00122     {}
00123 
00124     virtual ~FutureUserException() throw()
00125     {}
00126   };
00127 
00128   template <typename T>
00129   class Future {
00130   public:
00131     typedef typename FutureType<T>::type     ValueType;
00132     typedef typename FutureType<T>::typecast ValueTypeCast;
00133 
00134   public:
00135     Future()
00136       : _p(boost::make_shared<detail::FutureBaseTyped<T> >())
00137     {
00138     }
00139 
00140     Future(const Future<T>& b)
00141     : _p(b._p)
00142     {}
00143 
00144     bool operator==(const Future<T> &other)
00145     {
00146       return _p.get() == other._p.get();
00147     }
00148 
00149     inline Future<T>& operator=(const Future<T>& b)
00150     {
00151       _p = b._p;
00152       return *this;
00153     }
00154 
00155     bool operator < (const Future<T>& b) const
00156     {
00157       return _p.get() < b._p.get();
00158     }
00159     explicit Future<T>(const ValueType& v, FutureCallbackType async = FutureCallbackType_Async)
00160     {
00161       Promise<T> promise(async);
00162       promise.setValue(v);
00163       *this = promise.future();
00164     }
00165 
00178     inline const ValueType &value(int msecs = FutureTimeout_Infinite) const { return _p->value(msecs); }
00179 
00182     inline operator const ValueTypeCast&() const { return _p->value(FutureTimeout_Infinite); }
00183 
00188     inline FutureState wait(int msecs = FutureTimeout_Infinite) const          { return _p->wait(msecs); }
00189 
00195     inline bool isFinished() const                                             { return _p->isFinished(); }
00196 
00202     inline bool isRunning() const                                              { return _p->isRunning(); }
00203 
00209     inline bool isCanceled() const                                             { return _p->isCanceled(); }
00210 
00218     inline bool hasError(int msecs = FutureTimeout_Infinite) const             { return _p->hasError(msecs); }
00227     inline bool hasValue(int msecs = FutureTimeout_Infinite) const             { return _p->hasValue(msecs); }
00228 
00236     inline const std::string &error(int msecs = FutureTimeout_Infinite) const  { return _p->error(msecs); }
00237 
00238 
00239     inline FutureSync<T> sync()
00240     {
00241       return FutureSync<T>(*this);
00242     };
00243 
00250     void cancel()
00251     {
00252       _p->cancel(*this);
00253     }
00254 
00257     bool isCancelable() const
00258     {
00259       return _p->isCancelable();
00260     }
00261   public: //Signals
00262     typedef boost::function<void (Future<T>) > Connection;
00263 
00270     template<typename AF>
00271     inline void connect(const AF& fun,
00272         FutureCallbackType type = FutureCallbackType_Async)
00273     {
00274       _p->connect(*this, fun, type);
00275     }
00276 #ifdef DOXYGEN
00277 
00283     template<typename FUNCTYPE, typename ARG0>
00284     void connect(FUNCTYPE fun, ARG0 tracked, ...,
00285         FutureCallbackType type = FutureCallbackType_Async);
00286 #else
00287 #define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma)                   \
00288     template<typename AF, typename ARG0 comma ATYPEDECL>                    \
00289     inline void connect(const AF& fun, const ARG0& arg0 comma ADECL,        \
00290         FutureCallbackType type = FutureCallbackType_Async)                 \
00291     {                                                                       \
00292       _p->connect(*this, ::qi::bind<void(Future<T>)>(fun, arg0 comma AUSE), \
00293           type);                                                            \
00294     }
00295     QI_GEN(genCall)
00296 #undef genCall
00297 #endif
00298 
00299     // Our companion library libqitype requires a connect with same signature for all instantiations
00300     inline void _connect(const boost::function<void()>& s) { connect(boost::bind(s));}
00301 
00302     boost::shared_ptr<detail::FutureBaseTyped<T> > impl() { return _p;}
00303     Future(boost::shared_ptr<detail::FutureBaseTyped<T> > p) :
00304       _p(p)
00305     {
00306       assert(_p);
00307     }
00308   protected:
00309     // C4251 needs to have dll-interface to be used by clients of class 'qi::Future<T>'
00310     boost::shared_ptr< detail::FutureBaseTyped<T> > _p;
00311     friend class Promise<T>;
00312     friend class FutureSync<T>;
00313 
00314     template<typename FT, typename PT>
00315     friend void adaptFuture(const Future<FT>& f, Promise<PT>& p);
00316     template<typename FT, typename PT, typename CONV>
00317     friend void adaptFuture(const Future<FT>& f, Promise<PT>& p,
00318         CONV converter);
00319     template<typename FT>
00320     friend void detail::futureCancelAdapter(
00321         boost::weak_ptr<detail::FutureBaseTyped<FT> > wf);
00322   };
00323 
00324 
00325 
00329   template<typename T>
00330   class FutureSync
00331   {
00332   public:
00333     typedef typename Future<T>::ValueType ValueType;
00334     typedef typename Future<T>::ValueTypeCast ValueTypeCast;
00335     typedef typename Future<T>::Connection Connection;
00336     // This future cannot be set, so sync starts at false
00337     FutureSync() : _sync(false) {}
00338 
00339     FutureSync(const Future<T>& b)
00340     : _sync(true)
00341     {
00342       _future = b;
00343     }
00344 
00345     FutureSync(const FutureSync<T>& b)
00346     : _sync(true)
00347     {
00348       _future = b._future;
00349       b._sync = false;
00350     }
00351 
00352     explicit FutureSync<T>(const ValueType& v)
00353     : _sync(false)
00354     {
00355       Promise<T> promise;
00356       promise.setValue(v);
00357       _future = promise.future();
00358     }
00359 
00360     inline FutureSync<T>& operator=(const FutureSync<T>& b)
00361     {
00362       _future = b;
00363       _sync = true;
00364       b._sync = false;
00365       return *this;
00366     }
00367 
00368     inline FutureSync<T>& operator=(const Future<T>& b)
00369     {
00370       _future = b;
00371       _sync = true;
00372       return *this;
00373     }
00374 
00375     ~FutureSync()
00376     {
00377       if (_sync)
00378         _future.value();
00379     }
00380 
00381     operator Future<T>()
00382     {
00383       return async();
00384     }
00385 
00386     bool operator < (const FutureSync<T>& b) const
00387     {
00388       return _future._p.get() < b._future._p.get();
00389     }
00390 
00391     const ValueType &value(int msecs = FutureTimeout_Infinite) const   { _sync = false; return _future.value(msecs); }
00392     operator const typename Future<T>::ValueTypeCast&() const          { _sync = false; return _future.value(); }
00393     FutureState wait(int msecs = FutureTimeout_Infinite) const         { _sync = false; return _future.wait(msecs); }
00394     bool isRunning() const                                             { _sync = false; return _future.isRunning(); }
00395     bool isFinished() const                                            { _sync = false; return _future.isFinished(); }
00396     bool isCanceled() const                                            { _sync = false; return _future.isCanceled(); }
00397     bool hasError(int msecs = FutureTimeout_Infinite) const            { _sync = false; return _future.hasError(msecs); }
00398     bool hasValue(int msecs = FutureTimeout_Infinite) const            { _sync = false; return _future.hasValue(msecs); }
00399     const std::string &error(int msecs = FutureTimeout_Infinite) const { _sync = false; return _future.error(msecs); }
00400     void cancel()                                                      { _sync = false; _future.cancel(); }
00401     bool isCancelable() const                                          { _sync = false; return _future.isCancelable(); }
00402     void connect(const Connection& s)                                  { _sync = false; _future.connect(s);}
00403     void _connect(const boost::function<void()>& s)                    { _sync = false; _future._connect(s);}
00404 
00405 #ifdef DOXYGEN
00406 
00412     template<typename FUNCTYPE, typename ARG0>
00413     void connect(FUNCTYPE fun, ARG0 tracked, ...);
00414 #else
00415 #define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma)                \
00416     template<typename AF, typename ARG0 comma ATYPEDECL>                 \
00417     inline void connect(const AF& fun, const ARG0& arg0 comma ADECL)     \
00418     {                                                                    \
00419       _sync = false;                                                     \
00420       connect(::qi::bind<void(FutureSync<T>)>(fun, arg0 comma AUSE));    \
00421     }
00422     QI_GEN(genCall)
00423 #undef genCall
00424 #endif
00425 
00426     Future<T> async()
00427     {
00428       _sync = false;
00429       return _future;
00430     }
00431 
00432   protected:
00433     mutable bool _sync;
00434     Future<T> _future;
00435     friend class Future<T>;
00436   };
00437 
00438 
00441   template <typename T>
00442   class Promise {
00443   public:
00444     typedef typename FutureType<T>::type ValueType;
00445 
00451     explicit Promise(FutureCallbackType async = FutureCallbackType_Async) {
00452       _f._p->reportStart();
00453       _f._p->_async = async;
00454     }
00455 
00461     explicit Promise(boost::function<void (qi::Promise<T>)> cancelCallback, FutureCallbackType async = FutureCallbackType_Async)
00462     {
00463       setup(cancelCallback, async);
00464     }
00465 
00469     void setValue(const ValueType &value) {
00470       _f._p->setValue(_f, value);
00471     }
00472 
00476     void setError(const std::string &msg) {
00477       _f._p->setError(_f, msg);
00478     }
00479 
00483     void setCanceled() {
00484       _f._p->setCanceled(_f);
00485     }
00486 
00487     /* reset the promise and the future */
00488     void reset() {
00489       _f._p->reset();
00490     }
00491 
00493     Future<T> future() const { return _f; }
00494 
00498     ValueType& value() { return _f._p->_value;}
00501     void trigger() { _f._p->set(_f);}
00502   protected:
00503     void setup(boost::function<void (qi::Promise<T>)> cancelCallback, FutureCallbackType async = FutureCallbackType_Async)
00504     {
00505       this->_f._p->reportStart();
00506       this->_f._p->setOnCancel(cancelCallback);
00507       this->_f._p->_async = async;
00508     }
00509     explicit Promise(Future<T>& f) : _f(f) {}
00510     template<typename> friend class ::qi::detail::FutureBaseTyped;
00511     Future<T> _f;
00512 
00513     template<typename FT, typename PT>
00514     friend void adaptFuture(const Future<FT>& f, Promise<PT>& p);
00515     template<typename FT, typename PT, typename CONV>
00516     friend void adaptFuture(const Future<FT>& f, Promise<PT>& p,
00517         CONV converter);
00518   };
00519 
00520   template<typename T>
00521   class FutureBarrier {
00522   public:
00524     FutureBarrier(FutureCallbackType async = FutureCallbackType_Async)
00525       : _closed(false)
00526       , _count(0)
00527       , _futures()
00528       , _promise(async)
00529     {}
00530 
00532     bool addFuture(qi::Future<T> fut) {
00533       // Can't add future from closed qi::FutureBarrier.
00534       if (this->_closed)
00535         return false;
00536 
00537       ++(this->_count);
00538       fut.connect(boost::bind<void>(&FutureBarrier::onFutureFinish, this));
00539       this->_futures.push_back(fut);
00540       return true;
00541     }
00542 
00544     Future< std::vector< Future<T> > > future() {
00545       this->close();
00546       return this->_promise.future();
00547     }
00548 
00549   protected:
00550     bool _closed;
00551     Atomic<int> _count;
00552     std::vector< Future<T> > _futures;
00553     Promise< std::vector< Future<T> > > _promise;
00554 
00555   private:
00556     void onFutureFinish() {
00557       if (--(this->_count) == 0 && this->_closed) {
00558         this->_promise.setValue(this->_futures);
00559       }
00560     }
00561 
00562     void close() {
00563       this->_closed = true;
00564       if (*(this->_count) == 0) {
00565         this->_promise.setValue(this->_futures);
00566       }
00567     }
00568   };
00569 
00570   template <typename T>
00571   qi::Future<T> makeFutureError(const std::string &value, FutureCallbackType async = FutureCallbackType_Async);
00572 
00574   template <typename T>
00575   void waitForAll(std::vector< Future<T> >& vect);
00576 
00578   template <typename T>
00579   qi::FutureSync< qi::Future<T> > waitForFirst(std::vector< Future<T> >& vect);
00580 
00582   template<typename FT, typename PT>
00583   struct FutureValueConverter
00584   {
00585     void operator()(const FT& vIn, PT& vOut) { vOut = vIn;}
00586   };
00587 
00593   template<typename FT, typename PT>
00594   void adaptFuture(const Future<FT>& f, Promise<PT>& p);
00595 
00597   template<typename FT, typename PT, typename CONV>
00598   void adaptFuture(const Future<FT>& f, Promise<PT>& p, CONV converter);
00599 }
00600 
00601 #ifdef _MSC_VER
00602 #  pragma warning( pop )
00603 #endif
00604 
00605 #include <qi/details/future.hxx>
00606 
00607 #endif  // _QI_FUTURE_HPP_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines