libqi-api  2.8.7.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
futurebarrier.hpp
Go to the documentation of this file.
1 #pragma once
2 /*
3 ** Copyright (C) 2015 Aldebaran Robotics
4 ** See COPYING for the license
5 */
6 
7 #ifndef QI_DETAIL_FUTURE_BARRIER_HXX_
8 #define QI_DETAIL_FUTURE_BARRIER_HXX_
9 
10 namespace qi
11 {
12 
13 namespace detail
14 {
15 
16 template<typename T>
18 public:
21  : _closed(0)
22  , _count(0)
23  , _futures()
24  , _promise(async)
25  {}
26 
27  void onFutureFinish() {
28  if (--(this->_count) == 0 && this->_closed.load()) {
29  if (!_set.swap(true))
30  this->_promise.setValue(this->_futures);
31  }
32  }
33 
34  void cancelAll() {
36  for (typename std::vector< Future<T> >::iterator it = this->_futures.begin();
37  it != this->_futures.end();
38  ++it)
39  it->cancel();
40  }
41 
45  std::vector< Future<T> > _futures;
47 
48 };
49 
50 }
51 
163 template<typename T>
164 class FutureBarrier : boost::noncopyable {
165 public:
168  : _p(boost::make_shared<detail::FutureBarrierPrivate<T> >(async))
169  {
170  _p->_promise.setOnCancel(qi::bindWithFallback(
171  boost::function<void()>(),
173  boost::weak_ptr<detail::FutureBarrierPrivate<T> >(_p)));
174  }
175 
189  // Can't add future from closed qi::FutureBarrier.
190  if (_p->_closed.load())
191  throw std::runtime_error("Adding future to closed barrier");
192 
193  ++(_p->_count);
195  _p->_futures.push_back(fut);
196  }
197 
210  this->close();
211  return _p->_promise.future();
212  }
213 
214 protected:
215  boost::shared_ptr<detail::FutureBarrierPrivate<T> > _p;
216 
217 private:
218  void close() {
219  _p->_closed = true;
220  if (_p->_count.load() == 0) {
221  if (!_p->_set.swap(true))
222  _p->_promise.setValue(_p->_futures);
223  }
224  }
225 };
226 
238 template <typename T>
240  typename std::vector< Future<T> >::iterator it;
241  qi::FutureBarrier<T> barrier;
242 
243  for (it = vect.begin(); it != vect.end(); ++it) {
244  barrier.addFuture(*it);
245  }
246  return barrier.future();
247 }
248 
260 template <typename T>
262  typename std::vector< Future<T> >::iterator it;
264  qi::Atomic<int>* count = new qi::Atomic<int>();
265  count->swap((int)vect.size());
266  for (it = vect.begin(); it != vect.end(); ++it) {
267  it->connect(boost::bind<void>(&detail::waitForFirstHelper<T>, prom, *it, count));
268  }
269  return prom.future();
270 }
271 
272 }
273 
274 #endif
FutureBarrier(FutureCallbackType async=FutureCallbackType_Async)
FutureBarrier constructor taking no argument.
T swap(T value)
Definition: atomic.hpp:210
void connect(const AF &fun, FutureCallbackType type=FutureCallbackType_Auto)
Definition: future_fwd.hpp:545
void addFuture(qi::Future< T > fut)
Adds the future to the barrier.
This class helps waiting for multiple futures at the same point.
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bindWithFallback(boost::function< void()> onFail, AF &&fun, Arg0 &&arg0, Args &&...args)
Definition: trackable.hxx:291
#define QI_ASSERT(expr__)
Definition: assert.hpp:27
Future< std::vector< Future< T > > > future()
Gets the future result for the barrier.
qi::FutureSync< std::vector< Future< T > > > waitForAll(std::vector< Future< T > > &vect)
Helper function that creates a future waiting on a vector of futures.
std::vector< Future< T > > _futures
Future< T > future() const
Get a future linked to this promise. Can be called multiple times.
Definition: future_fwd.hpp:881
auto async(F &&callback) -> decltype(asyncDelay(std::forward< F >(callback), qi::Duration(0)))
Definition: async.hpp:53
Promise< std::vector< Future< T > > > _promise
FutureCallbackType
Definition: future_fwd.hpp:104
FutureBarrierPrivate(FutureCallbackType async=FutureCallbackType_Async)
FutureBarrier constructor taking no argument.
boost::shared_ptr< detail::FutureBarrierPrivate< T > > _p
qi::FutureSync< qi::Future< T > > waitForFirst(std::vector< Future< T > > &vect)
Helper function to wait for the first valid future.
T load() const
Definition: atomic.hpp:221