libqi-api  2.1.4.13
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
future.hpp
Go to the documentation of this file.
1 #pragma once
2 /*
3 ** Copyright (C) 2012 Aldebaran Robotics
4 ** See COPYING for the license
5 */
6 
7 #ifndef _QI_FUTURE_HPP_
8 #define _QI_FUTURE_HPP_
9 
10 #include <qi/api.hpp>
11 #include <vector>
12 #include <qi/atomic.hpp>
13 #include <qi/config.hpp>
14 #include <qi/trackable.hpp>
15 
16 #include <boost/shared_ptr.hpp>
17 #include <boost/make_shared.hpp>
18 #include <boost/function.hpp>
19 #include <boost/bind.hpp>
20 #include <boost/thread/recursive_mutex.hpp>
21 
22 #ifdef _MSC_VER
23 # pragma warning( push )
24 # pragma warning( disable: 4251 )
25 # pragma warning( disable: 4275 ) //std::runtime_error: no dll interface
26 #endif
27 
28 namespace qi {
29 
30  template<typename T>
31  struct FutureType
32  {
33  typedef T type;
34  typedef T typecast;
35  };
36 
37  struct FutureHasNoValue {};
38  // Hold a void* for Future<void>
39  template<>
40  struct FutureType<void>
41  {
42  typedef void* type;
44  };
45 
46  template <typename T> class FutureInterface;
47  template <typename T> class Future;
48  template <typename T> class FutureSync;
49  template <typename T> class Promise;
50 
51  namespace detail {
52  template <typename T> class FutureBaseTyped;
53 
54  template<typename FT>
56  boost::weak_ptr<detail::FutureBaseTyped<FT> > wf);
57  }
58 
61  enum FutureState {
67  };
68 
72  };
73 
75  FutureTimeout_Infinite = ((int) 0x7fffffff),
77  };
78 
81  class QI_API FutureException : public std::runtime_error {
82  public:
84  //No result ready
86  //The future has been canceled
88  //The future is not cancelable
90  //asked for error, but there is no error
92  //real future error
94  //when the promise is already set.
96  };
97 
98  explicit FutureException(const ExceptionState &es, const std::string &str = std::string())
99  : std::runtime_error(stateToString(es) + str)
100  , _state(es)
101  {}
102 
103  inline ExceptionState state() const { return _state; }
104 
105  std::string stateToString(const ExceptionState &es);
106 
107  virtual ~FutureException() throw()
108  {}
109 
110  private:
111  ExceptionState _state;
112  };
113 
118  public:
119 
120  explicit FutureUserException(const std::string &str = std::string())
121  : FutureException(ExceptionState_FutureUserError, str)
122  {}
123 
124  virtual ~FutureUserException() throw()
125  {}
126  };
127 
128  template <typename T>
129  class Future {
130  public:
131  typedef typename FutureType<T>::type ValueType;
133 
134  public:
136  : _p(boost::make_shared<detail::FutureBaseTyped<T> >())
137  {
138  }
139 
140  Future(const Future<T>& b)
141  : _p(b._p)
142  {}
143 
144  bool operator==(const Future<T> &other)
145  {
146  return _p.get() == other._p.get();
147  }
148 
149  inline Future<T>& operator=(const Future<T>& b)
150  {
151  _p = b._p;
152  return *this;
153  }
154 
155  bool operator < (const Future<T>& b) const
156  {
157  return _p.get() < b._p.get();
158  }
160  {
161  Promise<T> promise(async);
162  promise.setValue(v);
163  *this = promise.future();
164  }
165 
178  inline const ValueType &value(int msecs = FutureTimeout_Infinite) const { return _p->value(msecs); }
179 
182  inline operator const ValueTypeCast&() const { return _p->value(FutureTimeout_Infinite); }
183 
188  inline FutureState wait(int msecs = FutureTimeout_Infinite) const { return _p->wait(msecs); }
189 
195  inline bool isFinished() const { return _p->isFinished(); }
196 
202  inline bool isRunning() const { return _p->isRunning(); }
203 
209  inline bool isCanceled() const { return _p->isCanceled(); }
210 
218  inline bool hasError(int msecs = FutureTimeout_Infinite) const { return _p->hasError(msecs); }
227  inline bool hasValue(int msecs = FutureTimeout_Infinite) const { return _p->hasValue(msecs); }
228 
236  inline const std::string &error(int msecs = FutureTimeout_Infinite) const { return _p->error(msecs); }
237 
238 
240  {
241  return FutureSync<T>(*this);
242  };
243 
250  void cancel()
251  {
252  _p->cancel(*this);
253  }
254 
257  bool isCancelable() const
258  {
259  return _p->isCancelable();
260  }
261  public: //Signals
262  typedef boost::function<void (Future<T>) > Connection;
263 
270  template<typename AF>
271  inline void connect(const AF& fun,
273  {
274  _p->connect(*this, fun, type);
275  }
276 #ifdef DOXYGEN
277 
283  template<typename FUNCTYPE, typename ARG0>
284  void connect(FUNCTYPE fun, ARG0 tracked, ...,
286 #else
287 #define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma) \
288  template<typename AF, typename ARG0 comma ATYPEDECL> \
289  inline void connect(const AF& fun, const ARG0& arg0 comma ADECL, \
290  FutureCallbackType type = FutureCallbackType_Async) \
291  { \
292  _p->connect(*this, ::qi::bind<void(Future<T>)>(fun, arg0 comma AUSE), \
293  type); \
294  }
295  QI_GEN(genCall)
296 #undef genCall
297 #endif
298 
299  // Our companion library libqitype requires a connect with same signature for all instantiations
300  inline void _connect(const boost::function<void()>& s) { connect(boost::bind(s));}
301 
302  boost::shared_ptr<detail::FutureBaseTyped<T> > impl() { return _p;}
303  Future(boost::shared_ptr<detail::FutureBaseTyped<T> > p) :
304  _p(p)
305  {
306  assert(_p);
307  }
308  protected:
309  // C4251 needs to have dll-interface to be used by clients of class 'qi::Future<T>'
310  boost::shared_ptr< detail::FutureBaseTyped<T> > _p;
311  friend class Promise<T>;
312  friend class FutureSync<T>;
313 
314  template<typename FT, typename PT>
315  friend void adaptFuture(const Future<FT>& f, Promise<PT>& p);
316  template<typename FT, typename PT, typename CONV>
317  friend void adaptFuture(const Future<FT>& f, Promise<PT>& p,
318  CONV converter);
319  template<typename FT>
320  friend void detail::futureCancelAdapter(
321  boost::weak_ptr<detail::FutureBaseTyped<FT> > wf);
322  };
323 
324 
325 
329  template<typename T>
330  class FutureSync
331  {
332  public:
333  typedef typename Future<T>::ValueType ValueType;
336  // This future cannot be set, so sync starts at false
337  FutureSync() : _sync(false) {}
338 
340  : _sync(true)
341  {
342  _future = b;
343  }
344 
346  : _sync(true)
347  {
348  _future = b._future;
349  b._sync = false;
350  }
351 
352  explicit FutureSync<T>(const ValueType& v)
353  : _sync(false)
354  {
355  Promise<T> promise;
356  promise.setValue(v);
357  _future = promise.future();
358  }
359 
361  {
362  _future = b;
363  _sync = true;
364  b._sync = false;
365  return *this;
366  }
367 
369  {
370  _future = b;
371  _sync = true;
372  return *this;
373  }
374 
376  {
377  if (_sync)
378  _future.value();
379  }
380 
381  operator Future<T>()
382  {
383  return async();
384  }
385 
386  bool operator < (const FutureSync<T>& b) const
387  {
388  return _future._p.get() < b._future._p.get();
389  }
390 
391  const ValueType &value(int msecs = FutureTimeout_Infinite) const { _sync = false; return _future.value(msecs); }
392  operator const typename Future<T>::ValueTypeCast&() const { _sync = false; return _future.value(); }
393  FutureState wait(int msecs = FutureTimeout_Infinite) const { _sync = false; return _future.wait(msecs); }
394  bool isRunning() const { _sync = false; return _future.isRunning(); }
395  bool isFinished() const { _sync = false; return _future.isFinished(); }
396  bool isCanceled() const { _sync = false; return _future.isCanceled(); }
397  bool hasError(int msecs = FutureTimeout_Infinite) const { _sync = false; return _future.hasError(msecs); }
398  bool hasValue(int msecs = FutureTimeout_Infinite) const { _sync = false; return _future.hasValue(msecs); }
399  const std::string &error(int msecs = FutureTimeout_Infinite) const { _sync = false; return _future.error(msecs); }
400  void cancel() { _sync = false; _future.cancel(); }
401  bool isCancelable() const { _sync = false; return _future.isCancelable(); }
402  void connect(const Connection& s) { _sync = false; _future.connect(s);}
403  void _connect(const boost::function<void()>& s) { _sync = false; _future._connect(s);}
404 
405 #ifdef DOXYGEN
406 
412  template<typename FUNCTYPE, typename ARG0>
413  void connect(FUNCTYPE fun, ARG0 tracked, ...);
414 #else
415 #define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma) \
416  template<typename AF, typename ARG0 comma ATYPEDECL> \
417  inline void connect(const AF& fun, const ARG0& arg0 comma ADECL) \
418  { \
419  _sync = false; \
420  connect(::qi::bind<void(FutureSync<T>)>(fun, arg0 comma AUSE)); \
421  }
422  QI_GEN(genCall)
423 #undef genCall
424 #endif
425 
427  {
428  _sync = false;
429  return _future;
430  }
431 
432  protected:
433  mutable bool _sync;
435  friend class Future<T>;
436  };
437 
438 
441  template <typename T>
442  class Promise {
443  public:
444  typedef typename FutureType<T>::type ValueType;
445 
452  _f._p->reportStart();
453  _f._p->_async = async;
454  }
455 
461  explicit Promise(boost::function<void (qi::Promise<T>)> cancelCallback, FutureCallbackType async = FutureCallbackType_Async)
462  {
463  setup(cancelCallback, async);
464  }
465 
469  void setValue(const ValueType &value) {
470  _f._p->setValue(_f, value);
471  }
472 
476  void setError(const std::string &msg) {
477  _f._p->setError(_f, msg);
478  }
479 
483  void setCanceled() {
484  _f._p->setCanceled(_f);
485  }
486 
487  /* reset the promise and the future */
488  void reset() {
489  _f._p->reset();
490  }
491 
493  Future<T> future() const { return _f; }
494 
498  ValueType& value() { return _f._p->_value;}
501  void trigger() { _f._p->set(_f);}
502  protected:
503  void setup(boost::function<void (qi::Promise<T>)> cancelCallback, FutureCallbackType async = FutureCallbackType_Async)
504  {
505  this->_f._p->reportStart();
506  this->_f._p->setOnCancel(cancelCallback);
507  this->_f._p->_async = async;
508  }
509  explicit Promise(Future<T>& f) : _f(f) {}
510  template<typename> friend class ::qi::detail::FutureBaseTyped;
512 
513  template<typename FT, typename PT>
514  friend void adaptFuture(const Future<FT>& f, Promise<PT>& p);
515  template<typename FT, typename PT, typename CONV>
516  friend void adaptFuture(const Future<FT>& f, Promise<PT>& p,
517  CONV converter);
518  };
519 
520  template<typename T>
522  public:
525  : _closed(false)
526  , _count(0)
527  , _futures()
528  , _promise(async)
529  {}
530 
533  // Can't add future from closed qi::FutureBarrier.
534  if (this->_closed)
535  return false;
536 
537  ++(this->_count);
538  fut.connect(boost::bind<void>(&FutureBarrier::onFutureFinish, this));
539  this->_futures.push_back(fut);
540  return true;
541  }
542 
545  this->close();
546  return this->_promise.future();
547  }
548 
549  protected:
550  bool _closed;
552  std::vector< Future<T> > _futures;
554 
555  private:
556  void onFutureFinish() {
557  if (--(this->_count) == 0 && this->_closed) {
558  this->_promise.setValue(this->_futures);
559  }
560  }
561 
562  void close() {
563  this->_closed = true;
564  if (*(this->_count) == 0) {
565  this->_promise.setValue(this->_futures);
566  }
567  }
568  };
569 
570  template <typename T>
572 
574  template <typename T>
575  void waitForAll(std::vector< Future<T> >& vect);
576 
578  template <typename T>
579  qi::FutureSync< qi::Future<T> > waitForFirst(std::vector< Future<T> >& vect);
580 
582  template<typename FT, typename PT>
584  {
585  void operator()(const FT& vIn, PT& vOut) { vOut = vIn;}
586  };
587 
593  template<typename FT, typename PT>
594  void adaptFuture(const Future<FT>& f, Promise<PT>& p);
595 
597  template<typename FT, typename PT, typename CONV>
598  void adaptFuture(const Future<FT>& f, Promise<PT>& p, CONV converter);
599 }
600 
601 #ifdef _MSC_VER
602 # pragma warning( pop )
603 #endif
604 
605 #include <qi/details/future.hxx>
606 
607 #endif // _QI_FUTURE_HPP_
Future< T >::ValueType ValueType
Definition: future.hpp:333
This class helps waiting on multiple futures at the same point.
Definition: future.hpp:521
Promise(boost::function< void(qi::Promise< T >)> cancelCallback, FutureCallbackType async=FutureCallbackType_Async)
Definition: future.hpp:461
FutureSync(const Future< T > &b)
Definition: future.hpp:339
bool hasValue(int msecs=FutureTimeout_Infinite) const
Definition: future.hpp:398
const ValueType & value(int msecs=FutureTimeout_Infinite) const
Return the value associated to a Future.
Definition: future.hpp:178
void operator()(const FT &vIn, PT &vOut)
Definition: future.hpp:585
Future< T >::Connection Connection
Definition: future.hpp:335
void trigger()
Definition: future.hpp:501
FutureType< T >::type ValueType
Definition: future.hpp:131
Future< std::vector< Future< T > > > future()
Gets the future result for the barrier.
Definition: future.hpp:544
The future has been canceled.
Definition: future.hpp:65
qi::Future< T > makeFutureError(const std::string &error, FutureCallbackType async)
Definition: future.hxx:231
bool isRunning() const
isRunning
Definition: future.hpp:202
void connect(const Connection &s)
Definition: future.hpp:402
FutureTimeout
Definition: future.hpp:74
FutureState
Definition: future.hpp:61
void setCanceled()
Definition: future.hpp:483
bool isFinished() const
isFinished
Definition: future.hpp:195
bool hasError(int msecs=FutureTimeout_Infinite) const
hasError
Definition: future.hpp:218
Future< T > & operator=(const Future< T > &b)
Definition: future.hpp:149
bool isCancelable() const
Definition: future.hpp:257
FutureType< T >::typecast ValueTypeCast
Definition: future.hpp:132
FutureState wait(int msecs=FutureTimeout_Infinite) const
Definition: future.hpp:188
void cancel()
Definition: future.hpp:400
Future< T > _future
Definition: future.hpp:434
bool operator==(const Future< T > &other)
Definition: future.hpp:144
Promise(FutureCallbackType async=FutureCallbackType_Async)
Definition: future.hpp:451
#define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma)
Definition: trackable.hxx:94
ValueType & value()
Definition: future.hpp:498
Future< T > future() const
Get a future linked to this promise. Can be called multiple times.
Definition: future.hpp:493
qi::FutureSync< qi::Future< T > > waitForFirst(std::vector< Future< T > > &vect)
Helper function to wait for the first valid future.
Definition: future.hxx:249
FutureSync< T > & operator=(const Future< T > &b)
Definition: future.hpp:368
bool isRunning() const
Definition: future.hpp:394
Operation pending.
Definition: future.hpp:64
void futureCancelAdapter(boost::weak_ptr< FutureBaseTyped< FT > > wf)
Definition: future.hxx:284
bool isCancelable() const
Definition: future.hpp:401
FutureSync(const FutureSync< T > &b)
Definition: future.hpp:345
void cancel()
Definition: future.hpp:250
bool hasValue(int msecs=FutureTimeout_Infinite) const
hasValue
Definition: future.hpp:227
Atomic< int > _count
Definition: future.hpp:551
FutureBarrier(FutureCallbackType async=FutureCallbackType_Async)
FutureBarrier constructor taking no argument.
Definition: future.hpp:524
void connect(const AF &fun, FutureCallbackType type=FutureCallbackType_Async)
Definition: future.hpp:271
Future is not tied to a promise.
Definition: future.hpp:63
Specialize this struct to provide conversion between future values.
Definition: future.hpp:583
virtual ~FutureException()
Definition: future.hpp:107
Promise(Future< T > &f)
Definition: future.hpp:509
Future< T > async()
Definition: future.hpp:426
FutureHasNoValue typecast
Definition: future.hpp:43
void adaptFuture(const Future< FT > &f, Promise< PT > &p)
Definition: future.hxx:316
Future< T >::ValueTypeCast ValueTypeCast
Definition: future.hpp:334
void reset()
Definition: future.hpp:488
Future(const Future< T > &b)
Definition: future.hpp:140
bool isFinished() const
Definition: future.hpp:395
FutureCallbackType
Definition: future.hpp:69
std::vector< Future< T > > _futures
Definition: future.hpp:552
The operation is finished with an error.
Definition: future.hpp:66
#define QI_GEN(f)
Definition: preproc.hpp:471
FutureSync< T > sync()
Definition: future.hpp:239
virtual ~FutureUserException()
Definition: future.hpp:124
void _connect(const boost::function< void()> &s)
Definition: future.hpp:300
ExceptionState state() const
Definition: future.hpp:103
boost::function< void(Future< std::vector< qi::Future< T > > >) > Connection
Definition: future.hpp:262
const std::string & error(int msecs=FutureTimeout_Infinite) const
error
Definition: future.hpp:236
FutureSync< T > & operator=(const FutureSync< T > &b)
Definition: future.hpp:360
bool isCanceled() const
Definition: future.hpp:396
boost::shared_ptr< detail::FutureBaseTyped< T > > impl()
Definition: future.hpp:302
FutureState wait(int msecs=FutureTimeout_Infinite) const
Definition: future.hpp:393
dll import/export and compiler message
void setError(const std::string &msg)
Definition: future.hpp:476
bool addFuture(qi::Future< T > fut)
Adds the future to the barrier.
Definition: future.hpp:532
Promise< std::vector< Future< T > > > _promise
Definition: future.hpp:553
boost::function< RF > bind(const AF &fun,...)
Future(boost::shared_ptr< detail::FutureBaseTyped< T > > p)
Definition: future.hpp:303
bool isCanceled() const
isCanceled
Definition: future.hpp:209
bool hasError(int msecs=FutureTimeout_Infinite) const
Definition: future.hpp:397
void _connect(const boost::function< void()> &s)
Definition: future.hpp:403
const std::string & error(int msecs=FutureTimeout_Infinite) const
Definition: future.hpp:399
friend void adaptFuture(const Future< FT > &f, Promise< PT > &p)
Definition: future.hxx:316
FutureException(const ExceptionState &es, const std::string &str=std::string())
Definition: future.hpp:98
boost::shared_ptr< detail::FutureBaseTyped< T > > _p
Definition: future.hpp:310
void setValue(const ValueType &value)
Definition: future.hpp:469
void waitForAll(std::vector< Future< T > > &vect)
Helper function to wait on a vector of futures.
Definition: future.hxx:238
friend void adaptFuture(const Future< FT > &f, Promise< PT > &p)
Definition: future.hxx:316
FutureType< T >::type ValueType
Definition: future.hpp:444
#define QI_API
Definition: api.hpp:24
void setup(boost::function< void(qi::Promise< T >)> cancelCallback, FutureCallbackType async=FutureCallbackType_Async)
Definition: future.hpp:503
const ValueType & value(int msecs=FutureTimeout_Infinite) const
Definition: future.hpp:391
FutureUserException(const std::string &str=std::string())
Definition: future.hpp:120
Future< T > _f
Definition: future.hpp:511