annotate DEPENDENCIES/generic/include/boost/thread/futures/wait_for_any.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents f46d142149f5
children
rev   line source
Chris@102 1 // (C) Copyright 2008-10 Anthony Williams
Chris@102 2 // (C) Copyright 2011-2015 Vicente J. Botet Escriba
Chris@102 3 //
Chris@102 4 // Distributed under the Boost Software License, Version 1.0. (See
Chris@102 5 // accompanying file LICENSE_1_0.txt or copy at
Chris@102 6 // http://www.boost.org/LICENSE_1_0.txt)
Chris@102 7
Chris@102 8 #ifndef BOOST_THREAD_FUTURES_WAIT_FOR_ANY_HPP
Chris@102 9 #define BOOST_THREAD_FUTURES_WAIT_FOR_ANY_HPP
Chris@102 10
Chris@102 11 #include <boost/thread/detail/config.hpp>
Chris@102 12
Chris@102 13 #include <boost/thread/detail/move.hpp>
Chris@102 14 #include <boost/thread/futures/is_future_type.hpp>
Chris@102 15 #include <boost/thread/lock_algorithms.hpp>
Chris@102 16 #include <boost/thread/mutex.hpp>
Chris@102 17
Chris@102 18 #include <boost/core/enable_if.hpp>
Chris@102 19 #include <boost/next_prior.hpp>
Chris@102 20 #include <boost/scoped_array.hpp>
Chris@102 21
Chris@102 22 #include <iterator>
Chris@102 23 #include <vector>
Chris@102 24
Chris@102 25 namespace boost
Chris@102 26 {
Chris@102 27 namespace detail
Chris@102 28 {
Chris@102 29 template <class Future>
Chris@102 30 class waiter_for_any_in_seq
Chris@102 31 {
Chris@102 32 struct registered_waiter;
Chris@102 33 typedef std::vector<int>::size_type count_type;
Chris@102 34
Chris@102 35 struct registered_waiter
Chris@102 36 {
Chris@102 37 typedef Future future_type;
Chris@102 38 future_type* future_;
Chris@102 39 typedef typename Future::notify_when_ready_handle notify_when_ready_handle;
Chris@102 40 notify_when_ready_handle handle;
Chris@102 41 count_type index;
Chris@102 42
Chris@102 43 registered_waiter(future_type & a_future,
Chris@102 44 notify_when_ready_handle handle_, count_type index_) :
Chris@102 45 future_(&a_future), handle(handle_), index(index_)
Chris@102 46 {
Chris@102 47 }
Chris@102 48 };
Chris@102 49
Chris@102 50 struct all_futures_lock
Chris@102 51 {
Chris@102 52 #ifdef _MANAGED
Chris@102 53 typedef std::ptrdiff_t count_type_portable;
Chris@102 54 #else
Chris@102 55 typedef count_type count_type_portable;
Chris@102 56 #endif
Chris@102 57 count_type_portable count;
Chris@102 58 boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
Chris@102 59
Chris@102 60 all_futures_lock(std::vector<registered_waiter>& waiters) :
Chris@102 61 count(waiters.size()), locks(new boost::unique_lock<boost::mutex>[count])
Chris@102 62 {
Chris@102 63 for (count_type_portable i = 0; i < count; ++i)
Chris@102 64 {
Chris@102 65 locks[i] = BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(waiters[i].future_->mutex()));
Chris@102 66 }
Chris@102 67 }
Chris@102 68
Chris@102 69 void lock()
Chris@102 70 {
Chris@102 71 boost::lock(locks.get(), locks.get() + count);
Chris@102 72 }
Chris@102 73
Chris@102 74 void unlock()
Chris@102 75 {
Chris@102 76 for (count_type_portable i = 0; i < count; ++i)
Chris@102 77 {
Chris@102 78 locks[i].unlock();
Chris@102 79 }
Chris@102 80 }
Chris@102 81 };
Chris@102 82
Chris@102 83 boost::condition_variable_any cv;
Chris@102 84 std::vector<registered_waiter> waiters_;
Chris@102 85 count_type future_count;
Chris@102 86
Chris@102 87 public:
Chris@102 88 waiter_for_any_in_seq() :
Chris@102 89 future_count(0)
Chris@102 90 {
Chris@102 91 }
Chris@102 92
Chris@102 93 template <typename F>
Chris@102 94 void add(F& f)
Chris@102 95 {
Chris@102 96 if (f.valid())
Chris@102 97 {
Chris@102 98 registered_waiter waiter(f, f.notify_when_ready(cv), future_count);
Chris@102 99 try
Chris@102 100 {
Chris@102 101 waiters_.push_back(waiter);
Chris@102 102 }
Chris@102 103 catch (...)
Chris@102 104 {
Chris@102 105 f.future_->unnotify_when_ready(waiter.handle);
Chris@102 106 throw;
Chris@102 107 }
Chris@102 108 ++future_count;
Chris@102 109 }
Chris@102 110 }
Chris@102 111
Chris@102 112 #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
Chris@102 113 template <typename F1, typename ... Fs>
Chris@102 114 void add(F1& f1, Fs&... fs)
Chris@102 115 {
Chris@102 116 add(f1);
Chris@102 117 add(fs...);
Chris@102 118 }
Chris@102 119 #endif
Chris@102 120
Chris@102 121 count_type wait()
Chris@102 122 {
Chris@102 123 all_futures_lock lk(waiters_);
Chris@102 124 for (;;)
Chris@102 125 {
Chris@102 126 for (count_type i = 0; i < waiters_.size(); ++i)
Chris@102 127 {
Chris@102 128 if (waiters_[i].future_->is_ready(lk.locks[i]))
Chris@102 129 {
Chris@102 130 return waiters_[i].index;
Chris@102 131 }
Chris@102 132 }
Chris@102 133 cv.wait(lk);
Chris@102 134 }
Chris@102 135 }
Chris@102 136
Chris@102 137 ~waiter_for_any_in_seq()
Chris@102 138 {
Chris@102 139 for (count_type i = 0; i < waiters_.size(); ++i)
Chris@102 140 {
Chris@102 141 waiters_[i].future_->unnotify_when_ready(waiters_[i].handle);
Chris@102 142 }
Chris@102 143 }
Chris@102 144 };
Chris@102 145 }
Chris@102 146
Chris@102 147 template <typename Iterator>
Chris@102 148 typename boost::disable_if<is_future_type<Iterator> , Iterator>::type wait_for_any(Iterator begin, Iterator end)
Chris@102 149 {
Chris@102 150 if (begin == end) return end;
Chris@102 151
Chris@102 152 detail::waiter_for_any_in_seq<typename std::iterator_traits<Iterator>::value_type> waiter;
Chris@102 153 for (Iterator current = begin; current != end; ++current)
Chris@102 154 {
Chris@102 155 waiter.add(*current);
Chris@102 156 }
Chris@102 157 return boost::next(begin, waiter.wait());
Chris@102 158 }
Chris@102 159 }
Chris@102 160
Chris@102 161 #endif // header