libqi-api  2.0.6.8
/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;
00267     inline void connect(const Connection& s) { _p->connect(*this, s);}
00268 
00269 #ifdef DOXYGEN
00270 
00276     template<typename FUNCTYPE, typename ARG0>
00277     void connect(FUNCTYPE fun, ARG0 tracked, ...);
00278 #else
00279 #define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma) \
00280     template<typename AF, typename ARG0 comma ATYPEDECL>      \
00281     inline void connect(const AF& fun, const ARG0& arg0 comma ADECL)  \
00282     {                                                                    \
00283       connect(::qi::bind<void(Future<T>)>(fun, arg0 comma AUSE));    \
00284     }
00285     QI_GEN(genCall)
00286 #undef genCall
00287 #endif
00288 
00289     // Our companion library libqitype requires a connect with same signature for all instantiations
00290     inline void _connect(const boost::function<void()>& s) { connect(boost::bind(s));}
00291 
00292     boost::shared_ptr<detail::FutureBaseTyped<T> > impl() { return _p;}
00293     Future(boost::shared_ptr<detail::FutureBaseTyped<T> > p) :
00294       _p(p)
00295     {
00296       assert(_p);
00297     }
00298   protected:
00299     // C4251 needs to have dll-interface to be used by clients of class 'qi::Future<T>'
00300     boost::shared_ptr< detail::FutureBaseTyped<T> > _p;
00301     friend class Promise<T>;
00302     friend class FutureSync<T>;
00303 
00304     template<typename FT, typename PT>
00305     friend void adaptFuture(const Future<FT>& f, Promise<PT>& p);
00306     template<typename FT, typename PT, typename CONV>
00307     friend void adaptFuture(const Future<FT>& f, Promise<PT>& p,
00308         CONV converter);
00309     template<typename FT>
00310     friend void detail::futureCancelAdapter(
00311         boost::weak_ptr<detail::FutureBaseTyped<FT> > wf);
00312   };
00313 
00314 
00315 
00319   template<typename T>
00320   class FutureSync
00321   {
00322   public:
00323     typedef typename Future<T>::ValueType ValueType;
00324     typedef typename Future<T>::ValueTypeCast ValueTypeCast;
00325     typedef typename Future<T>::Connection Connection;
00326     // This future cannot be set, so sync starts at false
00327     FutureSync() : _sync(false) {}
00328 
00329     FutureSync(const Future<T>& b)
00330     : _sync(true)
00331     {
00332       _future = b;
00333     }
00334 
00335     FutureSync(const FutureSync<T>& b)
00336     : _sync(true)
00337     {
00338       _future = b._future;
00339       b._sync = false;
00340     }
00341 
00342     explicit FutureSync<T>(const ValueType& v)
00343     : _sync(false)
00344     {
00345       Promise<T> promise;
00346       promise.setValue(v);
00347       _future = promise.future();
00348     }
00349 
00350     inline FutureSync<T>& operator=(const FutureSync<T>& b)
00351     {
00352       _future = b;
00353       _sync = true;
00354       b._sync = false;
00355       return *this;
00356     }
00357 
00358     inline FutureSync<T>& operator=(const Future<T>& b)
00359     {
00360       _future = b;
00361       _sync = true;
00362       return *this;
00363     }
00364 
00365     ~FutureSync()
00366     {
00367       if (_sync)
00368         _future.value();
00369     }
00370 
00371     operator Future<T>()
00372     {
00373       return async();
00374     }
00375 
00376     bool operator < (const FutureSync<T>& b) const
00377     {
00378       return _future._p.get() < b._future._p.get();
00379     }
00380 
00381     const ValueType &value(int msecs = FutureTimeout_Infinite) const   { _sync = false; return _future.value(msecs); }
00382     operator const typename Future<T>::ValueTypeCast&() const          { _sync = false; return _future.value(); }
00383     FutureState wait(int msecs = FutureTimeout_Infinite) const         { _sync = false; return _future.wait(msecs); }
00384     bool isRunning() const                                             { _sync = false; return _future.isRunning(); }
00385     bool isFinished() const                                            { _sync = false; return _future.isFinished(); }
00386     bool isCanceled() const                                            { _sync = false; return _future.isCanceled(); }
00387     bool hasError(int msecs = FutureTimeout_Infinite) const            { _sync = false; return _future.hasError(msecs); }
00388     bool hasValue(int msecs = FutureTimeout_Infinite) const            { _sync = false; return _future.hasValue(msecs); }
00389     const std::string &error(int msecs = FutureTimeout_Infinite) const { _sync = false; return _future.error(msecs); }
00390     void cancel()                                                      { _sync = false; _future.cancel(); }
00391     bool isCancelable() const                                          { _sync = false; return _future.isCancelable(); }
00392     void connect(const Connection& s)                                  { _sync = false; _future.connect(s);}
00393     void _connect(const boost::function<void()>& s)                    { _sync = false; _future._connect(s);}
00394 
00395 #ifdef DOXYGEN
00396 
00402     template<typename FUNCTYPE, typename ARG0>
00403     void connect(FUNCTYPE fun, ARG0 tracked, ...);
00404 #else
00405 #define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma)                \
00406     template<typename AF, typename ARG0 comma ATYPEDECL>                 \
00407     inline void connect(const AF& fun, const ARG0& arg0 comma ADECL)     \
00408     {                                                                    \
00409       _sync = false;                                                     \
00410       connect(::qi::bind<void(FutureSync<T>)>(fun, arg0 comma AUSE));    \
00411     }
00412     QI_GEN(genCall)
00413 #undef genCall
00414 #endif
00415 
00416     Future<T> async()
00417     {
00418       _sync = false;
00419       return _future;
00420     }
00421 
00422   protected:
00423     mutable bool _sync;
00424     Future<T> _future;
00425     friend class Future<T>;
00426   };
00427 
00428 
00431   template <typename T>
00432   class Promise {
00433   public:
00434     typedef typename FutureType<T>::type ValueType;
00435 
00441     explicit Promise(FutureCallbackType async = FutureCallbackType_Async) {
00442       _f._p->reportStart();
00443       _f._p->_async = async;
00444     }
00445 
00451     explicit Promise(boost::function<void (qi::Promise<T>)> cancelCallback, FutureCallbackType async = FutureCallbackType_Async)
00452     {
00453       setup(cancelCallback, async);
00454     }
00455 
00459     void setValue(const ValueType &value) {
00460       _f._p->setValue(_f, value);
00461     }
00462 
00466     void setError(const std::string &msg) {
00467       _f._p->setError(_f, msg);
00468     }
00469 
00473     void setCanceled() {
00474       _f._p->setCanceled(_f);
00475     }
00476 
00477     /* reset the promise and the future */
00478     void reset() {
00479       _f._p->reset();
00480     }
00481 
00483     Future<T> future() const { return _f; }
00484 
00488     ValueType& value() { return _f._p->_value;}
00491     void trigger() { _f._p->set(_f);}
00492   protected:
00493     void setup(boost::function<void (qi::Promise<T>)> cancelCallback, FutureCallbackType async = FutureCallbackType_Async)
00494     {
00495       this->_f._p->reportStart();
00496       this->_f._p->setOnCancel(cancelCallback);
00497       this->_f._p->_async = async;
00498     }
00499     explicit Promise(Future<T>& f) : _f(f) {}
00500     template<typename> friend class ::qi::detail::FutureBaseTyped;
00501     Future<T> _f;
00502 
00503     template<typename FT, typename PT>
00504     friend void adaptFuture(const Future<FT>& f, Promise<PT>& p);
00505     template<typename FT, typename PT, typename CONV>
00506     friend void adaptFuture(const Future<FT>& f, Promise<PT>& p,
00507         CONV converter);
00508   };
00509 
00510   template<typename T>
00511   class FutureBarrier {
00512   public:
00514     FutureBarrier(FutureCallbackType async = FutureCallbackType_Async)
00515       : _closed(false)
00516       , _count(0)
00517       , _futures()
00518       , _promise(async)
00519     {}
00520 
00522     bool addFuture(qi::Future<T> fut) {
00523       // Can't add future from closed qi::FutureBarrier.
00524       if (this->_closed)
00525         return false;
00526 
00527       ++(this->_count);
00528       fut.connect(boost::bind<void>(&FutureBarrier::onFutureFinish, this));
00529       this->_futures.push_back(fut);
00530       return true;
00531     }
00532 
00534     Future< std::vector< Future<T> > > future() {
00535       this->close();
00536       return this->_promise.future();
00537     }
00538 
00539   protected:
00540     bool _closed;
00541     Atomic<int> _count;
00542     std::vector< Future<T> > _futures;
00543     Promise< std::vector< Future<T> > > _promise;
00544 
00545   private:
00546     void onFutureFinish() {
00547       if (--(this->_count) == 0 && this->_closed) {
00548         this->_promise.setValue(this->_futures);
00549       }
00550     }
00551 
00552     void close() {
00553       this->_closed = true;
00554       if (*(this->_count) == 0) {
00555         this->_promise.setValue(this->_futures);
00556       }
00557     }
00558   };
00559 
00560   template <typename T>
00561   qi::Future<T> makeFutureError(const std::string &value, FutureCallbackType async = FutureCallbackType_Async);
00562 
00564   template <typename T>
00565   void waitForAll(std::vector< Future<T> >& vect);
00566 
00568   template <typename T>
00569   qi::FutureSync< qi::Future<T> > waitForFirst(std::vector< Future<T> >& vect);
00570 
00572   template<typename FT, typename PT>
00573   struct FutureValueConverter
00574   {
00575     void operator()(const FT& vIn, PT& vOut) { vOut = vIn;}
00576   };
00577 
00583   template<typename FT, typename PT>
00584   void adaptFuture(const Future<FT>& f, Promise<PT>& p);
00585 
00587   template<typename FT, typename PT, typename CONV>
00588   void adaptFuture(const Future<FT>& f, Promise<PT>& p, CONV converter);
00589 }
00590 
00591 #ifdef _MSC_VER
00592 #  pragma warning( pop )
00593 #endif
00594 
00595 #include <qi/details/future.hxx>
00596 
00597 #endif  // _QI_FUTURE_HPP_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines