libqi-api
2.1.0.18
|
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_