Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/thread/future.hpp @ 101:c530137014c0
Update Boost headers (1.58.0)
author | Chris Cannam |
---|---|
date | Mon, 07 Sep 2015 11:12:49 +0100 |
parents | 2665513ce2d3 |
children |
comparison
equal
deleted
inserted
replaced
100:793467b5e61c | 101:c530137014c0 |
---|---|
1 // (C) Copyright 2008-10 Anthony Williams | 1 // (C) Copyright 2008-10 Anthony Williams |
2 // (C) Copyright 2011-2013 Vicente J. Botet Escriba | 2 // (C) Copyright 2011-2015 Vicente J. Botet Escriba |
3 // | 3 // |
4 // Distributed under the Boost Software License, Version 1.0. (See | 4 // Distributed under the Boost Software License, Version 1.0. (See |
5 // accompanying file LICENSE_1_0.txt or copy at | 5 // accompanying file LICENSE_1_0.txt or copy at |
6 // http://www.boost.org/LICENSE_1_0.txt) | 6 // http://www.boost.org/LICENSE_1_0.txt) |
7 | 7 |
13 // boost::thread::future requires exception handling | 13 // boost::thread::future requires exception handling |
14 // due to boost::exception::exception_ptr dependency | 14 // due to boost::exception::exception_ptr dependency |
15 | 15 |
16 #ifndef BOOST_NO_EXCEPTIONS | 16 #ifndef BOOST_NO_EXCEPTIONS |
17 | 17 |
18 //#include <boost/thread/detail/log.hpp> | 18 #include <boost/thread/condition_variable.hpp> |
19 #include <boost/detail/scoped_enum_emulation.hpp> | |
20 #include <stdexcept> | |
21 #include <boost/thread/detail/move.hpp> | 19 #include <boost/thread/detail/move.hpp> |
22 #include <boost/thread/detail/async_func.hpp> | 20 #include <boost/thread/detail/invoker.hpp> |
23 #include <boost/thread/thread_time.hpp> | 21 #include <boost/thread/detail/invoke.hpp> |
24 #include <boost/thread/mutex.hpp> | 22 #include <boost/thread/detail/is_convertible.hpp> |
25 #include <boost/thread/condition_variable.hpp> | 23 #include <boost/thread/exceptional_ptr.hpp> |
24 #include <boost/thread/futures/future_error.hpp> | |
25 #include <boost/thread/futures/future_error_code.hpp> | |
26 #include <boost/thread/futures/future_status.hpp> | |
27 #include <boost/thread/futures/is_future_type.hpp> | |
28 #include <boost/thread/futures/launch.hpp> | |
29 #include <boost/thread/futures/wait_for_all.hpp> | |
30 #include <boost/thread/futures/wait_for_any.hpp> | |
26 #include <boost/thread/lock_algorithms.hpp> | 31 #include <boost/thread/lock_algorithms.hpp> |
27 #include <boost/thread/lock_types.hpp> | 32 #include <boost/thread/lock_types.hpp> |
28 #include <boost/exception_ptr.hpp> | 33 #include <boost/thread/mutex.hpp> |
29 #include <boost/shared_ptr.hpp> | 34 #include <boost/thread/thread_only.hpp> |
30 #include <boost/scoped_ptr.hpp> | 35 #include <boost/thread/thread_time.hpp> |
31 #include <boost/type_traits/is_fundamental.hpp> | 36 |
32 #include <boost/thread/detail/is_convertible.hpp> | 37 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL |
33 #include <boost/type_traits/remove_reference.hpp> | 38 #include <boost/optional.hpp> |
34 #include <boost/type_traits/remove_cv.hpp> | 39 #else |
35 #include <boost/type_traits/is_void.hpp> | 40 #include <boost/thread/csbl/memory/unique_ptr.hpp> |
36 #include <boost/mpl/if.hpp> | 41 #endif |
37 #include <boost/config.hpp> | 42 |
38 #include <boost/throw_exception.hpp> | 43 #include <boost/assert.hpp> |
39 #include <algorithm> | |
40 #include <boost/function.hpp> | |
41 #include <boost/bind.hpp> | 44 #include <boost/bind.hpp> |
42 #include <boost/ref.hpp> | |
43 #include <boost/scoped_array.hpp> | |
44 #include <boost/enable_shared_from_this.hpp> | |
45 #include <boost/utility/enable_if.hpp> | |
46 #include <list> | |
47 #include <boost/next_prior.hpp> | |
48 #include <vector> | |
49 | |
50 #include <boost/thread/future_error_code.hpp> | |
51 #ifdef BOOST_THREAD_USES_CHRONO | 45 #ifdef BOOST_THREAD_USES_CHRONO |
52 #include <boost/chrono/system_clocks.hpp> | 46 #include <boost/chrono/system_clocks.hpp> |
53 #endif | 47 #endif |
48 #include <boost/core/enable_if.hpp> | |
49 #include <boost/core/ref.hpp> | |
50 #include <boost/enable_shared_from_this.hpp> | |
51 #include <boost/exception_ptr.hpp> | |
52 #include <boost/function.hpp> | |
53 #include <boost/next_prior.hpp> | |
54 #include <boost/scoped_array.hpp> | |
55 #include <boost/shared_ptr.hpp> | |
56 #include <boost/throw_exception.hpp> | |
57 #include <boost/type_traits/conditional.hpp> | |
58 #include <boost/type_traits/decay.hpp> | |
59 #include <boost/type_traits/is_copy_constructible.hpp> | |
60 #include <boost/type_traits/is_fundamental.hpp> | |
61 #include <boost/type_traits/is_void.hpp> | |
62 #include <boost/utility/result_of.hpp> | |
63 | |
54 | 64 |
55 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS | 65 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS |
56 #include <boost/thread/detail/memory.hpp> | 66 #include <boost/thread/detail/memory.hpp> |
57 #endif | 67 #include <boost/container/scoped_allocator.hpp> |
58 | 68 #if ! defined BOOST_NO_CXX11_ALLOCATOR |
59 #include <boost/utility/result_of.hpp> | 69 #include <memory> |
60 #include <boost/thread/thread_only.hpp> | 70 #endif |
71 #endif | |
72 | |
73 #if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY | |
74 #include <boost/thread/csbl/tuple.hpp> | |
75 #include <boost/thread/csbl/vector.hpp> | |
76 #endif | |
77 | |
78 #include <algorithm> | |
79 #include <list> | |
80 #include <vector> | |
81 #include <utility> | |
61 | 82 |
62 #if defined BOOST_THREAD_PROVIDES_FUTURE | 83 #if defined BOOST_THREAD_PROVIDES_FUTURE |
63 #define BOOST_THREAD_FUTURE future | 84 #define BOOST_THREAD_FUTURE future |
64 #else | 85 #else |
65 #define BOOST_THREAD_FUTURE unique_future | 86 #define BOOST_THREAD_FUTURE unique_future |
66 #endif | 87 #endif |
67 | 88 |
68 namespace boost | 89 namespace boost |
69 { | 90 { |
70 | |
71 //enum class launch | |
72 BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch) | |
73 { | |
74 none = 0, | |
75 async = 1, | |
76 deferred = 2, | |
77 any = async | deferred | |
78 } | |
79 BOOST_SCOPED_ENUM_DECLARE_END(launch) | |
80 | |
81 //enum class future_status | |
82 BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status) | |
83 { | |
84 ready, | |
85 timeout, | |
86 deferred | |
87 } | |
88 BOOST_SCOPED_ENUM_DECLARE_END(future_status) | |
89 | |
90 class BOOST_SYMBOL_VISIBLE future_error | |
91 : public std::logic_error | |
92 { | |
93 system::error_code ec_; | |
94 public: | |
95 future_error(system::error_code ec) | |
96 : logic_error(ec.message()), | |
97 ec_(ec) | |
98 { | |
99 } | |
100 | |
101 const system::error_code& code() const BOOST_NOEXCEPT | |
102 { | |
103 return ec_; | |
104 } | |
105 }; | |
106 | |
107 class BOOST_SYMBOL_VISIBLE future_uninitialized: | |
108 public future_error | |
109 { | |
110 public: | |
111 future_uninitialized() : | |
112 future_error(system::make_error_code(future_errc::no_state)) | |
113 {} | |
114 }; | |
115 class BOOST_SYMBOL_VISIBLE broken_promise: | |
116 public future_error | |
117 { | |
118 public: | |
119 broken_promise(): | |
120 future_error(system::make_error_code(future_errc::broken_promise)) | |
121 {} | |
122 }; | |
123 class BOOST_SYMBOL_VISIBLE future_already_retrieved: | |
124 public future_error | |
125 { | |
126 public: | |
127 future_already_retrieved(): | |
128 future_error(system::make_error_code(future_errc::future_already_retrieved)) | |
129 {} | |
130 }; | |
131 class BOOST_SYMBOL_VISIBLE promise_already_satisfied: | |
132 public future_error | |
133 { | |
134 public: | |
135 promise_already_satisfied(): | |
136 future_error(system::make_error_code(future_errc::promise_already_satisfied)) | |
137 {} | |
138 }; | |
139 | |
140 class BOOST_SYMBOL_VISIBLE task_already_started: | |
141 public future_error | |
142 { | |
143 public: | |
144 task_already_started(): | |
145 future_error(system::make_error_code(future_errc::promise_already_satisfied)) | |
146 {} | |
147 }; | |
148 | |
149 class BOOST_SYMBOL_VISIBLE task_moved: | |
150 public future_error | |
151 { | |
152 public: | |
153 task_moved(): | |
154 future_error(system::make_error_code(future_errc::no_state)) | |
155 {} | |
156 }; | |
157 | |
158 class promise_moved: | |
159 public future_error | |
160 { | |
161 public: | |
162 promise_moved(): | |
163 future_error(system::make_error_code(future_errc::no_state)) | |
164 {} | |
165 }; | |
166 | |
167 namespace future_state | |
168 { | |
169 enum state { uninitialized, waiting, ready, moved, deferred }; | |
170 } | |
171 | |
172 namespace detail | 91 namespace detail |
173 { | 92 { |
174 struct relocker | 93 struct relocker |
175 { | 94 { |
176 boost::unique_lock<boost::mutex>& lock_; | 95 boost::unique_lock<boost::mutex>& lock_; |
177 bool unlocked_; | |
178 | 96 |
179 relocker(boost::unique_lock<boost::mutex>& lk): | 97 relocker(boost::unique_lock<boost::mutex>& lk): |
180 lock_(lk) | 98 lock_(lk) |
181 { | 99 { |
182 lock_.unlock(); | 100 lock_.unlock(); |
183 unlocked_=true; | |
184 } | 101 } |
185 ~relocker() | 102 ~relocker() |
186 { | 103 { |
187 if (unlocked_) { | 104 if (! lock_.owns_lock()) { |
188 lock_.lock(); | 105 lock_.lock(); |
189 } | 106 } |
190 } | 107 } |
191 void lock() { | 108 void lock() { |
192 if (unlocked_) { | 109 if (! lock_.owns_lock()) { |
193 lock_.lock(); | 110 lock_.lock(); |
194 unlocked_=false; | |
195 } | 111 } |
196 } | 112 } |
197 private: | 113 private: |
198 relocker& operator=(relocker const&); | 114 relocker& operator=(relocker const&); |
199 }; | 115 }; |
200 | 116 |
201 struct shared_state_base : enable_shared_from_this<shared_state_base> | 117 struct shared_state_base : enable_shared_from_this<shared_state_base> |
202 { | 118 { |
203 typedef std::list<boost::condition_variable_any*> waiter_list; | 119 typedef std::list<boost::condition_variable_any*> waiter_list; |
120 typedef waiter_list::iterator notify_when_ready_handle; | |
204 // This type should be only included conditionally if interruptions are allowed, but is included to maintain the same layout. | 121 // This type should be only included conditionally if interruptions are allowed, but is included to maintain the same layout. |
205 typedef shared_ptr<shared_state_base> continuation_ptr_type; | 122 typedef shared_ptr<shared_state_base> continuation_ptr_type; |
123 typedef std::vector<continuation_ptr_type> continuations_type; | |
206 | 124 |
207 boost::exception_ptr exception; | 125 boost::exception_ptr exception; |
208 bool done; | 126 bool done; |
127 bool is_valid_; | |
209 bool is_deferred_; | 128 bool is_deferred_; |
129 bool is_constructed; | |
130 std::size_t cnt_; | |
210 launch policy_; | 131 launch policy_; |
211 bool is_constructed; | |
212 mutable boost::mutex mutex; | 132 mutable boost::mutex mutex; |
213 boost::condition_variable waiters; | 133 boost::condition_variable waiters; |
214 waiter_list external_waiters; | 134 waiter_list external_waiters; |
215 boost::function<void()> callback; | 135 boost::function<void()> callback; |
216 // This declaration should be only included conditionally if interruptions are allowed, but is included to maintain the same layout. | |
217 bool thread_was_interrupted; | |
218 // This declaration should be only included conditionally, but is included to maintain the same layout. | 136 // This declaration should be only included conditionally, but is included to maintain the same layout. |
219 continuation_ptr_type continuation_ptr; | 137 continuations_type continuations; |
220 | 138 |
221 // This declaration should be only included conditionally, but is included to maintain the same layout. | 139 // This declaration should be only included conditionally, but is included to maintain the same layout. |
222 virtual void launch_continuation(boost::unique_lock<boost::mutex>&) | 140 virtual void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base>) |
223 { | 141 { |
224 } | 142 } |
225 | 143 |
226 shared_state_base(): | 144 shared_state_base(): |
227 done(false), | 145 done(false), |
146 is_valid_(true), | |
228 is_deferred_(false), | 147 is_deferred_(false), |
148 is_constructed(false), | |
149 cnt_(0), | |
229 policy_(launch::none), | 150 policy_(launch::none), |
230 is_constructed(false), | 151 continuations() |
231 thread_was_interrupted(false), | |
232 continuation_ptr() | |
233 {} | 152 {} |
234 virtual ~shared_state_base() | 153 virtual ~shared_state_base() |
154 { | |
155 BOOST_ASSERT(cnt_==0); | |
156 } | |
157 virtual void block_if_needed(boost::unique_lock<boost::mutex>&) | |
235 {} | 158 {} |
159 | |
160 bool valid(boost::unique_lock<boost::mutex>&) { return is_valid_; } | |
161 bool valid() { | |
162 boost::unique_lock<boost::mutex> lk(this->mutex); | |
163 return valid(lk); | |
164 } | |
165 void invalidate(boost::unique_lock<boost::mutex>&) { is_valid_ = false; } | |
166 void invalidate() { | |
167 boost::unique_lock<boost::mutex> lk(this->mutex); | |
168 invalidate(lk); | |
169 } | |
170 void validate(boost::unique_lock<boost::mutex>&) { is_valid_ = true; } | |
171 void validate() { | |
172 boost::unique_lock<boost::mutex> lk(this->mutex); | |
173 validate(lk); | |
174 } | |
175 | |
176 void inc(boost::unique_lock<boost::mutex>&) { ++cnt_; } | |
177 void inc() { boost::unique_lock<boost::mutex> lk(this->mutex); inc(lk); } | |
178 | |
179 void dec(boost::unique_lock<boost::mutex>& lk) { | |
180 if (--cnt_ == 0) { | |
181 block_if_needed(lk); | |
182 } | |
183 } | |
184 void dec() { boost::unique_lock<boost::mutex> lk(this->mutex); dec(lk); } | |
236 | 185 |
237 void set_deferred() | 186 void set_deferred() |
238 { | 187 { |
239 is_deferred_ = true; | 188 is_deferred_ = true; |
240 policy_ = launch::deferred; | 189 policy_ = launch::deferred; |
242 void set_async() | 191 void set_async() |
243 { | 192 { |
244 is_deferred_ = false; | 193 is_deferred_ = false; |
245 policy_ = launch::async; | 194 policy_ = launch::async; |
246 } | 195 } |
247 | 196 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS |
248 waiter_list::iterator register_external_waiter(boost::condition_variable_any& cv) | 197 void set_executor() |
249 { | 198 { |
250 boost::unique_lock<boost::mutex> lock(mutex); | 199 is_deferred_ = false; |
200 policy_ = launch::executor; | |
201 } | |
202 #endif | |
203 notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv) | |
204 { | |
205 boost::unique_lock<boost::mutex> lock(this->mutex); | |
251 do_callback(lock); | 206 do_callback(lock); |
252 return external_waiters.insert(external_waiters.end(),&cv); | 207 return external_waiters.insert(external_waiters.end(),&cv); |
253 } | 208 } |
254 | 209 |
255 void remove_external_waiter(waiter_list::iterator it) | 210 void unnotify_when_ready(notify_when_ready_handle it) |
256 { | 211 { |
257 boost::lock_guard<boost::mutex> lock(mutex); | 212 boost::lock_guard<boost::mutex> lock(this->mutex); |
258 external_waiters.erase(it); | 213 external_waiters.erase(it); |
259 } | 214 } |
260 | 215 |
261 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | 216 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION |
262 void do_continuation(boost::unique_lock<boost::mutex>& lock) | 217 void do_continuation(boost::unique_lock<boost::mutex>& lock) |
263 { | 218 { |
264 if (continuation_ptr) { | 219 if (! continuations.empty()) { |
265 continuation_ptr->launch_continuation(lock); | 220 continuations_type the_continuations = continuations; |
266 if (! lock.owns_lock()) | 221 continuations.clear(); |
267 lock.lock(); | 222 relocker rlk(lock); |
268 continuation_ptr.reset(); | 223 for (continuations_type::iterator it = the_continuations.begin(); it != the_continuations.end(); ++it) { |
224 boost::unique_lock<boost::mutex> cont_lock((*it)->mutex); | |
225 (*it)->launch_continuation(cont_lock, *it); | |
226 } | |
269 } | 227 } |
270 } | 228 } |
271 #else | 229 #else |
272 void do_continuation(boost::unique_lock<boost::mutex>&) | 230 void do_continuation(boost::unique_lock<boost::mutex>&) |
273 { | 231 { |
274 } | 232 } |
275 #endif | 233 #endif |
276 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | 234 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION |
277 void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock) | 235 virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock) |
278 { | 236 { |
279 continuation_ptr= continuation; | 237 continuations.push_back(continuation); |
280 if (done) { | 238 if (done) { |
281 do_continuation(lock); | 239 do_continuation(lock); |
282 } | 240 } |
283 } | 241 } |
284 #endif | 242 #endif |
293 } | 251 } |
294 do_continuation(lock); | 252 do_continuation(lock); |
295 } | 253 } |
296 void make_ready() | 254 void make_ready() |
297 { | 255 { |
298 boost::unique_lock<boost::mutex> lock(mutex); | 256 boost::unique_lock<boost::mutex> lock(this->mutex); |
299 mark_finished_internal(lock); | 257 mark_finished_internal(lock); |
300 } | 258 } |
301 | 259 |
302 void do_callback(boost::unique_lock<boost::mutex>& lock) | 260 void do_callback(boost::unique_lock<boost::mutex>& lock) |
303 { | 261 { |
307 relocker relock(lock); | 265 relocker relock(lock); |
308 local_callback(); | 266 local_callback(); |
309 } | 267 } |
310 } | 268 } |
311 | 269 |
270 virtual bool run_if_is_deferred() | |
271 { | |
272 boost::unique_lock<boost::mutex> lk(this->mutex); | |
273 if (is_deferred_) | |
274 { | |
275 is_deferred_=false; | |
276 execute(lk); | |
277 return true; | |
278 } | |
279 else | |
280 return false; | |
281 } | |
282 virtual bool run_if_is_deferred_or_ready() | |
283 { | |
284 boost::unique_lock<boost::mutex> lk(this->mutex); | |
285 if (is_deferred_) | |
286 { | |
287 is_deferred_=false; | |
288 execute(lk); | |
289 | |
290 return true; | |
291 } | |
292 else | |
293 return done; | |
294 } | |
312 void wait_internal(boost::unique_lock<boost::mutex> &lk, bool rethrow=true) | 295 void wait_internal(boost::unique_lock<boost::mutex> &lk, bool rethrow=true) |
313 { | 296 { |
314 do_callback(lk); | 297 do_callback(lk); |
315 //if (!done) // fixme why this doesn't work? | 298 if (is_deferred_) |
316 { | 299 { |
317 if (is_deferred_) | 300 is_deferred_=false; |
318 { | 301 execute(lk); |
319 is_deferred_=false; | |
320 execute(lk); | |
321 //lk.unlock(); | |
322 } | |
323 else | |
324 { | |
325 while(!done) | |
326 { | |
327 waiters.wait(lk); | |
328 } | |
329 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
330 if(rethrow && thread_was_interrupted) | |
331 { | |
332 throw boost::thread_interrupted(); | |
333 } | |
334 #endif | |
335 if(rethrow && exception) | |
336 { | |
337 boost::rethrow_exception(exception); | |
338 } | |
339 } | |
340 } | 302 } |
341 } | 303 while(!done) |
342 | 304 { |
343 virtual void wait(bool rethrow=true) | 305 waiters.wait(lk); |
344 { | 306 } |
345 boost::unique_lock<boost::mutex> lock(mutex); | 307 if(rethrow && exception) |
308 { | |
309 boost::rethrow_exception(exception); | |
310 } | |
311 } | |
312 | |
313 virtual void wait(boost::unique_lock<boost::mutex>& lock, bool rethrow=true) | |
314 { | |
346 wait_internal(lock, rethrow); | 315 wait_internal(lock, rethrow); |
316 } | |
317 | |
318 void wait(bool rethrow=true) | |
319 { | |
320 boost::unique_lock<boost::mutex> lock(this->mutex); | |
321 wait(lock, rethrow); | |
347 } | 322 } |
348 | 323 |
349 #if defined BOOST_THREAD_USES_DATETIME | 324 #if defined BOOST_THREAD_USES_DATETIME |
350 bool timed_wait_until(boost::system_time const& target_time) | 325 bool timed_wait_until(boost::system_time const& target_time) |
351 { | 326 { |
352 boost::unique_lock<boost::mutex> lock(mutex); | 327 boost::unique_lock<boost::mutex> lock(this->mutex); |
353 if (is_deferred_) | 328 if (is_deferred_) |
354 return false; | 329 return false; |
355 | 330 |
356 do_callback(lock); | 331 do_callback(lock); |
357 while(!done) | 332 while(!done) |
369 | 344 |
370 template <class Clock, class Duration> | 345 template <class Clock, class Duration> |
371 future_status | 346 future_status |
372 wait_until(const chrono::time_point<Clock, Duration>& abs_time) | 347 wait_until(const chrono::time_point<Clock, Duration>& abs_time) |
373 { | 348 { |
374 boost::unique_lock<boost::mutex> lock(mutex); | 349 boost::unique_lock<boost::mutex> lock(this->mutex); |
375 if (is_deferred_) | 350 if (is_deferred_) |
376 return future_status::deferred; | 351 return future_status::deferred; |
377 do_callback(lock); | 352 do_callback(lock); |
378 while(!done) | 353 while(!done) |
379 { | 354 { |
392 mark_finished_internal(lock); | 367 mark_finished_internal(lock); |
393 } | 368 } |
394 | 369 |
395 void mark_exceptional_finish() | 370 void mark_exceptional_finish() |
396 { | 371 { |
397 boost::unique_lock<boost::mutex> lock(mutex); | 372 boost::unique_lock<boost::mutex> lock(this->mutex); |
398 mark_exceptional_finish_internal(boost::current_exception(), lock); | 373 mark_exceptional_finish_internal(boost::current_exception(), lock); |
399 } | 374 } |
400 | 375 |
401 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
402 void mark_interrupted_finish() | |
403 { | |
404 boost::unique_lock<boost::mutex> lock(mutex); | |
405 thread_was_interrupted=true; | |
406 mark_finished_internal(lock); | |
407 } | |
408 | |
409 void set_interrupted_at_thread_exit() | |
410 { | |
411 unique_lock<boost::mutex> lk(mutex); | |
412 thread_was_interrupted=true; | |
413 if (has_value(lk)) | |
414 { | |
415 throw_exception(promise_already_satisfied()); | |
416 } | |
417 detail::make_ready_at_thread_exit(shared_from_this()); | |
418 } | |
419 #endif | |
420 | |
421 void set_exception_at_thread_exit(exception_ptr e) | 376 void set_exception_at_thread_exit(exception_ptr e) |
422 { | 377 { |
423 unique_lock<boost::mutex> lk(mutex); | 378 unique_lock<boost::mutex> lk(this->mutex); |
424 if (has_value(lk)) | 379 if (has_value(lk)) |
425 { | 380 { |
426 throw_exception(promise_already_satisfied()); | 381 throw_exception(promise_already_satisfied()); |
427 } | 382 } |
428 exception=e; | 383 exception=e; |
429 this->is_constructed = true; | 384 this->is_constructed = true; |
430 detail::make_ready_at_thread_exit(shared_from_this()); | 385 detail::make_ready_at_thread_exit(shared_from_this()); |
431 | |
432 } | 386 } |
433 | 387 |
434 bool has_value() const | 388 bool has_value() const |
435 { | 389 { |
436 boost::lock_guard<boost::mutex> lock(mutex); | 390 boost::lock_guard<boost::mutex> lock(this->mutex); |
437 return done && !(exception | 391 return done && ! exception; |
438 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
439 || thread_was_interrupted | |
440 #endif | |
441 ); | |
442 } | 392 } |
443 | 393 |
444 bool has_value(unique_lock<boost::mutex>& ) const | 394 bool has_value(unique_lock<boost::mutex>& ) const |
445 { | 395 { |
446 return done && !(exception | 396 return done && ! exception; |
447 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
448 || thread_was_interrupted | |
449 #endif | |
450 ); | |
451 } | 397 } |
452 | 398 |
453 bool has_exception() const | 399 bool has_exception() const |
454 { | 400 { |
455 boost::lock_guard<boost::mutex> lock(mutex); | 401 boost::lock_guard<boost::mutex> lock(this->mutex); |
456 return done && (exception | 402 return done && exception; |
457 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
458 || thread_was_interrupted | |
459 #endif | |
460 ); | |
461 } | |
462 | |
463 bool has_exception(unique_lock<boost::mutex>&) const | |
464 { | |
465 return done && (exception | |
466 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
467 || thread_was_interrupted | |
468 #endif | |
469 ); | |
470 } | |
471 | |
472 bool is_deferred(boost::lock_guard<boost::mutex>&) const { | |
473 return is_deferred_; | |
474 } | 403 } |
475 | 404 |
476 launch launch_policy(boost::unique_lock<boost::mutex>&) const | 405 launch launch_policy(boost::unique_lock<boost::mutex>&) const |
477 { | 406 { |
478 return policy_; | 407 return policy_; |
479 } | 408 } |
480 | 409 |
481 future_state::state get_state() const | 410 future_state::state get_state(boost::unique_lock<boost::mutex>& lk) const |
482 { | 411 { |
483 boost::lock_guard<boost::mutex> guard(mutex); | |
484 if(!done) | 412 if(!done) |
485 { | 413 { |
486 return future_state::waiting; | 414 return future_state::waiting; |
487 } | 415 } |
488 else | 416 else |
489 { | 417 { |
490 return future_state::ready; | 418 return future_state::ready; |
491 } | 419 } |
492 } | 420 } |
421 future_state::state get_state() const | |
422 { | |
423 boost::lock_guard<boost::mutex> guard(this->mutex); | |
424 if(!done) | |
425 { | |
426 return future_state::waiting; | |
427 } | |
428 else | |
429 { | |
430 return future_state::ready; | |
431 } | |
432 } | |
493 | 433 |
494 exception_ptr get_exception_ptr() | 434 exception_ptr get_exception_ptr() |
495 { | 435 { |
496 boost::unique_lock<boost::mutex> lock(mutex); | 436 boost::unique_lock<boost::mutex> lock(this->mutex); |
497 return get_exception_ptr(lock); | |
498 } | |
499 exception_ptr get_exception_ptr(boost::unique_lock<boost::mutex>& lock) | |
500 { | |
501 wait_internal(lock, false); | 437 wait_internal(lock, false); |
502 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
503 if(thread_was_interrupted) | |
504 { | |
505 return copy_exception(boost::thread_interrupted()); | |
506 } | |
507 #endif | |
508 return exception; | 438 return exception; |
509 } | 439 } |
510 | 440 |
511 template<typename F,typename U> | 441 template<typename F,typename U> |
512 void set_wait_callback(F f,U* u) | 442 void set_wait_callback(F f,U* u) |
513 { | 443 { |
514 boost::lock_guard<boost::mutex> lock(mutex); | 444 boost::lock_guard<boost::mutex> lock(this->mutex); |
515 callback=boost::bind(f,boost::ref(*u)); | 445 callback=boost::bind(f,boost::ref(*u)); |
516 } | 446 } |
517 | 447 |
518 virtual void execute(boost::unique_lock<boost::mutex>&) {} | 448 virtual void execute(boost::unique_lock<boost::mutex>&) {} |
519 | 449 |
520 private: | 450 private: |
521 shared_state_base(shared_state_base const&); | 451 shared_state_base(shared_state_base const&); |
522 shared_state_base& operator=(shared_state_base const&); | 452 shared_state_base& operator=(shared_state_base const&); |
523 }; | 453 }; |
524 | 454 |
525 template<typename T> | |
526 struct future_traits | |
527 { | |
528 typedef boost::scoped_ptr<T> storage_type; | |
529 struct dummy; | |
530 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
531 typedef T const& source_reference_type; | |
532 //typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type; | |
533 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type; | |
534 //typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type; | |
535 typedef T move_dest_type; | |
536 #elif defined BOOST_THREAD_USES_MOVE | |
537 typedef typename boost::mpl::if_c<boost::is_fundamental<T>::value,T,T&>::type source_reference_type; | |
538 //typedef typename boost::mpl::if_c<boost::is_fundamental<T>::value,T,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type; | |
539 //typedef typename boost::mpl::if_c<boost::enable_move_utility_emulation<T>::value,BOOST_THREAD_RV_REF(T),T>::type move_dest_type; | |
540 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type; | |
541 typedef T move_dest_type; | |
542 #else | |
543 typedef T& source_reference_type; | |
544 typedef typename boost::mpl::if_<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type; | |
545 typedef typename boost::mpl::if_<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T>::type move_dest_type; | |
546 #endif | |
547 | |
548 | |
549 typedef const T& shared_future_get_result_type; | |
550 | |
551 static void init(storage_type& storage,source_reference_type t) | |
552 { | |
553 storage.reset(new T(t)); | |
554 } | |
555 | |
556 static void init(storage_type& storage,rvalue_source_type t) | |
557 { | |
558 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES | |
559 storage.reset(new T(boost::forward<T>(t))); | |
560 #else | |
561 storage.reset(new T(static_cast<rvalue_source_type>(t))); | |
562 #endif | |
563 } | |
564 | |
565 static void cleanup(storage_type& storage) | |
566 { | |
567 storage.reset(); | |
568 } | |
569 }; | |
570 | |
571 template<typename T> | |
572 struct future_traits<T&> | |
573 { | |
574 typedef T* storage_type; | |
575 typedef T& source_reference_type; | |
576 //struct rvalue_source_type | |
577 //{}; | |
578 typedef T& move_dest_type; | |
579 typedef T& shared_future_get_result_type; | |
580 | |
581 static void init(storage_type& storage,T& t) | |
582 { | |
583 storage=&t; | |
584 } | |
585 | |
586 static void cleanup(storage_type& storage) | |
587 { | |
588 storage=0; | |
589 } | |
590 }; | |
591 | |
592 template<> | |
593 struct future_traits<void> | |
594 { | |
595 typedef bool storage_type; | |
596 typedef void move_dest_type; | |
597 typedef void shared_future_get_result_type; | |
598 | |
599 static void init(storage_type& storage) | |
600 { | |
601 storage=true; | |
602 } | |
603 | |
604 static void cleanup(storage_type& storage) | |
605 { | |
606 storage=false; | |
607 } | |
608 | |
609 }; | |
610 | |
611 // Used to create stand-alone futures | 455 // Used to create stand-alone futures |
612 template<typename T> | 456 template<typename T> |
613 struct shared_state: | 457 struct shared_state: |
614 detail::shared_state_base | 458 detail::shared_state_base |
615 { | 459 { |
616 typedef typename future_traits<T>::storage_type storage_type; | 460 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL |
617 typedef typename future_traits<T>::source_reference_type source_reference_type; | 461 typedef boost::optional<T> storage_type; |
618 typedef typename future_traits<T>::rvalue_source_type rvalue_source_type; | 462 #else |
619 typedef typename future_traits<T>::move_dest_type move_dest_type; | 463 typedef boost::csbl::unique_ptr<T> storage_type; |
620 typedef typename future_traits<T>::shared_future_get_result_type shared_future_get_result_type; | 464 #endif |
465 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
466 typedef T const& source_reference_type; | |
467 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type; | |
468 typedef T move_dest_type; | |
469 #elif defined BOOST_THREAD_USES_MOVE | |
470 typedef typename conditional<boost::is_fundamental<T>::value,T,T const&>::type source_reference_type; | |
471 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type; | |
472 typedef T move_dest_type; | |
473 #else | |
474 typedef T& source_reference_type; | |
475 typedef typename conditional<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >::value, BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type; | |
476 typedef typename conditional<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >::value, BOOST_THREAD_RV_REF(T),T>::type move_dest_type; | |
477 #endif | |
478 | |
479 typedef const T& shared_future_get_result_type; | |
621 | 480 |
622 storage_type result; | 481 storage_type result; |
623 | 482 |
624 shared_state(): | 483 shared_state(): |
625 result(0) | 484 result() |
626 {} | 485 {} |
627 | 486 |
628 ~shared_state() | 487 ~shared_state() |
629 {} | 488 {} |
630 | 489 |
631 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock) | 490 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock) |
632 { | 491 { |
633 future_traits<T>::init(result,result_); | 492 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL |
493 result = result_; | |
494 #else | |
495 result.reset(new T(result_)); | |
496 #endif | |
634 this->mark_finished_internal(lock); | 497 this->mark_finished_internal(lock); |
635 } | 498 } |
636 | 499 |
637 void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock) | 500 void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock) |
638 { | 501 { |
502 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL | |
503 result = boost::move(result_); | |
504 #elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES | |
505 result.reset(new T(boost::move(result_))); | |
506 #else | |
507 result.reset(new T(static_cast<rvalue_source_type>(result_))); | |
508 #endif | |
509 this->mark_finished_internal(lock); | |
510 } | |
511 | |
512 | |
513 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
514 template <class ...Args> | |
515 void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock, BOOST_THREAD_FWD_REF(Args)... args) | |
516 { | |
517 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL | |
518 result.emplace(boost::forward<Args>(args)...); | |
519 #else | |
520 result.reset(new T(boost::forward<Args>(args)...)); | |
521 #endif | |
522 this->mark_finished_internal(lock); | |
523 } | |
524 #endif | |
525 | |
526 void mark_finished_with_result(source_reference_type result_) | |
527 { | |
528 boost::unique_lock<boost::mutex> lock(this->mutex); | |
529 this->mark_finished_with_result_internal(result_, lock); | |
530 } | |
531 | |
532 void mark_finished_with_result(rvalue_source_type result_) | |
533 { | |
534 boost::unique_lock<boost::mutex> lock(this->mutex); | |
535 | |
639 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES | 536 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES |
640 future_traits<T>::init(result,boost::forward<T>(result_)); | 537 mark_finished_with_result_internal(boost::move(result_), lock); |
641 #else | |
642 future_traits<T>::init(result,static_cast<rvalue_source_type>(result_)); | |
643 #endif | |
644 this->mark_finished_internal(lock); | |
645 } | |
646 | |
647 void mark_finished_with_result(source_reference_type result_) | |
648 { | |
649 boost::unique_lock<boost::mutex> lock(mutex); | |
650 this->mark_finished_with_result_internal(result_, lock); | |
651 } | |
652 | |
653 void mark_finished_with_result(rvalue_source_type result_) | |
654 { | |
655 boost::unique_lock<boost::mutex> lock(mutex); | |
656 | |
657 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES | |
658 mark_finished_with_result_internal(boost::forward<T>(result_), lock); | |
659 #else | 538 #else |
660 mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock); | 539 mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock); |
661 #endif | 540 #endif |
662 } | 541 } |
663 | 542 |
664 virtual move_dest_type get() | 543 storage_type& get_storage(boost::unique_lock<boost::mutex>& lk) |
665 { | 544 { |
666 wait(); | 545 wait_internal(lk); |
667 return boost::move(*result); | 546 return result; |
668 } | 547 } |
669 | 548 virtual move_dest_type get(boost::unique_lock<boost::mutex>& lk) |
670 virtual shared_future_get_result_type get_sh() | 549 { |
671 { | 550 return boost::move(*get_storage(lk)); |
672 wait(); | 551 } |
673 return *result; | 552 move_dest_type get() |
674 } | 553 { |
675 | 554 boost::unique_lock<boost::mutex> lk(this->mutex); |
676 //void set_value_at_thread_exit(const T & result_) | 555 return this->get(lk); |
556 } | |
557 | |
558 virtual shared_future_get_result_type get_sh(boost::unique_lock<boost::mutex>& lk) | |
559 { | |
560 return *get_storage(lk); | |
561 } | |
562 shared_future_get_result_type get_sh() | |
563 { | |
564 boost::unique_lock<boost::mutex> lk(this->mutex); | |
565 return this->get_sh(lk); | |
566 } | |
567 | |
677 void set_value_at_thread_exit(source_reference_type result_) | 568 void set_value_at_thread_exit(source_reference_type result_) |
678 { | 569 { |
679 unique_lock<boost::mutex> lk(this->mutex); | 570 unique_lock<boost::mutex> lk(this->mutex); |
680 if (this->has_value(lk)) | 571 if (this->has_value(lk)) |
681 { | 572 { |
682 throw_exception(promise_already_satisfied()); | 573 throw_exception(promise_already_satisfied()); |
683 } | 574 } |
684 //future_traits<T>::init(result,result_); | 575 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL |
576 result = result_; | |
577 #else | |
685 result.reset(new T(result_)); | 578 result.reset(new T(result_)); |
579 #endif | |
686 | 580 |
687 this->is_constructed = true; | 581 this->is_constructed = true; |
688 detail::make_ready_at_thread_exit(shared_from_this()); | 582 detail::make_ready_at_thread_exit(shared_from_this()); |
689 } | 583 } |
690 //void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T) result_) | |
691 void set_value_at_thread_exit(rvalue_source_type result_) | 584 void set_value_at_thread_exit(rvalue_source_type result_) |
692 { | 585 { |
693 unique_lock<boost::mutex> lk(this->mutex); | 586 unique_lock<boost::mutex> lk(this->mutex); |
694 if (this->has_value(lk)) | 587 if (this->has_value(lk)) |
695 throw_exception(promise_already_satisfied()); | 588 throw_exception(promise_already_satisfied()); |
696 result.reset(new T(boost::move(result_))); | 589 |
697 //future_traits<T>::init(result,static_cast<rvalue_source_type>(result_)); | 590 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES |
591 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL | |
592 result = boost::move(result_); | |
593 #else | |
594 result.reset(new T(boost::move(result_))); | |
595 #endif | |
596 #else | |
597 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL | |
598 result = boost::move(result_); | |
599 #else | |
600 result.reset(new T(static_cast<rvalue_source_type>(result_))); | |
601 #endif | |
602 #endif | |
698 this->is_constructed = true; | 603 this->is_constructed = true; |
699 detail::make_ready_at_thread_exit(shared_from_this()); | 604 detail::make_ready_at_thread_exit(shared_from_this()); |
700 } | 605 } |
701 | |
702 | 606 |
703 private: | 607 private: |
704 shared_state(shared_state const&); | 608 shared_state(shared_state const&); |
705 shared_state& operator=(shared_state const&); | 609 shared_state& operator=(shared_state const&); |
706 }; | 610 }; |
707 | 611 |
708 template<typename T> | 612 template<typename T> |
709 struct shared_state<T&>: | 613 struct shared_state<T&>: |
710 detail::shared_state_base | 614 detail::shared_state_base |
711 { | 615 { |
712 typedef typename future_traits<T&>::storage_type storage_type; | 616 typedef T* storage_type; |
713 typedef typename future_traits<T&>::source_reference_type source_reference_type; | 617 typedef T& source_reference_type; |
714 typedef typename future_traits<T&>::move_dest_type move_dest_type; | 618 typedef T& move_dest_type; |
715 typedef typename future_traits<T&>::shared_future_get_result_type shared_future_get_result_type; | 619 typedef T& shared_future_get_result_type; |
716 | 620 |
717 T* result; | 621 T* result; |
718 | 622 |
719 shared_state(): | 623 shared_state(): |
720 result(0) | 624 result(0) |
724 { | 628 { |
725 } | 629 } |
726 | 630 |
727 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock) | 631 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock) |
728 { | 632 { |
729 //future_traits<T>::init(result,result_); | |
730 result= &result_; | 633 result= &result_; |
731 mark_finished_internal(lock); | 634 mark_finished_internal(lock); |
732 } | 635 } |
733 | 636 |
734 void mark_finished_with_result(source_reference_type result_) | 637 void mark_finished_with_result(source_reference_type result_) |
735 { | 638 { |
736 boost::unique_lock<boost::mutex> lock(mutex); | 639 boost::unique_lock<boost::mutex> lock(this->mutex); |
737 mark_finished_with_result_internal(result_, lock); | 640 mark_finished_with_result_internal(result_, lock); |
738 } | 641 } |
739 | 642 |
740 virtual T& get() | 643 virtual T& get(boost::unique_lock<boost::mutex>& lock) |
741 { | 644 { |
742 wait(); | 645 wait_internal(lock); |
743 return *result; | 646 return *result; |
744 } | 647 } |
745 | 648 T& get() |
746 virtual T& get_sh() | 649 { |
747 { | 650 boost::unique_lock<boost::mutex> lk(this->mutex); |
748 wait(); | 651 return get(lk); |
652 } | |
653 | |
654 virtual T& get_sh(boost::unique_lock<boost::mutex>& lock) | |
655 { | |
656 wait_internal(lock); | |
749 return *result; | 657 return *result; |
658 } | |
659 T& get_sh() | |
660 { | |
661 boost::unique_lock<boost::mutex> lock(this->mutex); | |
662 return get_sh(lock); | |
750 } | 663 } |
751 | 664 |
752 void set_value_at_thread_exit(T& result_) | 665 void set_value_at_thread_exit(T& result_) |
753 { | 666 { |
754 unique_lock<boost::mutex> lk(this->mutex); | 667 unique_lock<boost::mutex> lk(this->mutex); |
755 if (this->has_value(lk)) | 668 if (this->has_value(lk)) |
756 throw_exception(promise_already_satisfied()); | 669 throw_exception(promise_already_satisfied()); |
757 //future_traits<T>::init(result,result_); | |
758 result= &result_; | 670 result= &result_; |
759 this->is_constructed = true; | 671 this->is_constructed = true; |
760 detail::make_ready_at_thread_exit(shared_from_this()); | 672 detail::make_ready_at_thread_exit(shared_from_this()); |
761 } | 673 } |
762 | 674 |
767 | 679 |
768 template<> | 680 template<> |
769 struct shared_state<void>: | 681 struct shared_state<void>: |
770 detail::shared_state_base | 682 detail::shared_state_base |
771 { | 683 { |
772 typedef void shared_future_get_result_type; | 684 typedef void shared_future_get_result_type; |
685 typedef void move_dest_type; | |
773 | 686 |
774 shared_state() | 687 shared_state() |
775 {} | 688 {} |
776 | 689 |
777 void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock) | 690 void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock) |
779 mark_finished_internal(lock); | 692 mark_finished_internal(lock); |
780 } | 693 } |
781 | 694 |
782 void mark_finished_with_result() | 695 void mark_finished_with_result() |
783 { | 696 { |
784 boost::unique_lock<boost::mutex> lock(mutex); | 697 boost::unique_lock<boost::mutex> lock(this->mutex); |
785 mark_finished_with_result_internal(lock); | 698 mark_finished_with_result_internal(lock); |
786 } | 699 } |
787 | 700 |
788 virtual void get() | 701 virtual void get(boost::unique_lock<boost::mutex>& lock) |
789 { | 702 { |
790 this->wait(); | 703 this->wait_internal(lock); |
791 } | 704 } |
792 | 705 void get() |
793 virtual void get_sh() | 706 { |
794 { | 707 boost::unique_lock<boost::mutex> lock(this->mutex); |
795 wait(); | 708 this->get(lock); |
709 } | |
710 | |
711 virtual void get_sh(boost::unique_lock<boost::mutex>& lock) | |
712 { | |
713 this->wait_internal(lock); | |
714 } | |
715 void get_sh() | |
716 { | |
717 boost::unique_lock<boost::mutex> lock(this->mutex); | |
718 this->get_sh(lock); | |
796 } | 719 } |
797 | 720 |
798 void set_value_at_thread_exit() | 721 void set_value_at_thread_exit() |
799 { | 722 { |
800 unique_lock<boost::mutex> lk(this->mutex); | 723 unique_lock<boost::mutex> lk(this->mutex); |
826 public: | 749 public: |
827 future_async_shared_state_base() | 750 future_async_shared_state_base() |
828 { | 751 { |
829 this->set_async(); | 752 this->set_async(); |
830 } | 753 } |
831 explicit future_async_shared_state_base(BOOST_THREAD_RV_REF(boost::thread) th) : | 754 |
832 thr_(boost::move(th)) | 755 virtual void block_if_needed(boost::unique_lock<boost::mutex>& lk) |
833 { | 756 { |
834 this->set_async(); | 757 this->wait(lk, false); |
835 } | 758 } |
836 | 759 |
837 ~future_async_shared_state_base() | 760 ~future_async_shared_state_base() |
838 { | 761 { |
839 join(); | 762 join(); |
840 } | 763 } |
841 | 764 |
842 virtual void wait(bool rethrow) | 765 virtual void wait(boost::unique_lock<boost::mutex>& lk, bool rethrow) |
843 { | 766 { |
844 join(); | 767 { |
845 this->base_type::wait(rethrow); | 768 relocker rlk(lk); |
769 join(); | |
770 } | |
771 this->base_type::wait(lk, rethrow); | |
846 } | 772 } |
847 }; | 773 }; |
848 | 774 |
849 ///////////////////////// | 775 ///////////////////////// |
850 /// future_async_shared_state | 776 /// future_async_shared_state |
851 ///////////////////////// | 777 ///////////////////////// |
852 template<typename Rp, typename Fp> | 778 template<typename Rp, typename Fp> |
853 struct future_async_shared_state: future_async_shared_state_base<Rp> | 779 struct future_async_shared_state: future_async_shared_state_base<Rp> |
854 { | 780 { |
855 typedef future_async_shared_state_base<Rp> base_type; | 781 future_async_shared_state() |
856 | |
857 public: | |
858 explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) : | |
859 base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f))) | |
860 { | 782 { |
861 } | 783 } |
862 | 784 |
863 static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f) | 785 void init(BOOST_THREAD_FWD_REF(Fp) f) |
864 { | 786 { |
787 shared_ptr<boost::detail::shared_state_base> that = this->shared_from_this(); | |
788 this->thr_ = thread(&future_async_shared_state::run, that, boost::forward<Fp>(f)); | |
789 } | |
790 | |
791 static void run(shared_ptr<boost::detail::shared_state_base> that_, BOOST_THREAD_FWD_REF(Fp) f) | |
792 { | |
793 future_async_shared_state* that = dynamic_cast<future_async_shared_state*>(that_.get()); | |
865 try | 794 try |
866 { | 795 { |
867 that->mark_finished_with_result(f()); | 796 that->mark_finished_with_result(f()); |
868 } | 797 } |
869 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
870 catch(thread_interrupted& ) | |
871 { | |
872 that->mark_interrupted_finish(); | |
873 } | |
874 #endif | |
875 catch(...) | 798 catch(...) |
876 { | 799 { |
877 that->mark_exceptional_finish(); | 800 that->mark_exceptional_finish(); |
878 } | 801 } |
879 } | 802 } |
880 }; | 803 }; |
881 | 804 |
882 template<typename Fp> | 805 template<typename Fp> |
883 struct future_async_shared_state<void, Fp>: public future_async_shared_state_base<void> | 806 struct future_async_shared_state<void, Fp>: public future_async_shared_state_base<void> |
884 { | 807 { |
885 typedef future_async_shared_state_base<void> base_type; | 808 void init(BOOST_THREAD_FWD_REF(Fp) f) |
886 | |
887 public: | |
888 explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) : | |
889 base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f))) | |
890 { | 809 { |
810 this->thr_ = thread(&future_async_shared_state::run, this->shared_from_this(), boost::move(f)); | |
891 } | 811 } |
892 | 812 |
893 static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f) | 813 static void run(shared_ptr<boost::detail::shared_state_base> that_, BOOST_THREAD_FWD_REF(Fp) f) |
894 { | 814 { |
815 future_async_shared_state* that = dynamic_cast<future_async_shared_state*>(that_.get()); | |
895 try | 816 try |
896 { | 817 { |
897 f(); | 818 f(); |
898 that->mark_finished_with_result(); | 819 that->mark_finished_with_result(); |
899 } | 820 } |
900 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
901 catch(thread_interrupted& ) | |
902 { | |
903 that->mark_interrupted_finish(); | |
904 } | |
905 #endif | |
906 catch(...) | 821 catch(...) |
907 { | 822 { |
908 that->mark_exceptional_finish(); | 823 that->mark_exceptional_finish(); |
909 } | 824 } |
910 } | 825 } |
911 }; | 826 }; |
912 | 827 |
913 template<typename Rp, typename Fp> | 828 template<typename Rp, typename Fp> |
914 struct future_async_shared_state<Rp&, Fp>: future_async_shared_state_base<Rp&> | 829 struct future_async_shared_state<Rp&, Fp>: future_async_shared_state_base<Rp&> |
915 { | 830 { |
916 typedef future_async_shared_state_base<Rp&> base_type; | 831 void init(BOOST_THREAD_FWD_REF(Fp) f) |
917 | |
918 public: | |
919 explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) : | |
920 base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f))) | |
921 { | 832 { |
833 this->thr_ = thread(&future_async_shared_state::run, this->shared_from_this(), boost::move(f)); | |
922 } | 834 } |
923 | 835 |
924 static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f) | 836 static void run(shared_ptr<boost::detail::shared_state_base> that_, BOOST_THREAD_FWD_REF(Fp) f) |
925 { | 837 { |
838 future_async_shared_state* that = dynamic_cast<future_async_shared_state*>(that_.get()); | |
926 try | 839 try |
927 { | 840 { |
928 that->mark_finished_with_result(f()); | 841 that->mark_finished_with_result(f()); |
929 } | 842 } |
930 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
931 catch(thread_interrupted& ) | |
932 { | |
933 that->mark_interrupted_finish(); | |
934 } | |
935 #endif | |
936 catch(...) | 843 catch(...) |
937 { | 844 { |
938 that->mark_exceptional_finish(); | 845 that->mark_exceptional_finish(); |
939 } | 846 } |
940 } | 847 } |
949 typedef shared_state<Rp> base_type; | 856 typedef shared_state<Rp> base_type; |
950 Fp func_; | 857 Fp func_; |
951 | 858 |
952 public: | 859 public: |
953 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) | 860 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) |
954 : func_(boost::forward<Fp>(f)) | 861 : func_(boost::move(f)) |
955 { | 862 { |
956 this->set_deferred(); | 863 this->set_deferred(); |
957 } | 864 } |
958 | 865 |
959 virtual void execute(boost::unique_lock<boost::mutex>& lck) { | 866 virtual void execute(boost::unique_lock<boost::mutex>& lck) { |
977 typedef shared_state<Rp&> base_type; | 884 typedef shared_state<Rp&> base_type; |
978 Fp func_; | 885 Fp func_; |
979 | 886 |
980 public: | 887 public: |
981 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) | 888 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) |
982 : func_(boost::forward<Fp>(f)) | 889 : func_(boost::move(f)) |
983 { | 890 { |
984 this->set_deferred(); | 891 this->set_deferred(); |
985 } | 892 } |
986 | 893 |
987 virtual void execute(boost::unique_lock<boost::mutex>& lck) { | 894 virtual void execute(boost::unique_lock<boost::mutex>& lck) { |
1002 typedef shared_state<void> base_type; | 909 typedef shared_state<void> base_type; |
1003 Fp func_; | 910 Fp func_; |
1004 | 911 |
1005 public: | 912 public: |
1006 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) | 913 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) |
1007 : func_(boost::forward<Fp>(f)) | 914 : func_(boost::move(f)) |
1008 { | 915 { |
1009 this->set_deferred(); | 916 this->set_deferred(); |
1010 } | 917 } |
1011 | 918 |
1012 virtual void execute(boost::unique_lock<boost::mutex>& lck) { | 919 virtual void execute(boost::unique_lock<boost::mutex>& lck) { |
1023 this->mark_exceptional_finish_internal(current_exception(), lck); | 930 this->mark_exceptional_finish_internal(current_exception(), lck); |
1024 } | 931 } |
1025 } | 932 } |
1026 }; | 933 }; |
1027 | 934 |
1028 // template<typename T, typename Allocator> | |
1029 // struct shared_state_alloc: public shared_state<T> | |
1030 // { | |
1031 // typedef shared_state<T> base; | |
1032 // Allocator alloc_; | |
1033 // | |
1034 // public: | |
1035 // explicit shared_state_alloc(const Allocator& a) | |
1036 // : alloc_(a) {} | |
1037 // | |
1038 // }; | |
1039 class future_waiter | 935 class future_waiter |
1040 { | 936 { |
1041 struct registered_waiter; | 937 struct registered_waiter; |
1042 typedef std::vector<int>::size_type count_type; | 938 typedef std::vector<int>::size_type count_type; |
1043 | 939 |
1044 struct registered_waiter | 940 struct registered_waiter |
1045 { | 941 { |
1046 boost::shared_ptr<detail::shared_state_base> future_; | 942 boost::shared_ptr<detail::shared_state_base> future_; |
1047 detail::shared_state_base::waiter_list::iterator wait_iterator; | 943 detail::shared_state_base::notify_when_ready_handle handle; |
1048 count_type index; | 944 count_type index; |
1049 | 945 |
1050 registered_waiter(boost::shared_ptr<detail::shared_state_base> const& a_future, | 946 registered_waiter(boost::shared_ptr<detail::shared_state_base> const& a_future, |
1051 detail::shared_state_base::waiter_list::iterator wait_iterator_, | 947 detail::shared_state_base::notify_when_ready_handle handle_, |
1052 count_type index_): | 948 count_type index_): |
1053 future_(a_future),wait_iterator(wait_iterator_),index(index_) | 949 future_(a_future),handle(handle_),index(index_) |
1054 {} | 950 {} |
1055 }; | 951 }; |
1056 | 952 |
1057 struct all_futures_lock | 953 struct all_futures_lock |
1058 { | 954 { |
1067 all_futures_lock(std::vector<registered_waiter>& futures): | 963 all_futures_lock(std::vector<registered_waiter>& futures): |
1068 count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count]) | 964 count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count]) |
1069 { | 965 { |
1070 for(count_type_portable i=0;i<count;++i) | 966 for(count_type_portable i=0;i<count;++i) |
1071 { | 967 { |
1072 #if defined __DECCXX || defined __SUNPRO_CC || defined __hpux | 968 locks[i]=BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(futures[i].future_->mutex)); |
1073 locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex).move(); | |
1074 #else | |
1075 locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex); | |
1076 #endif | |
1077 } | 969 } |
1078 } | 970 } |
1079 | 971 |
1080 void lock() | 972 void lock() |
1081 { | 973 { |
1090 } | 982 } |
1091 } | 983 } |
1092 }; | 984 }; |
1093 | 985 |
1094 boost::condition_variable_any cv; | 986 boost::condition_variable_any cv; |
1095 std::vector<registered_waiter> futures; | 987 std::vector<registered_waiter> futures_; |
1096 count_type future_count; | 988 count_type future_count; |
1097 | 989 |
1098 public: | 990 public: |
1099 future_waiter(): | 991 future_waiter(): |
1100 future_count(0) | 992 future_count(0) |
1103 template<typename F> | 995 template<typename F> |
1104 void add(F& f) | 996 void add(F& f) |
1105 { | 997 { |
1106 if(f.future_) | 998 if(f.future_) |
1107 { | 999 { |
1108 futures.push_back(registered_waiter(f.future_,f.future_->register_external_waiter(cv),future_count)); | 1000 registered_waiter waiter(f.future_,f.future_->notify_when_ready(cv),future_count); |
1001 try { | |
1002 futures_.push_back(waiter); | |
1003 } catch(...) { | |
1004 f.future_->unnotify_when_ready(waiter.handle); | |
1005 throw; | |
1006 } | |
1109 } | 1007 } |
1110 ++future_count; | 1008 ++future_count; |
1111 } | 1009 } |
1112 | 1010 |
1011 #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES | |
1012 template<typename F1, typename... Fs> | |
1013 void add(F1& f1, Fs&... fs) | |
1014 { | |
1015 add(f1); add(fs...); | |
1016 } | |
1017 #endif | |
1018 | |
1113 count_type wait() | 1019 count_type wait() |
1114 { | 1020 { |
1115 all_futures_lock lk(futures); | 1021 all_futures_lock lk(futures_); |
1116 for(;;) | 1022 for(;;) |
1117 { | 1023 { |
1118 for(count_type i=0;i<futures.size();++i) | 1024 for(count_type i=0;i<futures_.size();++i) |
1119 { | 1025 { |
1120 if(futures[i].future_->done) | 1026 if(futures_[i].future_->done) |
1121 { | 1027 { |
1122 return futures[i].index; | 1028 return futures_[i].index; |
1123 } | 1029 } |
1124 } | 1030 } |
1125 cv.wait(lk); | 1031 cv.wait(lk); |
1126 } | 1032 } |
1127 } | 1033 } |
1128 | 1034 |
1129 ~future_waiter() | 1035 ~future_waiter() |
1130 { | 1036 { |
1131 for(count_type i=0;i<futures.size();++i) | 1037 for(count_type i=0;i<futures_.size();++i) |
1132 { | 1038 { |
1133 futures[i].future_->remove_external_waiter(futures[i].wait_iterator); | 1039 futures_[i].future_->unnotify_when_ready(futures_[i].handle); |
1134 } | 1040 } |
1135 } | 1041 } |
1136 | |
1137 }; | 1042 }; |
1138 | 1043 |
1139 } | 1044 } |
1140 | 1045 |
1141 template <typename R> | 1046 template <typename R> |
1143 | 1048 |
1144 template <typename R> | 1049 template <typename R> |
1145 class shared_future; | 1050 class shared_future; |
1146 | 1051 |
1147 template<typename T> | 1052 template<typename T> |
1148 struct is_future_type | 1053 struct is_future_type<BOOST_THREAD_FUTURE<T> > : true_type |
1149 { | 1054 { |
1150 BOOST_STATIC_CONSTANT(bool, value=false); | |
1151 typedef void type; | |
1152 }; | 1055 }; |
1153 | 1056 |
1154 template<typename T> | 1057 template<typename T> |
1155 struct is_future_type<BOOST_THREAD_FUTURE<T> > | 1058 struct is_future_type<shared_future<T> > : true_type |
1156 { | 1059 { |
1157 BOOST_STATIC_CONSTANT(bool, value=true); | |
1158 typedef T type; | |
1159 }; | 1060 }; |
1160 | 1061 |
1161 template<typename T> | 1062 // template<typename Iterator> |
1162 struct is_future_type<shared_future<T> > | 1063 // typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end) |
1163 { | 1064 // { |
1164 BOOST_STATIC_CONSTANT(bool, value=true); | 1065 // if(begin==end) |
1165 typedef T type; | 1066 // return end; |
1166 }; | 1067 // |
1167 | 1068 // detail::future_waiter waiter; |
1168 template<typename Iterator> | 1069 // for(Iterator current=begin;current!=end;++current) |
1169 typename boost::disable_if<is_future_type<Iterator>,void>::type wait_for_all(Iterator begin,Iterator end) | 1070 // { |
1170 { | 1071 // waiter.add(*current); |
1171 for(Iterator current=begin;current!=end;++current) | 1072 // } |
1172 { | 1073 // return boost::next(begin,waiter.wait()); |
1173 current->wait(); | 1074 // } |
1174 } | 1075 |
1175 } | 1076 #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES |
1176 | |
1177 template<typename F1,typename F2> | |
1178 typename boost::enable_if<is_future_type<F1>,void>::type wait_for_all(F1& f1,F2& f2) | |
1179 { | |
1180 f1.wait(); | |
1181 f2.wait(); | |
1182 } | |
1183 | |
1184 template<typename F1,typename F2,typename F3> | |
1185 void wait_for_all(F1& f1,F2& f2,F3& f3) | |
1186 { | |
1187 f1.wait(); | |
1188 f2.wait(); | |
1189 f3.wait(); | |
1190 } | |
1191 | |
1192 template<typename F1,typename F2,typename F3,typename F4> | |
1193 void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4) | |
1194 { | |
1195 f1.wait(); | |
1196 f2.wait(); | |
1197 f3.wait(); | |
1198 f4.wait(); | |
1199 } | |
1200 | |
1201 template<typename F1,typename F2,typename F3,typename F4,typename F5> | |
1202 void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5) | |
1203 { | |
1204 f1.wait(); | |
1205 f2.wait(); | |
1206 f3.wait(); | |
1207 f4.wait(); | |
1208 f5.wait(); | |
1209 } | |
1210 | |
1211 template<typename Iterator> | |
1212 typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end) | |
1213 { | |
1214 if(begin==end) | |
1215 return end; | |
1216 | |
1217 detail::future_waiter waiter; | |
1218 for(Iterator current=begin;current!=end;++current) | |
1219 { | |
1220 waiter.add(*current); | |
1221 } | |
1222 return boost::next(begin,waiter.wait()); | |
1223 } | |
1224 | |
1225 template<typename F1,typename F2> | 1077 template<typename F1,typename F2> |
1226 typename boost::enable_if<is_future_type<F1>,unsigned>::type wait_for_any(F1& f1,F2& f2) | 1078 typename boost::enable_if<is_future_type<F1>,unsigned>::type wait_for_any(F1& f1,F2& f2) |
1227 { | 1079 { |
1228 detail::future_waiter waiter; | 1080 detail::future_waiter waiter; |
1229 waiter.add(f1); | 1081 waiter.add(f1); |
1261 waiter.add(f3); | 1113 waiter.add(f3); |
1262 waiter.add(f4); | 1114 waiter.add(f4); |
1263 waiter.add(f5); | 1115 waiter.add(f5); |
1264 return waiter.wait(); | 1116 return waiter.wait(); |
1265 } | 1117 } |
1118 #else | |
1119 template<typename F1, typename... Fs> | |
1120 typename boost::enable_if<is_future_type<F1>, unsigned>::type wait_for_any(F1& f1, Fs&... fs) | |
1121 { | |
1122 detail::future_waiter waiter; | |
1123 waiter.add(f1, fs...); | |
1124 return waiter.wait(); | |
1125 } | |
1126 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
1266 | 1127 |
1267 template <typename R> | 1128 template <typename R> |
1268 class promise; | 1129 class promise; |
1269 | 1130 |
1270 template <typename R> | 1131 template <typename R> |
1273 namespace detail | 1134 namespace detail |
1274 { | 1135 { |
1275 /// Common implementation for all the futures independently of the return type | 1136 /// Common implementation for all the futures independently of the return type |
1276 class base_future | 1137 class base_future |
1277 { | 1138 { |
1278 //BOOST_THREAD_MOVABLE(base_future) | 1139 public: |
1279 | |
1280 }; | 1140 }; |
1281 /// Common implementation for future and shared_future. | 1141 /// Common implementation for future and shared_future. |
1282 template <typename R> | 1142 template <typename R> |
1283 class basic_future : public base_future | 1143 class basic_future : public base_future |
1284 { | 1144 { |
1285 protected: | 1145 protected: |
1286 public: | 1146 public: |
1287 | 1147 |
1288 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr; | 1148 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr; |
1149 typedef typename detail::shared_state<R>::move_dest_type move_dest_type; | |
1150 | |
1151 static //BOOST_CONSTEXPR | |
1152 future_ptr make_exceptional_future_ptr(exceptional_ptr const& ex) { | |
1153 promise<R> p; | |
1154 p.set_exception(ex.ptr_); | |
1155 return p.get_future().future_; | |
1156 } | |
1157 | |
1158 void set_exceptional_if_invalid() { | |
1159 if (valid()) return; | |
1160 promise<R> p; | |
1161 p.set_exception(future_uninitialized()); | |
1162 future_ = p.get_future().future_; | |
1163 } | |
1289 | 1164 |
1290 future_ptr future_; | 1165 future_ptr future_; |
1291 | 1166 |
1292 basic_future(future_ptr a_future): | 1167 basic_future(future_ptr a_future): |
1293 future_(a_future) | 1168 future_(a_future) |
1294 { | 1169 { |
1295 } | 1170 if (a_future) a_future->inc(); |
1296 // Copy construction from a shared_future | 1171 } |
1297 explicit basic_future(const shared_future<R>&) BOOST_NOEXCEPT; | |
1298 | 1172 |
1299 public: | 1173 public: |
1300 typedef future_state::state state; | 1174 typedef future_state::state state; |
1301 | 1175 |
1302 BOOST_THREAD_MOVABLE(basic_future) | 1176 BOOST_THREAD_MOVABLE_ONLY(basic_future) |
1303 basic_future(): future_() {} | 1177 basic_future(): future_() {} |
1304 ~basic_future() {} | 1178 |
1179 | |
1180 //BOOST_CONSTEXPR | |
1181 basic_future(exceptional_ptr const& ex) | |
1182 : future_(make_exceptional_future_ptr(ex)) | |
1183 { | |
1184 future_->inc(); | |
1185 } | |
1186 | |
1187 ~basic_future() { | |
1188 if (future_) future_->dec(); | |
1189 } | |
1305 | 1190 |
1306 basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT: | 1191 basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT: |
1307 future_(BOOST_THREAD_RV(other).future_) | 1192 future_(BOOST_THREAD_RV(other).future_) |
1308 { | 1193 { |
1309 BOOST_THREAD_RV(other).future_.reset(); | 1194 BOOST_THREAD_RV(other).future_.reset(); |
1310 } | 1195 } |
1311 basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT | 1196 basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT |
1312 { | 1197 { |
1198 if (this->future_) { | |
1199 this->future_->dec(); | |
1200 } | |
1313 future_=BOOST_THREAD_RV(other).future_; | 1201 future_=BOOST_THREAD_RV(other).future_; |
1314 BOOST_THREAD_RV(other).future_.reset(); | 1202 BOOST_THREAD_RV(other).future_.reset(); |
1315 return *this; | 1203 return *this; |
1316 } | 1204 } |
1317 void swap(basic_future& that) BOOST_NOEXCEPT | 1205 void swap(basic_future& that) BOOST_NOEXCEPT |
1318 { | 1206 { |
1319 future_.swap(that.future_); | 1207 future_.swap(that.future_); |
1320 } | 1208 } |
1321 // functions to check state, and wait for ready | 1209 // functions to check state, and wait for ready |
1210 state get_state(boost::unique_lock<boost::mutex>& lk) const | |
1211 { | |
1212 if(!future_) | |
1213 { | |
1214 return future_state::uninitialized; | |
1215 } | |
1216 return future_->get_state(lk); | |
1217 } | |
1322 state get_state() const | 1218 state get_state() const |
1323 { | 1219 { |
1324 if(!future_) | 1220 if(!future_) |
1325 { | 1221 { |
1326 return future_state::uninitialized; | 1222 return future_state::uninitialized; |
1331 bool is_ready() const | 1227 bool is_ready() const |
1332 { | 1228 { |
1333 return get_state()==future_state::ready; | 1229 return get_state()==future_state::ready; |
1334 } | 1230 } |
1335 | 1231 |
1232 bool is_ready(boost::unique_lock<boost::mutex>& lk) const | |
1233 { | |
1234 return get_state(lk)==future_state::ready; | |
1235 } | |
1336 bool has_exception() const | 1236 bool has_exception() const |
1337 { | 1237 { |
1338 return future_ && future_->has_exception(); | 1238 return future_ && future_->has_exception(); |
1339 } | 1239 } |
1340 | 1240 |
1356 : exception_ptr(); | 1256 : exception_ptr(); |
1357 } | 1257 } |
1358 | 1258 |
1359 bool valid() const BOOST_NOEXCEPT | 1259 bool valid() const BOOST_NOEXCEPT |
1360 { | 1260 { |
1361 return future_ != 0; | 1261 return future_ != 0 && future_->valid(); |
1362 } | 1262 } |
1363 | |
1364 | 1263 |
1365 void wait() const | 1264 void wait() const |
1366 { | 1265 { |
1367 if(!future_) | 1266 if(!future_) |
1368 { | 1267 { |
1369 boost::throw_exception(future_uninitialized()); | 1268 boost::throw_exception(future_uninitialized()); |
1370 } | 1269 } |
1371 future_->wait(false); | 1270 future_->wait(false); |
1271 } | |
1272 | |
1273 typedef detail::shared_state_base::notify_when_ready_handle notify_when_ready_handle; | |
1274 | |
1275 boost::mutex& mutex() { | |
1276 if(!future_) | |
1277 { | |
1278 boost::throw_exception(future_uninitialized()); | |
1279 } | |
1280 return future_->mutex; | |
1281 }; | |
1282 | |
1283 notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv) | |
1284 { | |
1285 if(!future_) | |
1286 { | |
1287 boost::throw_exception(future_uninitialized()); | |
1288 } | |
1289 return future_->notify_when_ready(cv); | |
1290 } | |
1291 | |
1292 void unnotify_when_ready(notify_when_ready_handle h) | |
1293 { | |
1294 if(!future_) | |
1295 { | |
1296 boost::throw_exception(future_uninitialized()); | |
1297 } | |
1298 return future_->unnotify_when_ready(h); | |
1372 } | 1299 } |
1373 | 1300 |
1374 #if defined BOOST_THREAD_USES_DATETIME | 1301 #if defined BOOST_THREAD_USES_DATETIME |
1375 template<typename Duration> | 1302 template<typename Duration> |
1376 bool timed_wait(Duration const& rel_time) const | 1303 bool timed_wait(Duration const& rel_time) const |
1490 template <class Rp, class Fp> | 1417 template <class Rp, class Fp> |
1491 friend BOOST_THREAD_FUTURE<Rp> | 1418 friend BOOST_THREAD_FUTURE<Rp> |
1492 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); | 1419 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); |
1493 | 1420 |
1494 | 1421 |
1495 typedef typename detail::future_traits<R>::move_dest_type move_dest_type; | 1422 typedef typename base_type::move_dest_type move_dest_type; |
1423 public: // when_all | |
1496 | 1424 |
1497 BOOST_THREAD_FUTURE(future_ptr a_future): | 1425 BOOST_THREAD_FUTURE(future_ptr a_future): |
1498 base_type(a_future) | 1426 base_type(a_future) |
1499 { | 1427 { |
1500 } | 1428 } |
1503 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE) | 1431 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE) |
1504 typedef future_state::state state; | 1432 typedef future_state::state state; |
1505 typedef R value_type; // EXTENSION | 1433 typedef R value_type; // EXTENSION |
1506 | 1434 |
1507 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {} | 1435 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {} |
1436 //BOOST_CONSTEXPR | |
1437 BOOST_THREAD_FUTURE(exceptional_ptr const& ex): | |
1438 base_type(ex) {} | |
1508 | 1439 |
1509 ~BOOST_THREAD_FUTURE() {} | 1440 ~BOOST_THREAD_FUTURE() {} |
1510 | 1441 |
1511 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: | 1442 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: |
1512 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) | 1443 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) |
1513 { | 1444 { |
1514 } | 1445 } |
1515 inline BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION | 1446 inline BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION |
1516 | 1447 |
1448 explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(shared_future<R>) other) : | |
1449 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) | |
1450 {} | |
1451 | |
1517 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT | 1452 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT |
1518 { | 1453 { |
1519 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))); | 1454 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))); |
1520 return *this; | 1455 return *this; |
1521 } | 1456 } |
1538 // todo this function must be private and friendship provided to the internal users. | 1473 // todo this function must be private and friendship provided to the internal users. |
1539 void set_deferred() | 1474 void set_deferred() |
1540 { | 1475 { |
1541 this->future_->set_deferred(); | 1476 this->future_->set_deferred(); |
1542 } | 1477 } |
1543 | 1478 bool run_if_is_deferred() { |
1479 return this->future_->run_if_is_deferred(); | |
1480 } | |
1481 bool run_if_is_deferred_or_ready() { | |
1482 return this->future_->run_if_is_deferred_or_ready(); | |
1483 } | |
1544 // retrieving the value | 1484 // retrieving the value |
1545 move_dest_type get() | 1485 move_dest_type get() |
1546 { | 1486 { |
1547 if(!this->future_) | 1487 if (this->future_ == 0) |
1548 { | 1488 { |
1549 boost::throw_exception(future_uninitialized()); | 1489 boost::throw_exception(future_uninitialized()); |
1550 } | 1490 } |
1551 future_ptr fut_=this->future_; | 1491 unique_lock<boost::mutex> lk(this->future_->mutex); |
1492 if (! this->future_->valid(lk)) | |
1493 { | |
1494 boost::throw_exception(future_uninitialized()); | |
1495 } | |
1552 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET | 1496 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET |
1553 this->future_.reset(); | 1497 this->future_->invalidate(lk); |
1554 #endif | 1498 #endif |
1555 return fut_->get(); | 1499 return this->future_->get(lk); |
1556 } | 1500 } |
1557 | 1501 |
1558 template <typename R2> | 1502 template <typename R2> |
1559 typename boost::disable_if< is_void<R2>, move_dest_type>::type | 1503 typename boost::disable_if< is_void<R2>, move_dest_type>::type |
1560 get_or(BOOST_THREAD_RV_REF(R2) v) | 1504 get_or(BOOST_THREAD_RV_REF(R2) v) |
1561 { | 1505 { |
1562 if(!this->future_) | 1506 |
1507 if (this->future_ == 0) | |
1563 { | 1508 { |
1564 boost::throw_exception(future_uninitialized()); | 1509 boost::throw_exception(future_uninitialized()); |
1565 } | 1510 } |
1566 this->future_->wait(false); | 1511 unique_lock<boost::mutex> lk(this->future_->mutex); |
1567 future_ptr fut_=this->future_; | 1512 if (! this->future_->valid(lk)) |
1513 { | |
1514 boost::throw_exception(future_uninitialized()); | |
1515 } | |
1516 this->future_->wait(lk, false); | |
1568 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET | 1517 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET |
1569 this->future_.reset(); | 1518 this->future_->invalidate(lk); |
1570 #endif | 1519 #endif |
1571 if (fut_->has_value()) { | 1520 |
1572 return fut_->get(); | 1521 if (this->future_->has_value(lk)) { |
1522 return this->future_->get(lk); | |
1573 } | 1523 } |
1574 else { | 1524 else { |
1575 return boost::move(v); | 1525 return boost::move(v); |
1576 } | 1526 } |
1577 } | 1527 } |
1578 | 1528 |
1579 template <typename R2> | 1529 template <typename R2> |
1580 typename boost::disable_if< is_void<R2>, move_dest_type>::type | 1530 typename boost::disable_if< is_void<R2>, move_dest_type>::type |
1581 get_or(R2 const& v) // EXTENSION | 1531 get_or(R2 const& v) // EXTENSION |
1582 { | 1532 { |
1583 if(!this->future_) | 1533 if (this->future_ == 0) |
1584 { | 1534 { |
1585 boost::throw_exception(future_uninitialized()); | 1535 boost::throw_exception(future_uninitialized()); |
1586 } | 1536 } |
1587 this->future_->wait(false); | 1537 unique_lock<boost::mutex> lk(this->future_->mutex); |
1588 future_ptr fut_=this->future_; | 1538 if (! this->future_->valid(lk)) |
1539 { | |
1540 boost::throw_exception(future_uninitialized()); | |
1541 } | |
1542 this->future_->wait(lk, false); | |
1589 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET | 1543 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET |
1590 this->future_.reset(); | 1544 this->future_->invalidate(lk); |
1591 #endif | 1545 #endif |
1592 if (fut_->has_value()) { | 1546 if (this->future_->has_value(lk)) { |
1593 return fut_->get(); | 1547 return this->future_->get(lk); |
1594 } | 1548 } |
1595 else { | 1549 else { |
1596 return v; | 1550 return v; |
1597 } | 1551 } |
1598 } | 1552 } |
1599 | 1553 |
1600 | |
1601 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | 1554 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION |
1602 | |
1603 // template<typename F> | |
1604 // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; | |
1605 | |
1606 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) | |
1607 // template<typename RF> | |
1608 // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&)); | |
1609 // template<typename RF> | |
1610 // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(BOOST_THREAD_FUTURE&)); | |
1611 //#endif | |
1612 template<typename F> | 1555 template<typename F> |
1613 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> | 1556 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> |
1614 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION | 1557 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION |
1615 template<typename F> | 1558 template<typename F> |
1616 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> | 1559 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> |
1617 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION | 1560 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION |
1561 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS | |
1562 template<typename Ex, typename F> | |
1563 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> | |
1564 then(Ex& ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION | |
1565 #endif | |
1618 | 1566 |
1619 template <typename R2> | 1567 template <typename R2> |
1620 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type | 1568 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type |
1621 fallback_to(BOOST_THREAD_RV_REF(R2) v); // EXTENSION | 1569 fallback_to(BOOST_THREAD_RV_REF(R2) v); // EXTENSION |
1622 template <typename R2> | 1570 template <typename R2> |
1623 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type | 1571 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type |
1624 fallback_to(R2 const& v); // EXTENSION | 1572 fallback_to(R2 const& v); // EXTENSION |
1625 | 1573 |
1626 #endif | 1574 #endif |
1627 | |
1628 //#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP | |
1629 // inline | |
1630 // typename boost::enable_if< | |
1631 // is_future_type<value_type>, | |
1632 // value_type | |
1633 // //BOOST_THREAD_FUTURE<typename is_future_type<value_type>::type> | |
1634 // >::type | |
1635 // unwrap(); | |
1636 //#endif | |
1637 | 1575 |
1638 }; | 1576 }; |
1639 | 1577 |
1640 BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END | 1578 BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END |
1641 | 1579 |
1684 | 1622 |
1685 template <class Rp, class Fp> | 1623 template <class Rp, class Fp> |
1686 friend BOOST_THREAD_FUTURE<Rp> | 1624 friend BOOST_THREAD_FUTURE<Rp> |
1687 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); | 1625 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); |
1688 | 1626 |
1689 | 1627 typedef typename base_type::move_dest_type move_dest_type; |
1690 typedef typename detail::future_traits<R>::move_dest_type move_dest_type; | |
1691 | 1628 |
1692 BOOST_THREAD_FUTURE(future_ptr a_future): | 1629 BOOST_THREAD_FUTURE(future_ptr a_future): |
1693 base_type(a_future) | 1630 base_type(a_future) |
1694 { | 1631 { |
1695 } | 1632 } |
1698 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE) | 1635 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE) |
1699 typedef future_state::state state; | 1636 typedef future_state::state state; |
1700 typedef R value_type; // EXTENSION | 1637 typedef R value_type; // EXTENSION |
1701 | 1638 |
1702 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {} | 1639 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {} |
1640 //BOOST_CONSTEXPR | |
1641 BOOST_THREAD_FUTURE(exceptional_ptr const& ex): | |
1642 base_type(ex) {} | |
1703 | 1643 |
1704 ~BOOST_THREAD_FUTURE() {} | 1644 ~BOOST_THREAD_FUTURE() {} |
1705 | 1645 |
1706 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: | 1646 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: |
1707 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) | 1647 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) |
1732 // todo this function must be private and friendship provided to the internal users. | 1672 // todo this function must be private and friendship provided to the internal users. |
1733 void set_deferred() | 1673 void set_deferred() |
1734 { | 1674 { |
1735 this->future_->set_deferred(); | 1675 this->future_->set_deferred(); |
1736 } | 1676 } |
1737 | 1677 bool run_if_is_deferred() { |
1678 return this->future_->run_if_is_deferred(); | |
1679 } | |
1680 bool run_if_is_deferred_or_ready() { | |
1681 return this->future_->run_if_is_deferred_or_ready(); | |
1682 } | |
1738 // retrieving the value | 1683 // retrieving the value |
1739 move_dest_type get() | 1684 move_dest_type get() |
1740 { | 1685 { |
1741 if(!this->future_) | 1686 if (this->future_ == 0) |
1742 { | 1687 { |
1743 boost::throw_exception(future_uninitialized()); | 1688 boost::throw_exception(future_uninitialized()); |
1744 } | 1689 } |
1745 future_ptr fut_=this->future_; | 1690 unique_lock<boost::mutex> lk(this->future_->mutex); |
1746 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET | 1691 if (! this->future_->valid(lk)) |
1747 this->future_.reset(); | |
1748 #endif | |
1749 return fut_->get(); | |
1750 } | |
1751 move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION | |
1752 { | |
1753 if(!this->future_) | |
1754 { | 1692 { |
1755 boost::throw_exception(future_uninitialized()); | 1693 boost::throw_exception(future_uninitialized()); |
1756 } | 1694 } |
1757 this->future_->wait(false); | |
1758 future_ptr fut_=this->future_; | |
1759 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET | 1695 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET |
1760 this->future_.reset(); | 1696 this->future_->invalidate(lk); |
1761 #endif | 1697 #endif |
1762 if (fut_->has_value()) return fut_->get(); | 1698 return this->future_->get(lk); |
1763 else return boost::move(v); | 1699 } |
1764 } | 1700 move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION |
1765 | 1701 { |
1766 move_dest_type get_or(R const& v) // EXTENSION | 1702 if (this->future_ == 0) |
1767 { | |
1768 if(!this->future_) | |
1769 { | 1703 { |
1770 boost::throw_exception(future_uninitialized()); | 1704 boost::throw_exception(future_uninitialized()); |
1771 } | 1705 } |
1772 this->future_->wait(false); | 1706 unique_lock<boost::mutex> lk(this->future_->mutex); |
1773 future_ptr fut_=this->future_; | 1707 if (! this->future_->valid(lk)) |
1708 { | |
1709 boost::throw_exception(future_uninitialized()); | |
1710 } | |
1711 this->future_->wait(lk, false); | |
1774 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET | 1712 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET |
1775 this->future_.reset(); | 1713 this->future_->invalidate(lk); |
1776 #endif | 1714 #endif |
1777 if (fut_->has_value()) return fut_->get(); | 1715 if (this->future_->has_value(lk)) return this->future_->get(lk); |
1716 else return boost::move(v); | |
1717 } | |
1718 | |
1719 move_dest_type get_or(R const& v) // EXTENSION | |
1720 { | |
1721 if (this->future_ == 0) | |
1722 { | |
1723 boost::throw_exception(future_uninitialized()); | |
1724 } | |
1725 unique_lock<boost::mutex> lk(this->future_->mutex); | |
1726 if (! this->future_->valid(lk)) | |
1727 { | |
1728 boost::throw_exception(future_uninitialized()); | |
1729 } | |
1730 this->future_->wait(lk, false); | |
1731 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET | |
1732 this->future_->invalidate(lk); | |
1733 #endif | |
1734 if (this->future_->has_value(lk)) return this->future_->get(lk); | |
1778 else return v; | 1735 else return v; |
1779 } | 1736 } |
1780 | 1737 |
1781 | 1738 |
1782 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | 1739 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION |
1783 | |
1784 // template<typename F> | |
1785 // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; | |
1786 | |
1787 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) | |
1788 // template<typename RF> | |
1789 // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&)); | |
1790 // template<typename RF> | |
1791 // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(BOOST_THREAD_FUTURE&)); | |
1792 //#endif | |
1793 template<typename F> | 1740 template<typename F> |
1794 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> | 1741 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> |
1795 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION | 1742 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION |
1796 template<typename F> | 1743 template<typename F> |
1797 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> | 1744 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> |
1798 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION | 1745 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION |
1746 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS | |
1747 template<typename Ex, typename F> | |
1748 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> | |
1749 then(Ex &ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION | |
1750 #endif | |
1799 #endif | 1751 #endif |
1800 | 1752 |
1801 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP | 1753 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP |
1802 inline | 1754 inline |
1803 BOOST_THREAD_FUTURE<R2> | 1755 BOOST_THREAD_FUTURE<R2> |
1807 }; | 1759 }; |
1808 | 1760 |
1809 template <typename R> | 1761 template <typename R> |
1810 class shared_future : public detail::basic_future<R> | 1762 class shared_future : public detail::basic_future<R> |
1811 { | 1763 { |
1812 | |
1813 typedef detail::basic_future<R> base_type; | 1764 typedef detail::basic_future<R> base_type; |
1814 typedef typename base_type::future_ptr future_ptr; | 1765 typedef typename base_type::future_ptr future_ptr; |
1815 | 1766 |
1816 friend class detail::future_waiter; | 1767 friend class detail::future_waiter; |
1817 friend class promise<R>; | 1768 friend class promise<R>; |
1838 shared_future(future_ptr a_future): | 1789 shared_future(future_ptr a_future): |
1839 base_type(a_future) | 1790 base_type(a_future) |
1840 {} | 1791 {} |
1841 | 1792 |
1842 public: | 1793 public: |
1843 BOOST_THREAD_MOVABLE(shared_future) | 1794 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_future) |
1844 typedef R value_type; // EXTENSION | 1795 typedef R value_type; // EXTENSION |
1845 | 1796 |
1846 shared_future(shared_future const& other): | 1797 shared_future(shared_future const& other): |
1847 base_type(other) | 1798 base_type(other.future_) |
1848 {} | 1799 {} |
1849 | 1800 |
1850 typedef future_state::state state; | 1801 typedef future_state::state state; |
1851 | 1802 |
1852 BOOST_CONSTEXPR shared_future() | 1803 BOOST_CONSTEXPR shared_future() |
1853 {} | 1804 {} |
1854 | 1805 //BOOST_CONSTEXPR |
1806 shared_future(exceptional_ptr const& ex): | |
1807 base_type(ex) {} | |
1855 ~shared_future() | 1808 ~shared_future() |
1856 {} | 1809 {} |
1857 | 1810 |
1858 shared_future& operator=(shared_future const& other) | 1811 shared_future& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_future) other) |
1859 { | 1812 { |
1860 shared_future(other).swap(*this); | 1813 if (other.future_) { |
1814 other.future_->inc(); | |
1815 } | |
1816 if (this->future_) { | |
1817 this->future_->dec(); | |
1818 } | |
1819 this->future_ = other.future_; | |
1861 return *this; | 1820 return *this; |
1862 } | 1821 } |
1822 | |
1863 shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT : | 1823 shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT : |
1864 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) | 1824 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) |
1865 { | 1825 { |
1866 BOOST_THREAD_RV(other).future_.reset(); | |
1867 } | 1826 } |
1868 shared_future(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT : | 1827 shared_future(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT : |
1869 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) | 1828 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) |
1870 { | 1829 { |
1871 } | 1830 } |
1883 | 1842 |
1884 void swap(shared_future& other) BOOST_NOEXCEPT | 1843 void swap(shared_future& other) BOOST_NOEXCEPT |
1885 { | 1844 { |
1886 static_cast<base_type*>(this)->swap(other); | 1845 static_cast<base_type*>(this)->swap(other); |
1887 } | 1846 } |
1888 | 1847 bool run_if_is_deferred() { |
1848 return this->future_->run_if_is_deferred(); | |
1849 } | |
1850 bool run_if_is_deferred_or_ready() { | |
1851 return this->future_->run_if_is_deferred_or_ready(); | |
1852 } | |
1889 // retrieving the value | 1853 // retrieving the value |
1890 typename detail::shared_state<R>::shared_future_get_result_type get() | 1854 typename detail::shared_state<R>::shared_future_get_result_type get() const |
1891 { | 1855 { |
1892 if(!this->future_) | 1856 if(!this->future_) |
1893 { | 1857 { |
1894 boost::throw_exception(future_uninitialized()); | 1858 boost::throw_exception(future_uninitialized()); |
1895 } | 1859 } |
1896 | |
1897 return this->future_->get_sh(); | 1860 return this->future_->get_sh(); |
1898 } | 1861 } |
1899 | 1862 |
1900 template <typename R2> | 1863 template <typename R2> |
1901 typename boost::disable_if< is_void<R2>, typename detail::shared_state<R>::shared_future_get_result_type>::type | 1864 typename boost::disable_if< is_void<R2>, typename detail::shared_state<R>::shared_future_get_result_type>::type |
1902 get_or(BOOST_THREAD_RV_REF(R2) v) // EXTENSION | 1865 get_or(BOOST_THREAD_RV_REF(R2) v) const // EXTENSION |
1903 { | 1866 { |
1904 if(!this->future_) | 1867 if(!this->future_) |
1905 { | 1868 { |
1906 boost::throw_exception(future_uninitialized()); | 1869 boost::throw_exception(future_uninitialized()); |
1907 } | 1870 } |
1908 future_ptr fut_=this->future_; | 1871 this->future_->wait(); |
1909 fut_->wait(); | 1872 if (this->future_->has_value()) return this->future_->get_sh(); |
1910 if (fut_->has_value()) return fut_->get_sh(); | |
1911 else return boost::move(v); | 1873 else return boost::move(v); |
1912 } | 1874 } |
1913 | 1875 |
1914 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | 1876 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION |
1915 | |
1916 // template<typename F> | |
1917 // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; | |
1918 // template<typename F> | |
1919 // auto then(launch, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; | |
1920 | |
1921 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) | |
1922 // template<typename RF> | |
1923 // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(shared_future&)); | |
1924 // template<typename RF> | |
1925 // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(shared_future&)); | |
1926 //#endif | |
1927 template<typename F> | 1877 template<typename F> |
1928 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type> | 1878 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type> |
1929 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION | 1879 then(BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION |
1930 template<typename F> | 1880 template<typename F> |
1931 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type> | 1881 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type> |
1932 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION | 1882 then(launch policy, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION |
1933 #endif | 1883 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS |
1934 //#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP | 1884 template<typename Ex, typename F> |
1935 // inline | 1885 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type> |
1936 // typename boost::enable_if_c< | 1886 then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION |
1937 // is_future_type<value_type>::value, | 1887 #endif |
1938 // BOOST_THREAD_FUTURE<typename is_future_type<value_type>::type> | 1888 #endif |
1939 // >::type | |
1940 // unwrap(); | |
1941 //#endif | |
1942 | 1889 |
1943 }; | 1890 }; |
1944 | 1891 |
1945 BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END | 1892 BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END |
1946 | |
1947 namespace detail | |
1948 { | |
1949 /// Copy construction from a shared_future | |
1950 template <typename R> | |
1951 inline basic_future<R>::basic_future(const shared_future<R>& other) BOOST_NOEXCEPT | |
1952 : future_(other.future_) | |
1953 { | |
1954 } | |
1955 } | |
1956 | 1893 |
1957 template <typename R> | 1894 template <typename R> |
1958 class promise | 1895 class promise |
1959 { | 1896 { |
1960 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr; | 1897 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr; |
1898 | |
1899 typedef typename detail::shared_state<R>::source_reference_type source_reference_type; | |
1900 typedef typename detail::shared_state<R>::rvalue_source_type rvalue_source_type; | |
1901 typedef typename detail::shared_state<R>::move_dest_type move_dest_type; | |
1902 typedef typename detail::shared_state<R>::shared_future_get_result_type shared_future_get_result_type; | |
1961 | 1903 |
1962 future_ptr future_; | 1904 future_ptr future_; |
1963 bool future_obtained; | 1905 bool future_obtained; |
1964 | 1906 |
1965 void lazy_init() | 1907 void lazy_init() |
2047 } | 1989 } |
2048 future_obtained=true; | 1990 future_obtained=true; |
2049 return BOOST_THREAD_FUTURE<R>(future_); | 1991 return BOOST_THREAD_FUTURE<R>(future_); |
2050 } | 1992 } |
2051 | 1993 |
2052 void set_value(typename detail::future_traits<R>::source_reference_type r) | 1994 #if defined BOOST_NO_CXX11_RVALUE_REFERENCES |
1995 template <class TR> | |
1996 typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type set_value(TR const & r) | |
2053 { | 1997 { |
2054 lazy_init(); | 1998 lazy_init(); |
2055 boost::unique_lock<boost::mutex> lock(future_->mutex); | 1999 boost::unique_lock<boost::mutex> lock(future_->mutex); |
2056 if(future_->done) | 2000 if(future_->done) |
2057 { | 2001 { |
2058 boost::throw_exception(promise_already_satisfied()); | 2002 boost::throw_exception(promise_already_satisfied()); |
2059 } | 2003 } |
2060 future_->mark_finished_with_result_internal(r, lock); | 2004 future_->mark_finished_with_result_internal(r, lock); |
2061 } | 2005 } |
2062 | 2006 #else |
2063 // void set_value(R && r); | 2007 void set_value(source_reference_type r) |
2064 void set_value(typename detail::future_traits<R>::rvalue_source_type r) | |
2065 { | 2008 { |
2066 lazy_init(); | 2009 lazy_init(); |
2067 boost::unique_lock<boost::mutex> lock(future_->mutex); | 2010 boost::unique_lock<boost::mutex> lock(future_->mutex); |
2068 if(future_->done) | 2011 if(future_->done) |
2069 { | 2012 { |
2070 boost::throw_exception(promise_already_satisfied()); | 2013 boost::throw_exception(promise_already_satisfied()); |
2071 } | 2014 } |
2072 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES | 2015 future_->mark_finished_with_result_internal(r, lock); |
2073 future_->mark_finished_with_result_internal(boost::forward<R>(r), lock); | 2016 } |
2074 #else | 2017 #endif |
2075 future_->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r), lock); | 2018 |
2076 #endif | 2019 void set_value(rvalue_source_type r) |
2077 } | |
2078 | |
2079 void set_exception(boost::exception_ptr p) | |
2080 { | 2020 { |
2081 lazy_init(); | 2021 lazy_init(); |
2082 boost::unique_lock<boost::mutex> lock(future_->mutex); | 2022 boost::unique_lock<boost::mutex> lock(future_->mutex); |
2083 if(future_->done) | 2023 if(future_->done) |
2084 { | 2024 { |
2085 boost::throw_exception(promise_already_satisfied()); | 2025 boost::throw_exception(promise_already_satisfied()); |
2086 } | 2026 } |
2027 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES | |
2028 future_->mark_finished_with_result_internal(boost::move(r), lock); | |
2029 #else | |
2030 future_->mark_finished_with_result_internal(static_cast<rvalue_source_type>(r), lock); | |
2031 #endif | |
2032 } | |
2033 | |
2034 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
2035 template <class ...Args> | |
2036 void emplace(BOOST_THREAD_FWD_REF(Args) ...args) | |
2037 { | |
2038 lazy_init(); | |
2039 boost::unique_lock<boost::mutex> lock(future_->mutex); | |
2040 if(future_->done) | |
2041 { | |
2042 boost::throw_exception(promise_already_satisfied()); | |
2043 } | |
2044 future_->mark_finished_with_result_internal(lock, boost::forward<Args>(args)...); | |
2045 } | |
2046 | |
2047 #endif | |
2048 | |
2049 void set_exception(boost::exception_ptr p) | |
2050 { | |
2051 lazy_init(); | |
2052 boost::unique_lock<boost::mutex> lock(future_->mutex); | |
2053 if(future_->done) | |
2054 { | |
2055 boost::throw_exception(promise_already_satisfied()); | |
2056 } | |
2087 future_->mark_exceptional_finish_internal(p, lock); | 2057 future_->mark_exceptional_finish_internal(p, lock); |
2088 } | 2058 } |
2089 template <typename E> | 2059 template <typename E> |
2090 void set_exception(E ex) | 2060 void set_exception(E ex) |
2091 { | 2061 { |
2092 set_exception(copy_exception(ex)); | 2062 set_exception(boost::copy_exception(ex)); |
2093 } | 2063 } |
2094 // setting the result with deferred notification | 2064 // setting the result with deferred notification |
2095 void set_value_at_thread_exit(const R& r) | 2065 #if defined BOOST_NO_CXX11_RVALUE_REFERENCES |
2066 template <class TR> | |
2067 typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type set_value_at_thread_exit(TR const& r) | |
2096 { | 2068 { |
2097 if (future_.get()==0) | 2069 if (future_.get()==0) |
2098 { | 2070 { |
2099 boost::throw_exception(promise_moved()); | 2071 boost::throw_exception(promise_moved()); |
2100 } | 2072 } |
2101 future_->set_value_at_thread_exit(r); | 2073 future_->set_value_at_thread_exit(r); |
2102 } | 2074 } |
2103 | 2075 #else |
2076 void set_value_at_thread_exit(source_reference_type r) | |
2077 { | |
2078 if (future_.get()==0) | |
2079 { | |
2080 boost::throw_exception(promise_moved()); | |
2081 } | |
2082 future_->set_value_at_thread_exit(r); | |
2083 } | |
2084 #endif | |
2104 void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r) | 2085 void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r) |
2105 { | 2086 { |
2106 if (future_.get()==0) | 2087 if (future_.get()==0) |
2107 { | 2088 { |
2108 boost::throw_exception(promise_moved()); | 2089 boost::throw_exception(promise_moved()); |
2118 future_->set_exception_at_thread_exit(e); | 2099 future_->set_exception_at_thread_exit(e); |
2119 } | 2100 } |
2120 template <typename E> | 2101 template <typename E> |
2121 void set_exception_at_thread_exit(E ex) | 2102 void set_exception_at_thread_exit(E ex) |
2122 { | 2103 { |
2123 set_exception_at_thread_exit(copy_exception(ex)); | 2104 set_exception_at_thread_exit(boost::copy_exception(ex)); |
2124 } | 2105 } |
2125 | 2106 |
2126 template<typename F> | 2107 template<typename F> |
2127 void set_wait_callback(F f) | 2108 void set_wait_callback(F f) |
2128 { | 2109 { |
2249 future_->mark_exceptional_finish_internal(p, lock); | 2230 future_->mark_exceptional_finish_internal(p, lock); |
2250 } | 2231 } |
2251 template <typename E> | 2232 template <typename E> |
2252 void set_exception(E ex) | 2233 void set_exception(E ex) |
2253 { | 2234 { |
2254 set_exception(copy_exception(ex)); | 2235 set_exception(boost::copy_exception(ex)); |
2255 } | 2236 } |
2256 | 2237 |
2257 // setting the result with deferred notification | 2238 // setting the result with deferred notification |
2258 void set_value_at_thread_exit(R& r) | 2239 void set_value_at_thread_exit(R& r) |
2259 { | 2240 { |
2273 future_->set_exception_at_thread_exit(e); | 2254 future_->set_exception_at_thread_exit(e); |
2274 } | 2255 } |
2275 template <typename E> | 2256 template <typename E> |
2276 void set_exception_at_thread_exit(E ex) | 2257 void set_exception_at_thread_exit(E ex) |
2277 { | 2258 { |
2278 set_exception_at_thread_exit(copy_exception(ex)); | 2259 set_exception_at_thread_exit(boost::copy_exception(ex)); |
2279 } | 2260 } |
2280 | 2261 |
2281 template<typename F> | 2262 template<typename F> |
2282 void set_wait_callback(F f) | 2263 void set_wait_callback(F f) |
2283 { | 2264 { |
2284 lazy_init(); | 2265 lazy_init(); |
2285 future_->set_wait_callback(f,this); | 2266 future_->set_wait_callback(f,this); |
2286 } | 2267 } |
2287 | |
2288 }; | 2268 }; |
2269 | |
2289 template <> | 2270 template <> |
2290 class promise<void> | 2271 class promise<void> |
2291 { | 2272 { |
2292 typedef boost::shared_ptr<detail::shared_state<void> > future_ptr; | 2273 typedef boost::shared_ptr<detail::shared_state<void> > future_ptr; |
2293 | 2274 |
2377 if(future_obtained) | 2358 if(future_obtained) |
2378 { | 2359 { |
2379 boost::throw_exception(future_already_retrieved()); | 2360 boost::throw_exception(future_already_retrieved()); |
2380 } | 2361 } |
2381 future_obtained=true; | 2362 future_obtained=true; |
2363 //return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<void>(future_)); | |
2382 return BOOST_THREAD_FUTURE<void>(future_); | 2364 return BOOST_THREAD_FUTURE<void>(future_); |
2383 } | 2365 } |
2384 | 2366 |
2385 void set_value() | 2367 void set_value() |
2386 { | 2368 { |
2404 future_->mark_exceptional_finish_internal(p,lock); | 2386 future_->mark_exceptional_finish_internal(p,lock); |
2405 } | 2387 } |
2406 template <typename E> | 2388 template <typename E> |
2407 void set_exception(E ex) | 2389 void set_exception(E ex) |
2408 { | 2390 { |
2409 set_exception(copy_exception(ex)); | 2391 set_exception(boost::copy_exception(ex)); |
2410 } | 2392 } |
2411 | 2393 |
2412 // setting the result with deferred notification | 2394 // setting the result with deferred notification |
2413 void set_value_at_thread_exit() | 2395 void set_value_at_thread_exit() |
2414 { | 2396 { |
2428 future_->set_exception_at_thread_exit(e); | 2410 future_->set_exception_at_thread_exit(e); |
2429 } | 2411 } |
2430 template <typename E> | 2412 template <typename E> |
2431 void set_exception_at_thread_exit(E ex) | 2413 void set_exception_at_thread_exit(E ex) |
2432 { | 2414 { |
2433 set_exception_at_thread_exit(copy_exception(ex)); | 2415 set_exception_at_thread_exit(boost::copy_exception(ex)); |
2434 } | 2416 } |
2435 | 2417 |
2436 template<typename F> | 2418 template<typename F> |
2437 void set_wait_callback(F f) | 2419 void set_wait_callback(F f) |
2438 { | 2420 { |
2439 lazy_init(); | 2421 lazy_init(); |
2440 future_->set_wait_callback(f,this); | 2422 future_->set_wait_callback(f,this); |
2441 } | 2423 } |
2442 | 2424 |
2443 }; | 2425 }; |
2444 | 2426 } |
2445 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS | 2427 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS |
2446 namespace container | 2428 namespace boost { namespace container { |
2429 template <class R, class Alloc> | |
2430 struct uses_allocator< ::boost::promise<R> , Alloc> : true_type | |
2447 { | 2431 { |
2448 template <class R, class Alloc> | 2432 }; |
2449 struct uses_allocator<promise<R> , Alloc> : true_type | 2433 }} |
2450 { | 2434 #if ! defined BOOST_NO_CXX11_ALLOCATOR |
2451 }; | 2435 namespace std { |
2452 } | 2436 template <class R, class Alloc> |
2453 #endif | 2437 struct uses_allocator< ::boost::promise<R> , Alloc> : true_type |
2438 { | |
2439 }; | |
2440 } | |
2441 #endif | |
2442 #endif | |
2443 | |
2444 namespace boost | |
2445 { | |
2454 | 2446 |
2455 BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END | 2447 BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END |
2456 | 2448 |
2457 namespace detail | 2449 namespace detail |
2458 { | 2450 { |
2478 started(false) | 2470 started(false) |
2479 {} | 2471 {} |
2480 | 2472 |
2481 void reset() | 2473 void reset() |
2482 { | 2474 { |
2475 // todo The packaged_task::reset must be as if an assignemnt froma new packaged_task with the same function | |
2476 // the reset function is an optimization that avoids reallocating a new task. | |
2483 started=false; | 2477 started=false; |
2478 this->validate(); | |
2484 } | 2479 } |
2485 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 2480 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
2486 virtual void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0; | 2481 virtual void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0; |
2487 void run(BOOST_THREAD_RV_REF(ArgTypes) ... args) | 2482 void run(BOOST_THREAD_RV_REF(ArgTypes) ... args) |
2488 #else | 2483 #else |
2497 boost::throw_exception(task_already_started()); | 2492 boost::throw_exception(task_already_started()); |
2498 } | 2493 } |
2499 started=true; | 2494 started=true; |
2500 } | 2495 } |
2501 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 2496 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
2502 do_run(boost::forward<ArgTypes>(args)...); | 2497 do_run(boost::move(args)...); |
2503 #else | 2498 #else |
2504 do_run(); | 2499 do_run(); |
2505 #endif | 2500 #endif |
2506 } | 2501 } |
2507 | 2502 |
2520 boost::throw_exception(task_already_started()); | 2515 boost::throw_exception(task_already_started()); |
2521 } | 2516 } |
2522 started=true; | 2517 started=true; |
2523 } | 2518 } |
2524 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 2519 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
2525 do_apply(boost::forward<ArgTypes>(args)...); | 2520 do_apply(boost::move(args)...); |
2526 #else | 2521 #else |
2527 do_apply(); | 2522 do_apply(); |
2528 #endif | 2523 #endif |
2529 } | 2524 } |
2530 | 2525 |
2535 { | 2530 { |
2536 started=true; | 2531 started=true; |
2537 this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk); | 2532 this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk); |
2538 } | 2533 } |
2539 } | 2534 } |
2540 | |
2541 }; | 2535 }; |
2542 | 2536 |
2543 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | 2537 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK |
2544 template<typename F, typename R> | 2538 template<typename F, typename R> |
2545 struct task_shared_state; | 2539 struct task_shared_state; |
2567 {} | 2561 {} |
2568 task_shared_state(BOOST_THREAD_RV_REF(F) f_): | 2562 task_shared_state(BOOST_THREAD_RV_REF(F) f_): |
2569 f(boost::move(f_)) | 2563 f(boost::move(f_)) |
2570 {} | 2564 {} |
2571 | 2565 |
2566 F callable() | |
2567 { | |
2568 return boost::move(f); | |
2569 } | |
2570 | |
2572 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 2571 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
2573 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) | 2572 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) |
2574 { | 2573 { |
2575 try | 2574 try |
2576 { | 2575 { |
2577 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...)); | 2576 this->set_value_at_thread_exit(f(boost::move(args)...)); |
2578 } | 2577 } |
2579 #else | 2578 #else |
2580 void do_apply() | 2579 void do_apply() |
2581 { | 2580 { |
2582 try | 2581 try |
2583 { | 2582 { |
2584 this->set_value_at_thread_exit(f()); | 2583 this->set_value_at_thread_exit(f()); |
2585 } | 2584 } |
2586 #endif | 2585 #endif |
2587 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2588 catch(thread_interrupted& ) | |
2589 { | |
2590 this->set_interrupted_at_thread_exit(); | |
2591 } | |
2592 #endif | |
2593 catch(...) | 2586 catch(...) |
2594 { | 2587 { |
2595 this->set_exception_at_thread_exit(current_exception()); | 2588 this->set_exception_at_thread_exit(current_exception()); |
2596 } | 2589 } |
2597 } | 2590 } |
2599 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 2592 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
2600 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) | 2593 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) |
2601 { | 2594 { |
2602 try | 2595 try |
2603 { | 2596 { |
2604 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...)); | 2597 this->mark_finished_with_result(f(boost::move(args)...)); |
2605 } | 2598 } |
2606 #else | 2599 #else |
2607 void do_run() | 2600 void do_run() |
2608 { | 2601 { |
2609 try | 2602 try |
2613 this->mark_finished_with_result(boost::move(res)); | 2606 this->mark_finished_with_result(boost::move(res)); |
2614 #else | 2607 #else |
2615 this->mark_finished_with_result(f()); | 2608 this->mark_finished_with_result(f()); |
2616 #endif | 2609 #endif |
2617 } | 2610 } |
2618 #endif | |
2619 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2620 catch(thread_interrupted& ) | |
2621 { | |
2622 this->mark_interrupted_finish(); | |
2623 } | |
2624 #endif | 2611 #endif |
2625 catch(...) | 2612 catch(...) |
2626 { | 2613 { |
2627 this->mark_exceptional_finish(); | 2614 this->mark_exceptional_finish(); |
2628 } | 2615 } |
2654 {} | 2641 {} |
2655 task_shared_state(BOOST_THREAD_RV_REF(F) f_): | 2642 task_shared_state(BOOST_THREAD_RV_REF(F) f_): |
2656 f(boost::move(f_)) | 2643 f(boost::move(f_)) |
2657 {} | 2644 {} |
2658 | 2645 |
2646 F callable() | |
2647 { | |
2648 return f; | |
2649 } | |
2650 | |
2659 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 2651 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
2660 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) | 2652 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) |
2661 { | 2653 { |
2662 try | 2654 try |
2663 { | 2655 { |
2664 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...)); | 2656 this->set_value_at_thread_exit(f(boost::move(args)...)); |
2665 } | 2657 } |
2666 #else | 2658 #else |
2667 void do_apply() | 2659 void do_apply() |
2668 { | 2660 { |
2669 try | 2661 try |
2670 { | 2662 { |
2671 this->set_value_at_thread_exit(f()); | 2663 this->set_value_at_thread_exit(f()); |
2672 } | 2664 } |
2673 #endif | 2665 #endif |
2674 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2675 catch(thread_interrupted& ) | |
2676 { | |
2677 this->set_interrupted_at_thread_exit(); | |
2678 } | |
2679 #endif | |
2680 catch(...) | 2666 catch(...) |
2681 { | 2667 { |
2682 this->set_exception_at_thread_exit(current_exception()); | 2668 this->set_exception_at_thread_exit(current_exception()); |
2683 } | 2669 } |
2684 } | 2670 } |
2686 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 2672 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
2687 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) | 2673 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) |
2688 { | 2674 { |
2689 try | 2675 try |
2690 { | 2676 { |
2691 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...)); | 2677 this->mark_finished_with_result(f(boost::move(args)...)); |
2692 } | 2678 } |
2693 #else | 2679 #else |
2694 void do_run() | 2680 void do_run() |
2695 { | 2681 { |
2696 try | 2682 try |
2697 { | 2683 { |
2698 R& res((f())); | 2684 R& res((f())); |
2699 this->mark_finished_with_result(res); | 2685 this->mark_finished_with_result(res); |
2700 } | |
2701 #endif | |
2702 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2703 catch(thread_interrupted& ) | |
2704 { | |
2705 this->mark_interrupted_finish(); | |
2706 } | 2686 } |
2707 #endif | 2687 #endif |
2708 catch(...) | 2688 catch(...) |
2709 { | 2689 { |
2710 this->mark_exceptional_finish(); | 2690 this->mark_exceptional_finish(); |
2730 task_base_shared_state<R> | 2710 task_base_shared_state<R> |
2731 #endif | 2711 #endif |
2732 { | 2712 { |
2733 private: | 2713 private: |
2734 task_shared_state(task_shared_state&); | 2714 task_shared_state(task_shared_state&); |
2715 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2716 typedef R (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes) ... ); | |
2717 #else | |
2718 typedef R (*CallableType)(); | |
2719 #endif | |
2735 public: | 2720 public: |
2736 R (*f)(); | 2721 CallableType f; |
2737 task_shared_state(R (*f_)()): | 2722 task_shared_state(CallableType f_): |
2738 f(f_) | 2723 f(f_) |
2739 {} | 2724 {} |
2740 | 2725 |
2726 CallableType callable() | |
2727 { | |
2728 return f; | |
2729 } | |
2741 | 2730 |
2742 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 2731 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
2743 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) | 2732 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) |
2744 { | 2733 { |
2745 try | 2734 try |
2746 { | 2735 { |
2747 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...)); | 2736 this->set_value_at_thread_exit(f(boost::move(args)...)); |
2748 } | 2737 } |
2749 #else | 2738 #else |
2750 void do_apply() | 2739 void do_apply() |
2751 { | 2740 { |
2752 try | 2741 try |
2753 { | 2742 { |
2754 R r((f())); | 2743 R r((f())); |
2755 this->set_value_at_thread_exit(boost::move(r)); | 2744 this->set_value_at_thread_exit(boost::move(r)); |
2756 } | 2745 } |
2757 #endif | 2746 #endif |
2758 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2759 catch(thread_interrupted& ) | |
2760 { | |
2761 this->set_interrupted_at_thread_exit(); | |
2762 } | |
2763 #endif | |
2764 catch(...) | 2747 catch(...) |
2765 { | 2748 { |
2766 this->set_exception_at_thread_exit(current_exception()); | 2749 this->set_exception_at_thread_exit(current_exception()); |
2767 } | 2750 } |
2768 } | 2751 } |
2771 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 2754 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
2772 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) | 2755 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) |
2773 { | 2756 { |
2774 try | 2757 try |
2775 { | 2758 { |
2776 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...)); | 2759 this->mark_finished_with_result(f(boost::move(args)...)); |
2777 } | 2760 } |
2778 #else | 2761 #else |
2779 void do_run() | 2762 void do_run() |
2780 { | 2763 { |
2781 try | 2764 try |
2782 { | 2765 { |
2783 R res((f())); | 2766 R res((f())); |
2784 this->mark_finished_with_result(boost::move(res)); | 2767 this->mark_finished_with_result(boost::move(res)); |
2785 } | |
2786 #endif | |
2787 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2788 catch(thread_interrupted& ) | |
2789 { | |
2790 this->mark_interrupted_finish(); | |
2791 } | 2768 } |
2792 #endif | 2769 #endif |
2793 catch(...) | 2770 catch(...) |
2794 { | 2771 { |
2795 this->mark_exceptional_finish(); | 2772 this->mark_exceptional_finish(); |
2813 #endif | 2790 #endif |
2814 { | 2791 { |
2815 private: | 2792 private: |
2816 task_shared_state(task_shared_state&); | 2793 task_shared_state(task_shared_state&); |
2817 public: | 2794 public: |
2818 R& (*f)(); | 2795 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
2819 task_shared_state(R& (*f_)()): | 2796 typedef R& (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes) ... ); |
2797 #else | |
2798 typedef R& (*CallableType)(); | |
2799 #endif | |
2800 CallableType f; | |
2801 task_shared_state(CallableType f_): | |
2820 f(f_) | 2802 f(f_) |
2821 {} | 2803 {} |
2822 | 2804 |
2805 CallableType callable() | |
2806 { | |
2807 return boost::move(f); | |
2808 } | |
2823 | 2809 |
2824 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 2810 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
2825 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) | 2811 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) |
2826 { | 2812 { |
2827 try | 2813 try |
2828 { | 2814 { |
2829 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...)); | 2815 this->set_value_at_thread_exit(f(boost::move(args)...)); |
2830 } | 2816 } |
2831 #else | 2817 #else |
2832 void do_apply() | 2818 void do_apply() |
2833 { | 2819 { |
2834 try | 2820 try |
2835 { | 2821 { |
2836 this->set_value_at_thread_exit(f()); | 2822 this->set_value_at_thread_exit(f()); |
2837 } | |
2838 #endif | |
2839 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2840 catch(thread_interrupted& ) | |
2841 { | |
2842 this->set_interrupted_at_thread_exit(); | |
2843 } | 2823 } |
2844 #endif | 2824 #endif |
2845 catch(...) | 2825 catch(...) |
2846 { | 2826 { |
2847 this->set_exception_at_thread_exit(current_exception()); | 2827 this->set_exception_at_thread_exit(current_exception()); |
2852 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 2832 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
2853 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) | 2833 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) |
2854 { | 2834 { |
2855 try | 2835 try |
2856 { | 2836 { |
2857 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...)); | 2837 this->mark_finished_with_result(f(boost::move(args)...)); |
2858 } | 2838 } |
2859 #else | 2839 #else |
2860 void do_run() | 2840 void do_run() |
2861 { | 2841 { |
2862 try | 2842 try |
2863 { | 2843 { |
2864 this->mark_finished_with_result(f()); | 2844 this->mark_finished_with_result(f()); |
2865 } | |
2866 #endif | |
2867 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2868 catch(thread_interrupted& ) | |
2869 { | |
2870 this->mark_interrupted_finish(); | |
2871 } | 2845 } |
2872 #endif | 2846 #endif |
2873 catch(...) | 2847 catch(...) |
2874 { | 2848 { |
2875 this->mark_exceptional_finish(); | 2849 this->mark_exceptional_finish(); |
2894 #endif | 2868 #endif |
2895 { | 2869 { |
2896 private: | 2870 private: |
2897 task_shared_state(task_shared_state&); | 2871 task_shared_state(task_shared_state&); |
2898 public: | 2872 public: |
2873 typedef F CallableType; | |
2899 F f; | 2874 F f; |
2900 task_shared_state(F const& f_): | 2875 task_shared_state(F const& f_): |
2901 f(f_) | 2876 f(f_) |
2902 {} | 2877 {} |
2903 task_shared_state(BOOST_THREAD_RV_REF(F) f_): | 2878 task_shared_state(BOOST_THREAD_RV_REF(F) f_): |
2904 f(boost::move(f_)) | 2879 f(boost::move(f_)) |
2905 {} | 2880 {} |
2906 | 2881 F callable() |
2882 { | |
2883 return boost::move(f); | |
2884 } | |
2907 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 2885 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
2908 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) | 2886 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) |
2909 { | 2887 { |
2910 try | 2888 try |
2911 { | 2889 { |
2912 f(boost::forward<ArgTypes>(args)...); | 2890 f(boost::move(args)...); |
2913 #else | 2891 #else |
2914 void do_apply() | 2892 void do_apply() |
2915 { | 2893 { |
2916 try | 2894 try |
2917 { | 2895 { |
2918 f(); | 2896 f(); |
2919 #endif | 2897 #endif |
2920 this->set_value_at_thread_exit(); | 2898 this->set_value_at_thread_exit(); |
2921 } | 2899 } |
2922 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2923 catch(thread_interrupted& ) | |
2924 { | |
2925 this->set_interrupted_at_thread_exit(); | |
2926 } | |
2927 #endif | |
2928 catch(...) | 2900 catch(...) |
2929 { | 2901 { |
2930 this->set_exception_at_thread_exit(current_exception()); | 2902 this->set_exception_at_thread_exit(current_exception()); |
2931 } | 2903 } |
2932 } | 2904 } |
2934 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 2906 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
2935 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) | 2907 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) |
2936 { | 2908 { |
2937 try | 2909 try |
2938 { | 2910 { |
2939 f(boost::forward<ArgTypes>(args)...); | 2911 f(boost::move(args)...); |
2940 #else | 2912 #else |
2941 void do_run() | 2913 void do_run() |
2942 { | 2914 { |
2943 try | 2915 try |
2944 { | 2916 { |
2945 f(); | 2917 f(); |
2946 #endif | 2918 #endif |
2947 this->mark_finished_with_result(); | 2919 this->mark_finished_with_result(); |
2948 } | 2920 } |
2949 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2950 catch(thread_interrupted& ) | |
2951 { | |
2952 this->mark_interrupted_finish(); | |
2953 } | |
2954 #endif | |
2955 catch(...) | 2921 catch(...) |
2956 { | 2922 { |
2957 this->mark_exceptional_finish(); | 2923 this->mark_exceptional_finish(); |
2958 } | 2924 } |
2959 } | 2925 } |
2975 task_base_shared_state<void> | 2941 task_base_shared_state<void> |
2976 #endif | 2942 #endif |
2977 { | 2943 { |
2978 private: | 2944 private: |
2979 task_shared_state(task_shared_state&); | 2945 task_shared_state(task_shared_state&); |
2946 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2947 typedef void (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes)...); | |
2948 #else | |
2949 typedef void (*CallableType)(); | |
2950 #endif | |
2980 public: | 2951 public: |
2981 void (*f)(); | 2952 CallableType f; |
2982 task_shared_state(void (*f_)()): | 2953 task_shared_state(CallableType f_): |
2983 f(f_) | 2954 f(f_) |
2984 {} | 2955 {} |
2985 | 2956 CallableType callable() |
2957 { | |
2958 return f; | |
2959 } | |
2986 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 2960 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
2987 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) | 2961 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) |
2988 { | 2962 { |
2989 try | 2963 try |
2990 { | 2964 { |
2991 f(boost::forward<ArgTypes>(args)...); | 2965 f(boost::move(args)...); |
2992 #else | 2966 #else |
2993 void do_apply() | 2967 void do_apply() |
2994 { | 2968 { |
2995 try | 2969 try |
2996 { | 2970 { |
2997 f(); | 2971 f(); |
2998 #endif | 2972 #endif |
2999 this->set_value_at_thread_exit(); | 2973 this->set_value_at_thread_exit(); |
3000 } | 2974 } |
3001 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
3002 catch(thread_interrupted& ) | |
3003 { | |
3004 this->set_interrupted_at_thread_exit(); | |
3005 } | |
3006 #endif | |
3007 catch(...) | 2975 catch(...) |
3008 { | 2976 { |
3009 this->set_exception_at_thread_exit(current_exception()); | 2977 this->set_exception_at_thread_exit(current_exception()); |
3010 } | 2978 } |
3011 } | 2979 } |
3013 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 2981 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
3014 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) | 2982 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) |
3015 { | 2983 { |
3016 try | 2984 try |
3017 { | 2985 { |
3018 f(boost::forward<ArgTypes>(args)...); | 2986 f(boost::move(args)...); |
3019 #else | 2987 #else |
3020 void do_run() | 2988 void do_run() |
3021 { | 2989 { |
3022 try | 2990 try |
3023 { | 2991 { |
3024 f(); | 2992 f(); |
3025 #endif | 2993 #endif |
3026 this->mark_finished_with_result(); | 2994 this->mark_finished_with_result(); |
3027 } | 2995 } |
3028 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
3029 catch(thread_interrupted& ) | |
3030 { | |
3031 this->mark_interrupted_finish(); | |
3032 } | |
3033 #endif | |
3034 catch(...) | 2996 catch(...) |
3035 { | 2997 { |
3036 this->mark_exceptional_finish(); | 2998 this->mark_exceptional_finish(); |
3037 } | 2999 } |
3038 } | 3000 } |
3078 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 3040 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
3079 explicit packaged_task(R(*f)(), BOOST_THREAD_FWD_REF(ArgTypes)... args) | 3041 explicit packaged_task(R(*f)(), BOOST_THREAD_FWD_REF(ArgTypes)... args) |
3080 { | 3042 { |
3081 typedef R(*FR)(BOOST_THREAD_FWD_REF(ArgTypes)...); | 3043 typedef R(*FR)(BOOST_THREAD_FWD_REF(ArgTypes)...); |
3082 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type; | 3044 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type; |
3083 task= task_ptr(new task_shared_state_type(f, boost::forward<ArgTypes>(args)...)); | 3045 task= task_ptr(new task_shared_state_type(f, boost::move(args)...)); |
3084 future_obtained=false; | 3046 future_obtained=false; |
3085 } | 3047 } |
3086 #else | 3048 #else |
3087 explicit packaged_task(R(*f)()) | 3049 explicit packaged_task(R(*f)()) |
3088 { | 3050 { |
3106 template <class F> | 3068 template <class F> |
3107 explicit packaged_task(BOOST_THREAD_FWD_REF(F) f | 3069 explicit packaged_task(BOOST_THREAD_FWD_REF(F) f |
3108 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0 | 3070 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0 |
3109 ) | 3071 ) |
3110 { | 3072 { |
3111 typedef typename remove_cv<typename remove_reference<F>::type>::type FR; | 3073 typedef typename decay<F>::type FR; |
3112 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | 3074 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK |
3113 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 3075 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
3114 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type; | 3076 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type; |
3115 #else | 3077 #else |
3116 typedef detail::task_shared_state<FR,R()> task_shared_state_type; | 3078 typedef detail::task_shared_state<FR,R()> task_shared_state_type; |
3145 explicit packaged_task(BOOST_THREAD_RV_REF(F) f) | 3107 explicit packaged_task(BOOST_THREAD_RV_REF(F) f) |
3146 { | 3108 { |
3147 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | 3109 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK |
3148 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 3110 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
3149 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type; | 3111 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type; |
3150 task = task_ptr(new task_shared_state_type(boost::forward<F>(f))); | 3112 task = task_ptr(new task_shared_state_type(boost::move(f))); |
3151 #else | 3113 #else |
3152 typedef detail::task_shared_state<F,R()> task_shared_state_type; | 3114 typedef detail::task_shared_state<F,R()> task_shared_state_type; |
3153 task = task_ptr(new task_shared_state_type(boost::move(f))); // TODO forward | 3115 task = task_ptr(new task_shared_state_type(boost::move(f))); |
3154 #endif | 3116 #endif |
3155 #else | 3117 #else |
3156 typedef detail::task_shared_state<F,R> task_shared_state_type; | 3118 typedef detail::task_shared_state<F,R> task_shared_state_type; |
3157 task = task_ptr(new task_shared_state_type(boost::forward<F>(f))); | 3119 task = task_ptr(new task_shared_state_type(boost::move(f))); |
3158 #endif | 3120 #endif |
3159 future_obtained=false; | 3121 future_obtained=false; |
3160 | 3122 |
3161 } | 3123 } |
3162 #endif | 3124 #endif |
3187 | 3149 |
3188 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES | 3150 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES |
3189 template <class F, class Allocator> | 3151 template <class F, class Allocator> |
3190 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_REF(F) f) | 3152 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_REF(F) f) |
3191 { | 3153 { |
3192 typedef typename remove_cv<typename remove_reference<F>::type>::type FR; | 3154 typedef typename decay<F>::type FR; |
3155 | |
3193 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | 3156 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK |
3194 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 3157 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
3195 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type; | 3158 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type; |
3196 #else | 3159 #else |
3197 typedef detail::task_shared_state<FR,R()> task_shared_state_type; | 3160 typedef detail::task_shared_state<FR,R()> task_shared_state_type; |
3240 #endif | 3203 #endif |
3241 typedef typename Allocator::template rebind<task_shared_state_type>::other A2; | 3204 typedef typename Allocator::template rebind<task_shared_state_type>::other A2; |
3242 A2 a2(a); | 3205 A2 a2(a); |
3243 typedef thread_detail::allocator_destructor<A2> D; | 3206 typedef thread_detail::allocator_destructor<A2> D; |
3244 | 3207 |
3245 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 3208 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) ); |
3246 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) ); | |
3247 #else | |
3248 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) ); // TODO forward | |
3249 #endif | |
3250 future_obtained = false; | 3209 future_obtained = false; |
3251 } | 3210 } |
3252 | 3211 |
3253 #endif //BOOST_NO_CXX11_RVALUE_REFERENCES | 3212 #endif //BOOST_NO_CXX11_RVALUE_REFERENCES |
3254 #endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS | 3213 #endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS |
3255 | 3214 |
3256 ~packaged_task() | 3215 ~packaged_task() { |
3257 { | 3216 if(task) { |
3258 if(task) | |
3259 { | |
3260 task->owner_destroyed(); | 3217 task->owner_destroyed(); |
3261 } | 3218 } |
3262 } | 3219 } |
3263 | 3220 |
3264 // assignment | 3221 // assignment |
3265 packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT : | 3222 packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT |
3266 future_obtained(BOOST_THREAD_RV(other).future_obtained) | 3223 : future_obtained(BOOST_THREAD_RV(other).future_obtained) { |
3267 { | |
3268 task.swap(BOOST_THREAD_RV(other).task); | 3224 task.swap(BOOST_THREAD_RV(other).task); |
3269 BOOST_THREAD_RV(other).future_obtained=false; | 3225 BOOST_THREAD_RV(other).future_obtained=false; |
3270 } | 3226 } |
3271 packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT | 3227 packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT { |
3272 { | 3228 |
3273 | |
3274 // todo use forward | |
3275 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES | 3229 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES |
3276 packaged_task temp(boost::move(other)); | 3230 packaged_task temp(boost::move(other)); |
3277 #else | 3231 #else |
3278 packaged_task temp(static_cast<BOOST_THREAD_RV_REF(packaged_task)>(other)); | 3232 packaged_task temp(static_cast<BOOST_THREAD_RV_REF(packaged_task)>(other)); |
3279 #endif | 3233 #endif |
3280 swap(temp); | 3234 swap(temp); |
3281 return *this; | 3235 return *this; |
3282 } | 3236 } |
3283 | 3237 |
3284 void reset() | 3238 void reset() { |
3285 { | |
3286 if (!valid()) | 3239 if (!valid()) |
3287 throw future_error(system::make_error_code(future_errc::no_state)); | 3240 throw future_error(system::make_error_code(future_errc::no_state)); |
3241 | |
3242 // As if *this = packaged_task(task->callable()); | |
3243 | |
3288 task->reset(); | 3244 task->reset(); |
3289 future_obtained=false; | 3245 future_obtained=false; |
3290 } | 3246 } |
3291 | 3247 |
3292 void swap(packaged_task& other) BOOST_NOEXCEPT | 3248 void swap(packaged_task& other) BOOST_NOEXCEPT { |
3293 { | |
3294 task.swap(other.task); | 3249 task.swap(other.task); |
3295 std::swap(future_obtained,other.future_obtained); | 3250 std::swap(future_obtained,other.future_obtained); |
3296 } | 3251 } |
3297 bool valid() const BOOST_NOEXCEPT | 3252 bool valid() const BOOST_NOEXCEPT { |
3298 { | |
3299 return task.get()!=0; | 3253 return task.get()!=0; |
3300 } | 3254 } |
3301 | 3255 |
3302 // result retrieval | 3256 // result retrieval |
3303 BOOST_THREAD_FUTURE<R> get_future() | 3257 BOOST_THREAD_FUTURE<R> get_future() { |
3304 { | 3258 if(!task) { |
3305 if(!task) | |
3306 { | |
3307 boost::throw_exception(task_moved()); | 3259 boost::throw_exception(task_moved()); |
3308 } | 3260 } else if(!future_obtained) { |
3309 else if(!future_obtained) | |
3310 { | |
3311 future_obtained=true; | 3261 future_obtained=true; |
3312 return BOOST_THREAD_FUTURE<R>(task); | 3262 return BOOST_THREAD_FUTURE<R>(task); |
3313 } | 3263 } else { |
3314 else | |
3315 { | |
3316 boost::throw_exception(future_already_retrieved()); | 3264 boost::throw_exception(future_already_retrieved()); |
3317 } | 3265 } |
3318 //return BOOST_THREAD_FUTURE<R>(); | |
3319 } | 3266 } |
3320 | 3267 |
3321 // execution | 3268 // execution |
3322 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 3269 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
3323 void operator()(BOOST_THREAD_RV_REF(ArgTypes)... args) | 3270 void operator()(BOOST_THREAD_RV_REF(ArgTypes)... args) { |
3324 { | 3271 if(!task) { |
3325 if(!task) | |
3326 { | |
3327 boost::throw_exception(task_moved()); | 3272 boost::throw_exception(task_moved()); |
3328 } | 3273 } |
3329 task->run(boost::forward<ArgTypes>(args)...); | 3274 task->run(boost::move(args)...); |
3330 } | 3275 } |
3331 void make_ready_at_thread_exit(ArgTypes... args) | 3276 void make_ready_at_thread_exit(ArgTypes... args) { |
3332 { | 3277 if(!task) { |
3333 if(!task) | |
3334 { | |
3335 boost::throw_exception(task_moved()); | 3278 boost::throw_exception(task_moved()); |
3336 } | 3279 } |
3337 if (task->has_value()) | 3280 if (task->has_value()) { |
3338 { | |
3339 boost::throw_exception(promise_already_satisfied()); | 3281 boost::throw_exception(promise_already_satisfied()); |
3340 } | 3282 } |
3341 task->apply(boost::forward<ArgTypes>(args)...); | 3283 task->apply(boost::move(args)...); |
3342 } | 3284 } |
3343 #else | 3285 #else |
3344 void operator()() | 3286 void operator()() { |
3345 { | 3287 if(!task) { |
3346 if(!task) | |
3347 { | |
3348 boost::throw_exception(task_moved()); | 3288 boost::throw_exception(task_moved()); |
3349 } | 3289 } |
3350 task->run(); | 3290 task->run(); |
3351 } | 3291 } |
3352 void make_ready_at_thread_exit() | 3292 void make_ready_at_thread_exit() { |
3353 { | 3293 if(!task) { |
3354 if(!task) | |
3355 { | |
3356 boost::throw_exception(task_moved()); | 3294 boost::throw_exception(task_moved()); |
3357 } | 3295 } |
3358 if (task->has_value()) | 3296 if (task->has_value()) boost::throw_exception(promise_already_satisfied()); |
3359 boost::throw_exception(promise_already_satisfied()); | |
3360 task->apply(); | 3297 task->apply(); |
3361 } | 3298 } |
3362 #endif | 3299 #endif |
3363 template<typename F> | 3300 template<typename F> |
3364 void set_wait_callback(F f) | 3301 void set_wait_callback(F f) { |
3365 { | |
3366 task->set_wait_callback(f,this); | 3302 task->set_wait_callback(f,this); |
3367 } | 3303 } |
3368 }; | 3304 }; |
3369 | 3305 } |
3370 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS | 3306 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS |
3371 namespace container | 3307 namespace boost { namespace container { |
3372 { | 3308 template <class R, class Alloc> |
3373 template <class R, class Alloc> | 3309 struct uses_allocator< ::boost::packaged_task<R> , Alloc> : true_type |
3374 struct uses_allocator<packaged_task<R>, Alloc> | 3310 {}; |
3375 : public true_type {}; | 3311 }} |
3376 } | 3312 #if ! defined BOOST_NO_CXX11_ALLOCATOR |
3377 #endif | 3313 namespace std { |
3378 | 3314 template <class R, class Alloc> |
3379 BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END | 3315 struct uses_allocator< ::boost::packaged_task<R> , Alloc> : true_type |
3380 | 3316 {}; |
3381 namespace detail | 3317 } |
3382 { | 3318 #endif |
3383 //////////////////////////////// | 3319 #endif |
3384 // make_future_deferred_shared_state | 3320 |
3385 //////////////////////////////// | 3321 namespace boost |
3386 template <class Rp, class Fp> | 3322 { |
3387 BOOST_THREAD_FUTURE<Rp> | 3323 BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END |
3388 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) | 3324 |
3389 { | 3325 namespace detail |
3390 shared_ptr<future_deferred_shared_state<Rp, Fp> > | 3326 { |
3391 h(new future_deferred_shared_state<Rp, Fp>(boost::forward<Fp>(f))); | 3327 //////////////////////////////// |
3392 return BOOST_THREAD_FUTURE<Rp>(h); | 3328 // make_future_deferred_shared_state |
3393 } | 3329 //////////////////////////////// |
3394 | 3330 template <class Rp, class Fp> |
3395 //////////////////////////////// | 3331 BOOST_THREAD_FUTURE<Rp> |
3396 // make_future_async_shared_state | 3332 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) { |
3397 //////////////////////////////// | 3333 shared_ptr<future_deferred_shared_state<Rp, Fp> > |
3398 template <class Rp, class Fp> | 3334 h(new future_deferred_shared_state<Rp, Fp>(boost::forward<Fp>(f))); |
3399 BOOST_THREAD_FUTURE<Rp> | 3335 return BOOST_THREAD_FUTURE<Rp>(h); |
3400 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) | 3336 } |
3401 { | 3337 |
3402 shared_ptr<future_async_shared_state<Rp, Fp> > | 3338 //////////////////////////////// |
3403 h(new future_async_shared_state<Rp, Fp>(boost::forward<Fp>(f))); | 3339 // make_future_async_shared_state |
3404 return BOOST_THREAD_FUTURE<Rp>(h); | 3340 //////////////////////////////// |
3405 } | 3341 template <class Rp, class Fp> |
3406 | 3342 BOOST_THREAD_FUTURE<Rp> |
3407 } | 3343 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) { |
3344 shared_ptr<future_async_shared_state<Rp, Fp> > | |
3345 h(new future_async_shared_state<Rp, Fp>()); | |
3346 h->init(boost::forward<Fp>(f)); | |
3347 return BOOST_THREAD_FUTURE<Rp>(h); | |
3348 } | |
3349 } | |
3408 | 3350 |
3409 //////////////////////////////// | 3351 //////////////////////////////// |
3410 // template <class F, class... ArgTypes> | 3352 // template <class F, class... ArgTypes> |
3411 // future<R> async(launch policy, F&&, ArgTypes&&...); | 3353 // future<R> async(launch policy, F&&, ArgTypes&&...); |
3412 //////////////////////////////// | 3354 //////////////////////////////// |
3413 | 3355 |
3414 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR | 3356 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR |
3415 | 3357 |
3416 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | 3358 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
3417 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 3359 template <class R, class... ArgTypes> |
3418 template <class R, class... ArgTypes> | 3360 BOOST_THREAD_FUTURE<R> |
3419 BOOST_THREAD_FUTURE<R> | 3361 async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) { |
3420 async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) | 3362 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...); |
3421 { | 3363 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF; |
3422 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...); | 3364 typedef typename BF::result_type Rp; |
3423 typedef detail::async_func<typename decay<F>::type, typename decay<ArgTypes>::type...> BF; | 3365 |
3424 typedef typename BF::result_type Rp; | 3366 if (underlying_cast<int>(policy) & int(launch::async)) { |
3425 #else | 3367 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>( |
3426 template <class R> | |
3427 BOOST_THREAD_FUTURE<R> | |
3428 async(launch policy, R(*f)()) | |
3429 { | |
3430 typedef packaged_task<R()> packaged_task_type; | |
3431 #endif | |
3432 #else | |
3433 template <class R> | |
3434 BOOST_THREAD_FUTURE<R> | |
3435 async(launch policy, R(*f)()) | |
3436 { | |
3437 typedef packaged_task<R> packaged_task_type; | |
3438 #endif | |
3439 if (int(policy) & int(launch::async)) | |
3440 { | |
3441 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3442 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>( | |
3443 BF( | 3368 BF( |
3444 thread_detail::decay_copy(boost::forward<F>(f)) | 3369 f |
3445 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... | 3370 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... |
3446 ) | 3371 ) |
3447 )); | 3372 )); |
3448 #else | 3373 } else if (underlying_cast<int>(policy) & int(launch::deferred)) { |
3449 packaged_task_type pt( f ); | 3374 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>( |
3450 | |
3451 BOOST_THREAD_FUTURE<R> ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future()); | |
3452 ret.set_async(); | |
3453 boost::thread( boost::move(pt) ).detach(); | |
3454 return ::boost::move(ret); | |
3455 #endif | |
3456 } | |
3457 else if (int(policy) & int(launch::deferred)) | |
3458 { | |
3459 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3460 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>( | |
3461 BF( | 3375 BF( |
3462 thread_detail::decay_copy(boost::forward<F>(f)) | 3376 f |
3463 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... | 3377 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... |
3464 ) | 3378 ) |
3465 )); | 3379 )); |
3466 #else | 3380 } else { |
3467 std::terminate(); | 3381 std::terminate(); |
3468 BOOST_THREAD_FUTURE<R> ret; | 3382 BOOST_THREAD_FUTURE<R> ret; |
3469 return ::boost::move(ret); | 3383 return ::boost::move(ret); |
3470 | 3384 } |
3471 #endif | 3385 } |
3472 } else { | 3386 |
3473 std::terminate(); | 3387 #else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
3474 BOOST_THREAD_FUTURE<R> ret; | 3388 |
3475 return ::boost::move(ret); | 3389 template <class R> |
3476 } | 3390 BOOST_THREAD_FUTURE<R> |
3477 } | 3391 async(launch policy, R(*f)()) { |
3478 | 3392 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK |
3479 #endif | 3393 typedef packaged_task<R()> packaged_task_type; |
3480 | |
3481 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
3482 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3483 | |
3484 template <class F, class ...ArgTypes> | |
3485 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type( | |
3486 typename decay<ArgTypes>::type... | |
3487 )>::type> | |
3488 async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) | |
3489 { | |
3490 | |
3491 typedef typename boost::result_of<typename decay<F>::type( | |
3492 typename decay<ArgTypes>::type... | |
3493 )>::type R; | |
3494 | |
3495 typedef detail::async_func<typename decay<F>::type, typename decay<ArgTypes>::type...> BF; | |
3496 typedef typename BF::result_type Rp; | |
3497 | |
3498 #else | 3394 #else |
3499 template <class F> | 3395 typedef packaged_task<R> packaged_task_type; |
3500 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type> | |
3501 async(launch policy, BOOST_THREAD_FWD_REF(F) f) | |
3502 { | |
3503 typedef typename boost::result_of<typename decay<F>::type()>::type R; | |
3504 typedef packaged_task<R()> packaged_task_type; | |
3505 | |
3506 #endif | 3396 #endif |
3507 #else | 3397 |
3508 template <class F> | 3398 if (underlying_cast<int>(policy) & int(launch::async)) { |
3509 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type> | 3399 packaged_task_type pt( f ); |
3510 async(launch policy, BOOST_THREAD_FWD_REF(F) f) | 3400 BOOST_THREAD_FUTURE<R> ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future()); |
3511 { | 3401 ret.set_async(); |
3512 typedef typename boost::result_of<typename decay<F>::type()>::type R; | 3402 boost::thread( boost::move(pt) ).detach(); |
3513 typedef packaged_task<R> packaged_task_type; | 3403 return ::boost::move(ret); |
3514 | 3404 } else if (underlying_cast<int>(policy) & int(launch::deferred)) { |
3515 #endif | 3405 std::terminate(); |
3516 | 3406 BOOST_THREAD_FUTURE<R> ret; |
3517 if (int(policy) & int(launch::async)) | 3407 return ::boost::move(ret); |
3518 { | 3408 } else { |
3519 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 3409 std::terminate(); |
3520 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>( | 3410 BOOST_THREAD_FUTURE<R> ret; |
3411 return ::boost::move(ret); | |
3412 } | |
3413 } | |
3414 #endif | |
3415 #endif // defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) | |
3416 | |
3417 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3418 | |
3419 template <class F, class ...ArgTypes> | |
3420 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type( | |
3421 typename decay<ArgTypes>::type... | |
3422 )>::type> | |
3423 async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) { | |
3424 typedef typename boost::result_of<typename decay<F>::type( | |
3425 typename decay<ArgTypes>::type... | |
3426 )>::type R; | |
3427 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF; | |
3428 typedef typename BF::result_type Rp; | |
3429 | |
3430 if (underlying_cast<int>(policy) & int(launch::async)) { | |
3431 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>( | |
3521 BF( | 3432 BF( |
3522 thread_detail::decay_copy(boost::forward<F>(f)) | 3433 thread_detail::decay_copy(boost::forward<F>(f)) |
3523 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... | 3434 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... |
3524 ) | 3435 ) |
3525 )); | 3436 )); |
3526 #else | 3437 } else if (underlying_cast<int>(policy) & int(launch::deferred)) { |
3527 packaged_task_type pt( boost::forward<F>(f) ); | 3438 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>( |
3528 | |
3529 BOOST_THREAD_FUTURE<R> ret = pt.get_future(); | |
3530 ret.set_async(); | |
3531 boost::thread( boost::move(pt) ).detach(); | |
3532 return ::boost::move(ret); | |
3533 #endif | |
3534 } | |
3535 else if (int(policy) & int(launch::deferred)) | |
3536 { | |
3537 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3538 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>( | |
3539 BF( | 3439 BF( |
3540 thread_detail::decay_copy(boost::forward<F>(f)) | 3440 thread_detail::decay_copy(boost::forward<F>(f)) |
3541 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... | 3441 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... |
3542 ) | 3442 ) |
3543 )); | 3443 )); |
3544 #else | 3444 } else { |
3545 std::terminate(); | 3445 std::terminate(); |
3546 BOOST_THREAD_FUTURE<R> ret; | 3446 BOOST_THREAD_FUTURE<R> ret; |
3547 return ::boost::move(ret); | 3447 return ::boost::move(ret); |
3548 // return boost::detail::make_future_deferred_shared_state<Rp>( | 3448 } |
3549 // BF( | 3449 } |
3550 // thread_detail::decay_copy(boost::forward<F>(f)) | 3450 |
3551 // ) | 3451 #else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
3552 // ); | 3452 |
3553 #endif | 3453 template <class F> |
3554 | 3454 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type> |
3555 } else { | 3455 async(launch policy, BOOST_THREAD_FWD_REF(F) f) { |
3556 std::terminate(); | 3456 typedef typename boost::result_of<typename decay<F>::type()>::type R; |
3557 BOOST_THREAD_FUTURE<R> ret; | 3457 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK |
3558 return ::boost::move(ret); | 3458 typedef packaged_task<R()> packaged_task_type; |
3559 } | 3459 #else // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK |
3560 } | 3460 typedef packaged_task<R> packaged_task_type; |
3561 | 3461 #endif // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK |
3562 //////////////////////////////// | 3462 |
3563 // template <class F, class... ArgTypes> | 3463 if (underlying_cast<int>(policy) & int(launch::async)) { |
3564 // future<R> async(F&&, ArgTypes&&...); | 3464 packaged_task_type pt( boost::forward<F>(f) ); |
3565 //////////////////////////////// | 3465 BOOST_THREAD_FUTURE<R> ret = pt.get_future(); |
3566 | 3466 ret.set_async(); |
3567 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR | 3467 boost::thread( boost::move(pt) ).detach(); |
3568 | 3468 return ::boost::move(ret); |
3569 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 3469 } else if (underlying_cast<int>(policy) & int(launch::deferred)) { |
3570 template <class R, class... ArgTypes> | 3470 std::terminate(); |
3571 BOOST_THREAD_FUTURE<R> | 3471 BOOST_THREAD_FUTURE<R> ret; |
3572 async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) | 3472 return ::boost::move(ret); |
3573 { | 3473 // return boost::detail::make_future_deferred_shared_state<Rp>( |
3574 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward<ArgTypes>(args)...)); | 3474 // BF( |
3575 } | 3475 // thread_detail::decay_copy(boost::forward<F>(f)) |
3576 #else | 3476 // ) |
3577 template <class R> | 3477 // ); |
3578 BOOST_THREAD_FUTURE<R> | 3478 } else { |
3579 async(R(*f)()) | 3479 std::terminate(); |
3580 { | 3480 BOOST_THREAD_FUTURE<R> ret; |
3581 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f)); | 3481 return ::boost::move(ret); |
3582 } | 3482 } |
3583 #endif | 3483 } |
3584 #endif | 3484 #endif // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) |
3585 | 3485 |
3586 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | 3486 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS |
3587 template <class F, class ...ArgTypes> | 3487 namespace detail { |
3588 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type( | 3488 ///////////////////////// |
3589 typename decay<ArgTypes>::type... | 3489 /// shared_state_nullary_task |
3590 )>::type> | 3490 ///////////////////////// |
3591 async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) | 3491 template<typename Rp, typename Fp> |
3592 { | 3492 struct shared_state_nullary_task |
3593 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f), boost::forward<ArgTypes>(args)...)); | |
3594 } | |
3595 #else | |
3596 template <class F> | |
3597 BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type> | |
3598 async(BOOST_THREAD_RV_REF(F) f) | |
3599 { | 3493 { |
3600 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f))); | 3494 shared_state<Rp>* that; |
3601 } | 3495 Fp f_; |
3602 #endif | 3496 public: |
3603 | 3497 |
3498 shared_state_nullary_task(shared_state<Rp>* st, BOOST_THREAD_FWD_REF(Fp) f) | |
3499 : that(st), f_(boost::move(f)) | |
3500 {}; | |
3501 #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
3502 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task) | |
3503 shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT | |
3504 : that(x.that), f_(x.f_) | |
3505 {} | |
3506 shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT | |
3507 { | |
3508 if (this != &x) { | |
3509 that=x.that; | |
3510 f_=x.f_; | |
3511 } | |
3512 return *this; | |
3513 } | |
3514 // move | |
3515 shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT | |
3516 : that(x.that), f_(boost::move(x.f_)) | |
3517 { | |
3518 x.that=0; | |
3519 } | |
3520 shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT | |
3521 { | |
3522 if (this != &x) { | |
3523 that=x.that; | |
3524 f_=boost::move(x.f_); | |
3525 x.that=0; | |
3526 } | |
3527 return *this; | |
3528 } | |
3529 #endif | |
3530 void operator()() { | |
3531 try { | |
3532 that->mark_finished_with_result(f_()); | |
3533 } catch(...) { | |
3534 that->mark_exceptional_finish(); | |
3535 } | |
3536 } | |
3537 }; | |
3538 | |
3539 template<typename Fp> | |
3540 struct shared_state_nullary_task<void, Fp> | |
3541 { | |
3542 shared_state<void>* that; | |
3543 Fp f_; | |
3544 public: | |
3545 shared_state_nullary_task(shared_state<void>* st, BOOST_THREAD_FWD_REF(Fp) f) | |
3546 : that(st), f_(boost::move(f)) | |
3547 {}; | |
3548 #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
3549 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task) | |
3550 shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT | |
3551 : that(x.that), f_(x.f_) | |
3552 {} | |
3553 shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT | |
3554 { | |
3555 if (this != &x) { | |
3556 that=x.that; | |
3557 f_=x.f_; | |
3558 } | |
3559 return *this; | |
3560 } | |
3561 // move | |
3562 shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT | |
3563 : that(x.that), f_(boost::move(x.f_)) | |
3564 { | |
3565 x.that=0; | |
3566 } | |
3567 shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT { | |
3568 if (this != &x) { | |
3569 that=x.that; | |
3570 f_=boost::move(x.f_); | |
3571 x.that=0; | |
3572 } | |
3573 return *this; | |
3574 } | |
3575 #endif | |
3576 void operator()() { | |
3577 try { | |
3578 f_(); | |
3579 that->mark_finished_with_result(); | |
3580 } catch(...) { | |
3581 that->mark_exceptional_finish(); | |
3582 } | |
3583 } | |
3584 }; | |
3585 | |
3586 template<typename Rp, typename Fp> | |
3587 struct shared_state_nullary_task<Rp&, Fp> | |
3588 { | |
3589 shared_state<Rp&>* that; | |
3590 Fp f_; | |
3591 public: | |
3592 shared_state_nullary_task(shared_state<Rp&>* st, BOOST_THREAD_FWD_REF(Fp) f) | |
3593 : that(st), f_(boost::move(f)) | |
3594 {} | |
3595 #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
3596 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task) | |
3597 shared_state_nullary_task(shared_state_nullary_task const& x) BOOST_NOEXCEPT | |
3598 : that(x.that), f_(x.f_) {} | |
3599 | |
3600 shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT { | |
3601 if (this != &x){ | |
3602 that=x.that; | |
3603 f_=x.f_; | |
3604 } | |
3605 return *this; | |
3606 } | |
3607 // move | |
3608 shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT | |
3609 : that(x.that), f_(boost::move(x.f_)) | |
3610 { | |
3611 x.that=0; | |
3612 } | |
3613 shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT { | |
3614 if (this != &x) { | |
3615 that=x.that; | |
3616 f_=boost::move(x.f_); | |
3617 x.that=0; | |
3618 } | |
3619 return *this; | |
3620 } | |
3621 #endif | |
3622 void operator()() { | |
3623 try { | |
3624 that->mark_finished_with_result(f_()); | |
3625 } catch(...) { | |
3626 that->mark_exceptional_finish(); | |
3627 } | |
3628 } | |
3629 }; | |
3630 | |
3631 ///////////////////////// | |
3632 /// future_executor_shared_state_base | |
3633 ///////////////////////// | |
3634 template<typename Rp, typename Executor> | |
3635 struct future_executor_shared_state: shared_state<Rp> | |
3636 { | |
3637 typedef shared_state<Rp> base_type; | |
3638 protected: | |
3639 public: | |
3640 template<typename Fp> | |
3641 future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) { | |
3642 this->set_executor(); | |
3643 shared_state_nullary_task<Rp,Fp> t(this, boost::forward<Fp>(f)); | |
3644 ex.submit(boost::move(t)); | |
3645 } | |
3646 | |
3647 virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk) | |
3648 { | |
3649 this->wait(lk, false); | |
3650 } | |
3651 | |
3652 ~future_executor_shared_state() {} | |
3653 }; | |
3654 | |
3655 //////////////////////////////// | |
3656 // make_future_executor_shared_state | |
3657 //////////////////////////////// | |
3658 template <class Rp, class Fp, class Executor> | |
3659 BOOST_THREAD_FUTURE<Rp> | |
3660 make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) { | |
3661 shared_ptr<future_executor_shared_state<Rp, Executor> > | |
3662 h(new future_executor_shared_state<Rp, Executor>(ex, boost::forward<Fp>(f))); | |
3663 return BOOST_THREAD_FUTURE<Rp>(h); | |
3664 } | |
3665 | |
3666 } // detail | |
3667 | |
3668 //////////////////////////////// | |
3669 // template <class Executor, class F, class... ArgTypes> | |
3670 // future<R> async(Executor& ex, F&&, ArgTypes&&...); | |
3671 //////////////////////////////// | |
3672 | |
3673 //#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
3674 #if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE) | |
3675 | |
3676 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR | |
3677 | |
3678 template <class Executor, class R, class... ArgTypes> | |
3679 BOOST_THREAD_FUTURE<R> | |
3680 async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) { | |
3681 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...); | |
3682 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF; | |
3683 typedef typename BF::result_type Rp; | |
3684 | |
3685 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex, | |
3686 BF( | |
3687 f | |
3688 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... | |
3689 ) | |
3690 )); | |
3691 } | |
3692 #endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR | |
3693 | |
3694 template <class Executor, class F, class ...ArgTypes> | |
3695 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type( | |
3696 typename decay<ArgTypes>::type... | |
3697 )>::type> | |
3698 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) { | |
3699 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF; | |
3700 typedef typename BF::result_type Rp; | |
3701 | |
3702 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex, | |
3703 BF( | |
3704 thread_detail::decay_copy(boost::forward<F>(f)) | |
3705 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... | |
3706 ) | |
3707 )); | |
3708 } | |
3709 | |
3710 #else // ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
3711 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR | |
3712 | |
3713 template <class Executor, class R> | |
3714 BOOST_THREAD_FUTURE<R> | |
3715 async(Executor& ex, R(*f)()) { | |
3716 typedef R(*F)(); | |
3717 typedef detail::invoker<F> BF; | |
3718 typedef typename BF::result_type Rp; | |
3719 | |
3720 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex, | |
3721 BF( | |
3722 f | |
3723 ) | |
3724 )); | |
3725 } | |
3726 | |
3727 template <class Executor, class R, class A1> | |
3728 BOOST_THREAD_FUTURE<R> | |
3729 async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(A1)), BOOST_THREAD_FWD_REF(A1) a1) { | |
3730 typedef R(*F)(BOOST_THREAD_FWD_REF(A1)); | |
3731 typedef detail::invoker<F, typename decay<A1>::type> BF; | |
3732 typedef typename BF::result_type Rp; | |
3733 | |
3734 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex, | |
3735 BF( | |
3736 f | |
3737 , thread_detail::decay_copy(boost::forward<A1>(a1)) | |
3738 ) | |
3739 )); | |
3740 } | |
3741 #endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR | |
3742 | |
3743 template <class Executor, class F> | |
3744 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type> | |
3745 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f) { | |
3746 typedef detail::invoker<typename decay<F>::type> BF; | |
3747 typedef typename BF::result_type Rp; | |
3748 | |
3749 return boost::detail::make_future_executor_shared_state<Rp>(ex, | |
3750 BF( | |
3751 thread_detail::decay_copy(boost::forward<F>(f)) | |
3752 ) | |
3753 ); | |
3754 } | |
3755 | |
3756 template <class Executor, class F, class A1> | |
3757 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type( | |
3758 typename decay<A1>::type | |
3759 )>::type> | |
3760 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) { | |
3761 typedef detail::invoker<typename decay<F>::type, typename decay<A1>::type> BF; | |
3762 typedef typename BF::result_type Rp; | |
3763 | |
3764 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex, | |
3765 BF( | |
3766 thread_detail::decay_copy(boost::forward<F>(f)) | |
3767 , thread_detail::decay_copy(boost::forward<A1>(a1)) | |
3768 ) | |
3769 )); | |
3770 } | |
3771 | |
3772 template <class Executor, class F, class A1, class A2> | |
3773 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type( | |
3774 typename decay<A1>::type, typename decay<A2>::type | |
3775 )>::type> | |
3776 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) { | |
3777 typedef detail::invoker<typename decay<F>::type, typename decay<A1>::type, typename decay<A2>::type> BF; | |
3778 typedef typename BF::result_type Rp; | |
3779 | |
3780 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex, | |
3781 BF( | |
3782 thread_detail::decay_copy(boost::forward<F>(f)) | |
3783 , thread_detail::decay_copy(boost::forward<A1>(a1)) | |
3784 , thread_detail::decay_copy(boost::forward<A2>(a2)) | |
3785 ) | |
3786 )); | |
3787 } | |
3788 | |
3789 #endif //! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
3790 #endif | |
3791 | |
3792 //////////////////////////////// | |
3793 // template <class F, class... ArgTypes> | |
3794 // future<R> async(F&&, ArgTypes&&...); | |
3795 //////////////////////////////// | |
3796 | |
3797 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR | |
3798 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3799 template <class R, class... ArgTypes> | |
3800 BOOST_THREAD_FUTURE<R> | |
3801 async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) { | |
3802 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward<ArgTypes>(args)...)); | |
3803 } | |
3804 #else | |
3805 template <class R> | |
3806 BOOST_THREAD_FUTURE<R> | |
3807 async(R(*f)()) { | |
3808 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f)); | |
3809 } | |
3810 #endif | |
3811 #endif | |
3812 | |
3813 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3814 template <class F, class ...ArgTypes> | |
3815 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type( | |
3816 typename decay<ArgTypes>::type... | |
3817 )>::type> | |
3818 async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) { | |
3819 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f), boost::forward<ArgTypes>(args)...)); | |
3820 } | |
3821 #else | |
3822 template <class F> | |
3823 BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type> | |
3824 async(BOOST_THREAD_FWD_REF(F) f) { | |
3825 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f))); | |
3826 } | |
3827 #endif | |
3604 | 3828 |
3605 //////////////////////////////// | 3829 //////////////////////////////// |
3606 // make_future deprecated | 3830 // make_future deprecated |
3607 //////////////////////////////// | 3831 //////////////////////////////// |
3608 template <typename T> | 3832 template <typename T> |
3609 BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value) | 3833 BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value) { |
3610 { | |
3611 typedef typename decay<T>::type future_value_type; | 3834 typedef typename decay<T>::type future_value_type; |
3612 promise<future_value_type> p; | 3835 promise<future_value_type> p; |
3613 p.set_value(boost::forward<future_value_type>(value)); | 3836 p.set_value(boost::forward<future_value_type>(value)); |
3614 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | 3837 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); |
3615 } | 3838 } |
3616 | 3839 |
3617 #if defined BOOST_THREAD_USES_MOVE | 3840 #if defined BOOST_THREAD_USES_MOVE |
3618 inline BOOST_THREAD_FUTURE<void> make_future() | 3841 inline BOOST_THREAD_FUTURE<void> make_future() { |
3619 { | |
3620 promise<void> p; | 3842 promise<void> p; |
3621 p.set_value(); | 3843 p.set_value(); |
3622 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | 3844 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); |
3623 } | 3845 } |
3624 #endif | 3846 #endif |
3625 | 3847 |
3626 //////////////////////////////// | 3848 //////////////////////////////// |
3627 // make_ready_future | 3849 // make_ready_future |
3628 //////////////////////////////// | 3850 //////////////////////////////// |
3629 template <typename T> | 3851 namespace detail { |
3630 BOOST_THREAD_FUTURE<typename decay<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value) | 3852 template <class T> |
3853 struct deduced_type_impl | |
3854 { | |
3855 typedef T type; | |
3856 }; | |
3857 | |
3858 template <class T> | |
3859 struct deduced_type_impl<reference_wrapper<T> const> | |
3860 { | |
3861 typedef T& type; | |
3862 }; | |
3863 template <class T> | |
3864 struct deduced_type_impl<reference_wrapper<T> > | |
3865 { | |
3866 typedef T& type; | |
3867 }; | |
3868 #if __cplusplus > 201103L | |
3869 template <class T> | |
3870 struct deduced_type_impl<std::reference_wrapper<T> > | |
3871 { | |
3872 typedef T& type; | |
3873 }; | |
3874 #endif | |
3875 template <class T> | |
3876 struct deduced_type | |
3877 { | |
3878 typedef typename detail::deduced_type_impl<typename decay<T>::type>::type type; | |
3879 }; | |
3880 | |
3881 } | |
3882 | |
3883 | |
3884 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
3885 template <int = 0, int..., class T> | |
3886 #else | |
3887 template <class T> | |
3888 #endif | |
3889 BOOST_THREAD_FUTURE<typename detail::deduced_type<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value) { | |
3890 typedef typename detail::deduced_type<T>::type future_value_type; | |
3891 promise<future_value_type> p; | |
3892 p.set_value(boost::forward<T>(value)); | |
3893 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | |
3894 } | |
3895 | |
3896 // explicit overloads | |
3897 template <class T> | |
3898 BOOST_THREAD_FUTURE<T> make_ready_future(typename remove_reference<T>::type & x) | |
3631 { | 3899 { |
3632 typedef typename decay<T>::type future_value_type; | 3900 promise<T> p; |
3901 p.set_value(x); | |
3902 return p.get_future(); | |
3903 } | |
3904 | |
3905 template <class T> | |
3906 BOOST_THREAD_FUTURE<T> make_ready_future(BOOST_THREAD_FWD_REF(typename remove_reference<T>::type) x) | |
3907 { | |
3908 promise<T> p; | |
3909 p.set_value(forward<typename remove_reference<T>::type>(x)); | |
3910 return p.get_future(); | |
3911 } | |
3912 | |
3913 // variadic overload | |
3914 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
3915 template <class T, class ...Args> | |
3916 BOOST_THREAD_FUTURE<T> make_ready_future(Args&&... args) | |
3917 { | |
3918 promise<T> p; | |
3919 p.emplace(forward<Args>(args)...); | |
3920 return p.get_future(); | |
3921 | |
3922 } | |
3923 #endif | |
3924 | |
3925 template <typename T, typename T1> | |
3926 BOOST_THREAD_FUTURE<T> make_ready_no_decay_future(T1 value) { | |
3927 typedef T future_value_type; | |
3633 promise<future_value_type> p; | 3928 promise<future_value_type> p; |
3634 p.set_value(boost::forward<future_value_type>(value)); | 3929 p.set_value(value); |
3635 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | 3930 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); |
3636 } | 3931 } |
3637 | 3932 |
3638 #if defined BOOST_THREAD_USES_MOVE | 3933 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined BOOST_THREAD_USES_MOVE |
3639 inline BOOST_THREAD_FUTURE<void> make_ready_future() | 3934 inline BOOST_THREAD_FUTURE<void> make_ready_future() { |
3640 { | |
3641 promise<void> p; | 3935 promise<void> p; |
3642 p.set_value(); | 3936 p.set_value(); |
3643 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | 3937 return p.get_future(); |
3644 } | 3938 } |
3645 #endif | 3939 #endif |
3646 | 3940 |
3647 template <typename T> | 3941 template <typename T> |
3648 BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr ex) | 3942 BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr ex) { |
3649 { | |
3650 promise<T> p; | 3943 promise<T> p; |
3651 p.set_exception(ex); | 3944 p.set_exception(ex); |
3652 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | 3945 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); |
3653 } | 3946 } |
3947 | |
3948 template <typename T> | |
3949 BOOST_THREAD_FUTURE<T> make_exceptional_future(exception_ptr ex) { | |
3950 promise<T> p; | |
3951 p.set_exception(ex); | |
3952 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | |
3953 } | |
3954 | |
3654 template <typename T, typename E> | 3955 template <typename T, typename E> |
3655 BOOST_THREAD_FUTURE<T> make_ready_future(E ex) | 3956 BOOST_THREAD_FUTURE<T> make_exceptional_future(E ex) { |
3656 { | |
3657 promise<T> p; | 3957 promise<T> p; |
3658 p.set_exception(boost::copy_exception(ex)); | 3958 p.set_exception(boost::copy_exception(ex)); |
3659 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | 3959 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); |
3960 } | |
3961 | |
3962 template <typename T> | |
3963 BOOST_THREAD_FUTURE<T> make_exceptional_future() { | |
3964 promise<T> p; | |
3965 p.set_exception(boost::current_exception()); | |
3966 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | |
3967 } | |
3968 | |
3969 template <typename T> | |
3970 BOOST_THREAD_FUTURE<T> make_exceptional_future_if_invalid(BOOST_THREAD_FWD_REF(BOOST_THREAD_FUTURE<T>) fut) { | |
3971 fut.set_exceptional_if_invalid(); | |
3972 return boost::move(fut); | |
3973 } | |
3974 template <typename T> | |
3975 shared_future<T> make_exceptional_future_if_invalid(shared_future<T> fut) { | |
3976 fut.set_exceptional_if_invalid(); | |
3977 return fut; | |
3660 } | 3978 } |
3661 | 3979 |
3662 #if 0 | 3980 #if 0 |
3663 template<typename CLOSURE> | 3981 template<typename CLOSURE> |
3664 make_future(CLOSURE closure) -> BOOST_THREAD_FUTURE<decltype(closure())> { | 3982 make_future(CLOSURE closure) -> BOOST_THREAD_FUTURE<decltype(closure())> { |
3665 typedef decltype(closure()) T; | 3983 typedef decltype(closure()) T; |
3666 promise<T> p; | 3984 promise<T> p; |
3667 try | 3985 try { |
3668 { | |
3669 p.set_value(closure()); | 3986 p.set_value(closure()); |
3670 } | 3987 } catch(...) { |
3671 catch(...) | |
3672 { | |
3673 p.set_exception(std::current_exception()); | 3988 p.set_exception(std::current_exception()); |
3674 } | 3989 } |
3675 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | 3990 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); |
3676 } | 3991 } |
3677 #endif | 3992 #endif |
3678 | 3993 |
3679 //////////////////////////////// | 3994 //////////////////////////////// |
3680 // make_shared_future deprecated | 3995 // make_shared_future deprecated |
3681 //////////////////////////////// | 3996 //////////////////////////////// |
3682 template <typename T> | 3997 template <typename T> |
3683 shared_future<typename decay<T>::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value) | 3998 shared_future<typename decay<T>::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value) { |
3684 { | |
3685 typedef typename decay<T>::type future_type; | 3999 typedef typename decay<T>::type future_type; |
3686 promise<future_type> p; | 4000 promise<future_type> p; |
3687 p.set_value(boost::forward<T>(value)); | 4001 p.set_value(boost::forward<T>(value)); |
3688 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share()); | 4002 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share()); |
3689 } | 4003 } |
3690 | 4004 |
3691 | 4005 inline shared_future<void> make_shared_future() { |
3692 inline shared_future<void> make_shared_future() | |
3693 { | |
3694 promise<void> p; | 4006 promise<void> p; |
3695 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share()); | 4007 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share()); |
3696 | 4008 } |
3697 } | |
3698 | |
3699 // //////////////////////////////// | |
3700 // // make_ready_shared_future | |
3701 // //////////////////////////////// | |
3702 // template <typename T> | |
3703 // shared_future<typename decay<T>::type> make_ready_shared_future(BOOST_THREAD_FWD_REF(T) value) | |
3704 // { | |
3705 // typedef typename decay<T>::type future_type; | |
3706 // promise<future_type> p; | |
3707 // p.set_value(boost::forward<T>(value)); | |
3708 // return p.get_future().share(); | |
3709 // } | |
3710 // | |
3711 // | |
3712 // inline shared_future<void> make_ready_shared_future() | |
3713 // { | |
3714 // promise<void> p; | |
3715 // return BOOST_THREAD_MAKE_RV_REF(p.get_future().share()); | |
3716 // | |
3717 // } | |
3718 // | |
3719 // //////////////////////////////// | |
3720 // // make_exceptional_shared_future | |
3721 // //////////////////////////////// | |
3722 // template <typename T> | |
3723 // shared_future<T> make_exceptional_shared_future(exception_ptr ex) | |
3724 // { | |
3725 // promise<T> p; | |
3726 // p.set_exception(ex); | |
3727 // return p.get_future().share(); | |
3728 // } | |
3729 | 4009 |
3730 //////////////////////////////// | 4010 //////////////////////////////// |
3731 // detail::future_async_continuation_shared_state | 4011 // detail::future_async_continuation_shared_state |
3732 //////////////////////////////// | 4012 //////////////////////////////// |
3733 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | 4013 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION |
3734 namespace detail | 4014 namespace detail |
4015 { | |
4016 | |
4017 ///////////////////////// | |
4018 /// future_async_continuation_shared_state | |
4019 ///////////////////////// | |
4020 | |
4021 template<typename F, typename Rp, typename Fp> | |
4022 struct future_async_continuation_shared_state: future_async_shared_state_base<Rp> | |
3735 { | 4023 { |
3736 | 4024 F parent; |
3737 ///////////////////////// | 4025 Fp continuation; |
3738 /// future_async_continuation_shared_state | 4026 shared_ptr<shared_state_base> centinel; |
3739 ///////////////////////// | 4027 |
3740 | 4028 public: |
3741 template<typename F, typename Rp, typename Fp> | 4029 future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) |
3742 struct future_async_continuation_shared_state: future_async_shared_state_base<Rp> | 4030 : parent(boost::move(f)), |
4031 continuation(boost::move(c)), | |
4032 centinel(parent.future_) { | |
4033 } | |
4034 | |
4035 | |
4036 void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base> that) { | |
4037 this->thr_ = thread(&future_async_continuation_shared_state::run, that); | |
4038 } | |
4039 | |
4040 static void run(shared_ptr<boost::detail::shared_state_base> that_) { | |
4041 future_async_continuation_shared_state* that = dynamic_cast<future_async_continuation_shared_state*>(that_.get()); | |
4042 try { | |
4043 that->mark_finished_with_result(that->continuation(boost::move(that->parent))); | |
4044 } catch(...) { | |
4045 that->mark_exceptional_finish(); | |
4046 } | |
4047 } | |
4048 | |
4049 ~future_async_continuation_shared_state() { | |
4050 } | |
4051 }; | |
4052 | |
4053 template<typename F, typename Fp> | |
4054 struct future_async_continuation_shared_state<F, void, Fp>: public future_async_shared_state_base<void> | |
4055 { | |
4056 F parent; | |
4057 Fp continuation; | |
4058 shared_ptr<shared_state_base> centinel; | |
4059 | |
4060 public: | |
4061 future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) | |
4062 : parent(boost::move(f)), | |
4063 continuation(boost::move(c)), | |
4064 centinel(parent.future_) { | |
4065 } | |
4066 | |
4067 void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base> that) { | |
4068 this->thr_ = thread(&future_async_continuation_shared_state::run, that); | |
4069 } | |
4070 | |
4071 static void run(shared_ptr<boost::detail::shared_state_base> that_) { | |
4072 future_async_continuation_shared_state* that = dynamic_cast<future_async_continuation_shared_state*>(that_.get()); | |
4073 try { | |
4074 that->continuation(boost::move(that->parent)); | |
4075 that->mark_finished_with_result(); | |
4076 } catch(...) { | |
4077 that->mark_exceptional_finish(); | |
4078 } | |
4079 } | |
4080 | |
4081 ~future_async_continuation_shared_state() {} | |
4082 | |
4083 }; | |
4084 | |
4085 ///////////////////////// | |
4086 /// future_executor_continuation_shared_state | |
4087 ///////////////////////// | |
4088 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS | |
4089 | |
4090 template <typename FutureExecutorContinuationSharedState> | |
4091 struct run_it { | |
4092 shared_ptr<boost::detail::shared_state_base> that_; | |
4093 | |
4094 run_it(shared_ptr<boost::detail::shared_state_base> that) : that_ (that) {} | |
4095 void operator()() | |
3743 { | 4096 { |
3744 F parent; | 4097 FutureExecutorContinuationSharedState* that = dynamic_cast<FutureExecutorContinuationSharedState*>(that_.get()); |
3745 Fp continuation; | 4098 that->run(that_); |
3746 | 4099 } |
3747 public: | 4100 }; |
3748 future_async_continuation_shared_state( | 4101 |
3749 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c | 4102 template<typename Ex, typename F, typename Rp, typename Fp> |
3750 ) : | 4103 struct future_executor_continuation_shared_state: shared_state<Rp> |
3751 parent(boost::move(f)), | 4104 { |
3752 continuation(boost::move(c)) | 4105 Ex* ex; |
3753 { | 4106 F parent; |
4107 Fp continuation; | |
4108 shared_ptr<shared_state_base> centinel; | |
4109 | |
4110 public: | |
4111 future_executor_continuation_shared_state(Ex& ex, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) | |
4112 : ex(&ex), parent(boost::move(f)), | |
4113 continuation(boost::move(c)), | |
4114 centinel(parent.future_) { | |
4115 this->set_executor(); | |
4116 } | |
4117 | |
4118 void launch_continuation(boost::unique_lock<boost::mutex>& lck, shared_ptr<shared_state_base> that ) { | |
4119 relocker relock(lck); | |
4120 run_it<future_executor_continuation_shared_state> fct(that); | |
4121 ex->submit(fct); | |
4122 } | |
4123 | |
4124 static void run(shared_ptr<boost::detail::shared_state_base> that_) { | |
4125 future_executor_continuation_shared_state* that = dynamic_cast<future_executor_continuation_shared_state*>(that_.get()); | |
4126 try { | |
4127 that->mark_finished_with_result(that->continuation(boost::move(that->parent))); | |
4128 } catch(...) { | |
4129 that->mark_exceptional_finish(); | |
3754 } | 4130 } |
3755 | 4131 } |
3756 void launch_continuation(boost::unique_lock<boost::mutex>& lock) | 4132 |
3757 { | 4133 virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk) |
3758 lock.unlock(); | 4134 { |
3759 this->thr_ = thread(&future_async_continuation_shared_state::run, this); | 4135 this->wait(lk, false); |
4136 } | |
4137 | |
4138 ~future_executor_continuation_shared_state() {} | |
4139 }; | |
4140 | |
4141 template<typename Ex, typename F, typename Fp> | |
4142 struct future_executor_continuation_shared_state<Ex, F, void, Fp>: public shared_state<void> | |
4143 { | |
4144 Ex* ex; | |
4145 F parent; | |
4146 Fp continuation; | |
4147 shared_ptr<shared_state_base> centinel; | |
4148 | |
4149 public: | |
4150 future_executor_continuation_shared_state(Ex& ex, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) | |
4151 : ex(&ex), parent(boost::move(f)), | |
4152 continuation(boost::move(c)), | |
4153 centinel(parent.future_) { | |
4154 this->set_executor(); | |
4155 } | |
4156 | |
4157 void launch_continuation(boost::unique_lock<boost::mutex>& lck, shared_ptr<shared_state_base> that ) { | |
4158 relocker relock(lck); | |
4159 run_it<future_executor_continuation_shared_state> fct(that); | |
4160 ex->submit(fct); | |
4161 } | |
4162 | |
4163 static void run(shared_ptr<boost::detail::shared_state_base> that_) { | |
4164 future_executor_continuation_shared_state* that = dynamic_cast<future_executor_continuation_shared_state*>(that_.get()); | |
4165 try { | |
4166 that->continuation(boost::move(that->parent)); | |
4167 that->mark_finished_with_result(); | |
4168 } catch(...) { | |
4169 that->mark_exceptional_finish(); | |
3760 } | 4170 } |
3761 | 4171 } |
3762 static void run(future_async_continuation_shared_state* that) | 4172 |
3763 { | 4173 virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk) |
3764 try | 4174 { |
3765 { | 4175 this->wait(lk, false); |
3766 that->mark_finished_with_result(that->continuation(boost::move(that->parent))); | 4176 } |
3767 } | 4177 |
3768 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | 4178 ~future_executor_continuation_shared_state() {} |
3769 catch(thread_interrupted& ) | 4179 }; |
3770 { | 4180 #endif |
3771 that->mark_interrupted_finish(); | 4181 |
3772 } | 4182 ///////////////////////// |
3773 #endif | 4183 /// shared_future_async_continuation_shared_state |
3774 catch(...) | 4184 ///////////////////////// |
3775 { | 4185 |
3776 that->mark_exceptional_finish(); | 4186 template<typename F, typename Rp, typename Fp> |
3777 } | 4187 struct shared_future_async_continuation_shared_state: future_async_shared_state_base<Rp> |
4188 { | |
4189 F parent; | |
4190 Fp continuation; | |
4191 shared_ptr<shared_state_base> centinel; | |
4192 | |
4193 public: | |
4194 shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) | |
4195 : parent(f), | |
4196 continuation(boost::move(c)), | |
4197 centinel(parent.future_) { | |
4198 } | |
4199 | |
4200 void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base> that) { | |
4201 this->thr_ = thread(&shared_future_async_continuation_shared_state::run, that); | |
4202 } | |
4203 | |
4204 static void run(shared_ptr<boost::detail::shared_state_base> that_) { | |
4205 shared_future_async_continuation_shared_state* that = dynamic_cast<shared_future_async_continuation_shared_state*>(that_.get()); | |
4206 try { | |
4207 that->mark_finished_with_result(that->continuation(that->parent)); | |
4208 } catch(...) { | |
4209 that->mark_exceptional_finish(); | |
3778 } | 4210 } |
3779 ~future_async_continuation_shared_state() | 4211 } |
3780 { | 4212 |
3781 this->join(); | 4213 ~shared_future_async_continuation_shared_state() {} |
4214 }; | |
4215 | |
4216 template<typename F, typename Fp> | |
4217 struct shared_future_async_continuation_shared_state<F, void, Fp>: public future_async_shared_state_base<void> | |
4218 { | |
4219 F parent; | |
4220 Fp continuation; | |
4221 shared_ptr<shared_state_base> centinel; | |
4222 | |
4223 public: | |
4224 shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) | |
4225 : parent(f), | |
4226 continuation(boost::move(c)), | |
4227 centinel(parent.future_) { | |
4228 } | |
4229 | |
4230 void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base> that) { | |
4231 this->thr_ = thread(&shared_future_async_continuation_shared_state::run, that); | |
4232 } | |
4233 | |
4234 static void run(shared_ptr<boost::detail::shared_state_base> that_) { | |
4235 shared_future_async_continuation_shared_state* that = dynamic_cast<shared_future_async_continuation_shared_state*>(that_.get()); | |
4236 try { | |
4237 that->continuation(that->parent); | |
4238 that->mark_finished_with_result(); | |
4239 } catch(...) { | |
4240 that->mark_exceptional_finish(); | |
3782 } | 4241 } |
3783 }; | 4242 } |
3784 | 4243 |
3785 template<typename F, typename Fp> | 4244 ~shared_future_async_continuation_shared_state() {} |
3786 struct future_async_continuation_shared_state<F, void, Fp>: public future_async_shared_state_base<void> | 4245 }; |
4246 | |
4247 ///////////////////////// | |
4248 /// shared_future_executor_continuation_shared_state | |
4249 ///////////////////////// | |
4250 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS | |
4251 | |
4252 template<typename Ex, typename F, typename Rp, typename Fp> | |
4253 struct shared_future_executor_continuation_shared_state: shared_state<Rp> | |
4254 { | |
4255 Ex* ex; | |
4256 F parent; | |
4257 Fp continuation; | |
4258 shared_ptr<shared_state_base> centinel; | |
4259 | |
4260 public: | |
4261 shared_future_executor_continuation_shared_state(Ex& ex, F f, BOOST_THREAD_FWD_REF(Fp) c) | |
4262 : ex(&ex), parent(f), | |
4263 continuation(boost::move(c)), | |
4264 centinel(parent.future_) { | |
4265 this->set_executor(); | |
4266 } | |
4267 | |
4268 void launch_continuation(boost::unique_lock<boost::mutex>& lck, shared_ptr<shared_state_base> that) { | |
4269 relocker relock(lck); | |
4270 run_it<shared_future_executor_continuation_shared_state> fct(that); | |
4271 ex->submit(fct); | |
4272 } | |
4273 | |
4274 static void run(shared_ptr<boost::detail::shared_state_base> that_) { | |
4275 shared_future_executor_continuation_shared_state* that = dynamic_cast<shared_future_executor_continuation_shared_state*>(that_.get()); | |
4276 try { | |
4277 that->mark_finished_with_result(that->continuation(that->parent)); | |
4278 } catch(...) { | |
4279 that->mark_exceptional_finish(); | |
4280 } | |
4281 } | |
4282 | |
4283 virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk) | |
3787 { | 4284 { |
3788 F parent; | 4285 this->wait(lk, false); |
3789 Fp continuation; | 4286 } |
3790 | 4287 |
3791 public: | 4288 ~shared_future_executor_continuation_shared_state() {} |
3792 future_async_continuation_shared_state( | 4289 }; |
3793 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c | 4290 |
3794 ) : | 4291 template<typename Ex, typename F, typename Fp> |
3795 parent(boost::move(f)), | 4292 struct shared_future_executor_continuation_shared_state<Ex, F, void, Fp>: public shared_state<void> |
3796 continuation(boost::move(c)) | 4293 { |
3797 { | 4294 Ex* ex; |
4295 F parent; | |
4296 Fp continuation; | |
4297 shared_ptr<shared_state_base> centinel; | |
4298 | |
4299 public: | |
4300 shared_future_executor_continuation_shared_state(Ex& ex, F f, BOOST_THREAD_FWD_REF(Fp) c) | |
4301 : ex(&ex), parent(f), | |
4302 continuation(boost::move(c)), | |
4303 centinel(parent.future_) { | |
4304 } | |
4305 | |
4306 void launch_continuation(boost::unique_lock<boost::mutex>& lck, shared_ptr<shared_state_base> that) { | |
4307 relocker relock(lck); | |
4308 run_it<shared_future_executor_continuation_shared_state> fct(that); | |
4309 ex->submit(fct); | |
4310 } | |
4311 | |
4312 static void run(shared_ptr<boost::detail::shared_state_base> that_) { | |
4313 shared_future_executor_continuation_shared_state* that = dynamic_cast<shared_future_executor_continuation_shared_state*>(that_.get()); | |
4314 try { | |
4315 that->continuation(that->parent); | |
4316 that->mark_finished_with_result(); | |
4317 } catch(...) { | |
4318 that->mark_exceptional_finish(); | |
3798 } | 4319 } |
3799 | 4320 } |
3800 void launch_continuation(boost::unique_lock<boost::mutex>& lk) | 4321 |
3801 { | 4322 virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk) |
3802 lk.unlock(); | 4323 { |
3803 this->thr_ = thread(&future_async_continuation_shared_state::run, this); | 4324 this->wait(lk, false); |
4325 } | |
4326 | |
4327 ~shared_future_executor_continuation_shared_state() {} | |
4328 }; | |
4329 #endif | |
4330 ////////////////////////// | |
4331 /// future_deferred_continuation_shared_state | |
4332 ////////////////////////// | |
4333 template<typename F, typename Rp, typename Fp> | |
4334 struct future_deferred_continuation_shared_state: shared_state<Rp> | |
4335 { | |
4336 F parent; | |
4337 Fp continuation; | |
4338 shared_ptr<shared_state_base> centinel; | |
4339 | |
4340 public: | |
4341 future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) | |
4342 : parent(boost::move(f)), | |
4343 continuation(boost::move(c)), | |
4344 centinel(parent.future_) { | |
4345 this->set_deferred(); | |
4346 } | |
4347 | |
4348 virtual void launch_continuation(boost::unique_lock<boost::mutex>&lk, shared_ptr<shared_state_base> ) { | |
4349 if (this->is_deferred_) { | |
4350 this->is_deferred_=false; | |
4351 this->execute(lk); | |
3804 } | 4352 } |
3805 | 4353 } |
3806 static void run(future_async_continuation_shared_state* that) | 4354 |
3807 { | 4355 virtual void execute(boost::unique_lock<boost::mutex>& lck) { |
3808 try | 4356 try { |
3809 { | 4357 Fp local_fuct=boost::move(continuation); |
3810 that->continuation(boost::move(that->parent)); | 4358 F ftmp = boost::move(parent); |
3811 that->mark_finished_with_result(); | 4359 relocker relock(lck); |
3812 } | 4360 Rp res = local_fuct(boost::move(ftmp)); |
3813 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | 4361 relock.lock(); |
3814 catch(thread_interrupted& ) | 4362 this->mark_finished_with_result_internal(boost::move(res), lck); |
3815 { | 4363 } catch (...) { |
3816 that->mark_interrupted_finish(); | 4364 this->mark_exceptional_finish_internal(current_exception(), lck); |
3817 } | |
3818 #endif | |
3819 catch(...) | |
3820 { | |
3821 that->mark_exceptional_finish(); | |
3822 } | |
3823 } | 4365 } |
3824 ~future_async_continuation_shared_state() | 4366 } |
3825 { | 4367 }; |
3826 this->join(); | 4368 |
4369 template<typename F, typename Fp> | |
4370 struct future_deferred_continuation_shared_state<F,void,Fp>: shared_state<void> | |
4371 { | |
4372 F parent; | |
4373 Fp continuation; | |
4374 shared_ptr<shared_state_base> centinel; | |
4375 | |
4376 public: | |
4377 future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) | |
4378 : parent(boost::move(f)), | |
4379 continuation(boost::move(c)), | |
4380 centinel(parent.future_) { | |
4381 this->set_deferred(); | |
4382 } | |
4383 | |
4384 ~future_deferred_continuation_shared_state() { | |
4385 } | |
4386 virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk, shared_ptr<shared_state_base> ) { | |
4387 if (this->is_deferred_) { | |
4388 this->is_deferred_=false; | |
4389 this->execute(lk); | |
3827 } | 4390 } |
3828 }; | 4391 } |
3829 | 4392 |
3830 | 4393 virtual void execute(boost::unique_lock<boost::mutex>& lck) { |
3831 ////////////////////////// | 4394 try { |
3832 /// future_deferred_continuation_shared_state | 4395 Fp local_fuct=boost::move(continuation); |
3833 ////////////////////////// | 4396 F ftmp = boost::move(parent); |
3834 template<typename F, typename Rp, typename Fp> | 4397 relocker relock(lck); |
3835 struct future_deferred_continuation_shared_state: shared_state<Rp> | 4398 local_fuct(boost::move(ftmp)); |
3836 { | 4399 relock.lock(); |
3837 F parent; | 4400 this->mark_finished_with_result_internal(lck); |
3838 Fp continuation; | 4401 } catch (...) { |
3839 | 4402 this->mark_exceptional_finish_internal(current_exception(), lck); |
3840 public: | |
3841 future_deferred_continuation_shared_state( | |
3842 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c | |
3843 ) : | |
3844 parent(boost::move(f)), | |
3845 continuation(boost::move(c)) | |
3846 { | |
3847 this->set_deferred(); | |
3848 } | 4403 } |
3849 | 4404 } |
3850 virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk) | 4405 }; |
3851 { | 4406 |
3852 execute(lk); | 4407 ////////////////////////// |
4408 /// shared_future_deferred_continuation_shared_state | |
4409 ////////////////////////// | |
4410 template<typename F, typename Rp, typename Fp> | |
4411 struct shared_future_deferred_continuation_shared_state: shared_state<Rp> | |
4412 { | |
4413 F parent; | |
4414 Fp continuation; | |
4415 shared_ptr<shared_state_base> centinel; | |
4416 | |
4417 public: | |
4418 shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) | |
4419 : parent(f), | |
4420 continuation(boost::move(c)), | |
4421 centinel(parent.future_) { | |
4422 this->set_deferred(); | |
4423 } | |
4424 | |
4425 virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk, shared_ptr<shared_state_base> ) { | |
4426 if (this->is_deferred_) { | |
4427 this->is_deferred_=false; | |
4428 this->execute(lk); | |
3853 } | 4429 } |
3854 | 4430 } |
3855 virtual void execute(boost::unique_lock<boost::mutex>& lck) { | 4431 |
3856 try | 4432 virtual void execute(boost::unique_lock<boost::mutex>& lck) { |
3857 { | 4433 try { |
3858 Fp local_fuct=boost::move(continuation); | 4434 Fp local_fuct=boost::move(continuation); |
3859 F ftmp = boost::move(parent); | 4435 F ftmp = parent; |
3860 relocker relock(lck); | 4436 relocker relock(lck); |
3861 Rp res = local_fuct(boost::move(ftmp)); | 4437 Rp res = local_fuct(ftmp); |
3862 relock.lock(); | 4438 relock.lock(); |
3863 this->mark_finished_with_result_internal(boost::move(res), lck); | 4439 this->mark_finished_with_result_internal(boost::move(res), lck); |
3864 } | 4440 } catch (...) { |
3865 catch (...) | 4441 this->mark_exceptional_finish_internal(current_exception(), lck); |
3866 { | |
3867 this->mark_exceptional_finish_internal(current_exception(), lck); | |
3868 } | |
3869 } | 4442 } |
3870 }; | 4443 } |
3871 | 4444 }; |
3872 template<typename F, typename Fp> | 4445 |
3873 struct future_deferred_continuation_shared_state<F,void,Fp>: shared_state<void> | 4446 template<typename F, typename Fp> |
3874 { | 4447 struct shared_future_deferred_continuation_shared_state<F,void,Fp>: shared_state<void> |
3875 F parent; | 4448 { |
3876 Fp continuation; | 4449 F parent; |
3877 | 4450 Fp continuation; |
3878 public: | 4451 shared_ptr<shared_state_base> centinel; |
3879 future_deferred_continuation_shared_state( | 4452 |
3880 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c | 4453 public: |
3881 ): | 4454 shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) |
3882 parent(boost::move(f)), | 4455 : parent(f), |
3883 continuation(boost::move(c)) | 4456 continuation(boost::move(c)), |
3884 { | 4457 centinel(parent.future_) { |
3885 this->set_deferred(); | 4458 this->set_deferred(); |
4459 } | |
4460 | |
4461 virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk, shared_ptr<shared_state_base> ) { | |
4462 if (this->is_deferred_) { | |
4463 this->is_deferred_=false; | |
4464 this->execute(lk); | |
3886 } | 4465 } |
3887 | 4466 } |
3888 virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk) | 4467 |
3889 { | 4468 virtual void execute(boost::unique_lock<boost::mutex>& lck) { |
3890 execute(lk); | 4469 try { |
4470 Fp local_fuct=boost::move(continuation); | |
4471 F ftmp = parent; | |
4472 relocker relock(lck); | |
4473 local_fuct(ftmp); | |
4474 relock.lock(); | |
4475 this->mark_finished_with_result_internal(lck); | |
4476 } catch (...) { | |
4477 this->mark_exceptional_finish_internal(current_exception(), lck); | |
3891 } | 4478 } |
3892 virtual void execute(boost::unique_lock<boost::mutex>& lck) { | 4479 } |
3893 try | 4480 }; |
3894 { | 4481 |
3895 Fp local_fuct=boost::move(continuation); | 4482 //////////////////////////////// |
3896 F ftmp = boost::move(parent); | 4483 // make_future_deferred_continuation_shared_state |
3897 relocker relock(lck); | 4484 //////////////////////////////// |
3898 local_fuct(boost::move(ftmp)); | 4485 template<typename F, typename Rp, typename Fp> |
3899 relock.lock(); | 4486 BOOST_THREAD_FUTURE<Rp> |
3900 this->mark_finished_with_result_internal(lck); | 4487 make_future_deferred_continuation_shared_state( |
3901 } | 4488 boost::unique_lock<boost::mutex> &lock, |
3902 catch (...) | 4489 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) { |
3903 { | 4490 shared_ptr<future_deferred_continuation_shared_state<F, Rp, Fp> > |
3904 this->mark_exceptional_finish_internal(current_exception(), lck); | 4491 h(new future_deferred_continuation_shared_state<F, Rp, Fp>(boost::move(f), boost::forward<Fp>(c))); |
3905 } | 4492 lock.lock(); |
3906 } | 4493 h->parent.future_->set_continuation_ptr(h, lock); |
3907 }; | 4494 lock.unlock(); |
3908 | 4495 return BOOST_THREAD_FUTURE<Rp>(h); |
3909 //////////////////////////////// | 4496 } |
3910 // make_future_deferred_continuation_shared_state | 4497 |
3911 //////////////////////////////// | 4498 //////////////////////////////// |
3912 template<typename F, typename Rp, typename Fp> | 4499 // make_future_async_continuation_shared_state |
3913 BOOST_THREAD_FUTURE<Rp> | 4500 //////////////////////////////// |
3914 make_future_deferred_continuation_shared_state( | 4501 template<typename F, typename Rp, typename Fp> |
3915 boost::unique_lock<boost::mutex> &lock, | 4502 BOOST_THREAD_FUTURE<Rp> |
3916 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c | 4503 make_future_async_continuation_shared_state( |
3917 ) | 4504 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, |
3918 { | 4505 BOOST_THREAD_FWD_REF(Fp) c) { |
3919 shared_ptr<future_deferred_continuation_shared_state<F, Rp, Fp> > | 4506 shared_ptr<future_async_continuation_shared_state<F,Rp, Fp> > |
3920 h(new future_deferred_continuation_shared_state<F, Rp, Fp>(boost::move(f), boost::forward<Fp>(c))); | 4507 h(new future_async_continuation_shared_state<F,Rp, Fp>(boost::move(f), boost::forward<Fp>(c))); |
3921 h->parent.future_->set_continuation_ptr(h, lock); | 4508 lock.lock(); |
3922 return BOOST_THREAD_FUTURE<Rp>(h); | 4509 h->parent.future_->set_continuation_ptr(h, lock); |
3923 } | 4510 lock.unlock(); |
3924 | 4511 |
3925 //////////////////////////////// | 4512 return BOOST_THREAD_FUTURE<Rp>(h); |
3926 // make_future_async_continuation_shared_state | 4513 } |
3927 //////////////////////////////// | 4514 |
3928 template<typename F, typename Rp, typename Fp> | 4515 //////////////////////////////// |
3929 BOOST_THREAD_FUTURE<Rp> | 4516 // make_future_executor_continuation_shared_state |
3930 make_future_async_continuation_shared_state( | 4517 //////////////////////////////// |
3931 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c | 4518 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS |
3932 ) | 4519 |
3933 { | 4520 template<typename Ex, typename F, typename Rp, typename Fp> |
3934 shared_ptr<future_async_continuation_shared_state<F,Rp, Fp> > | 4521 BOOST_THREAD_FUTURE<Rp> |
3935 h(new future_async_continuation_shared_state<F,Rp, Fp>(boost::move(f), boost::forward<Fp>(c))); | 4522 make_future_executor_continuation_shared_state(Ex& ex, |
3936 h->parent.future_->set_continuation_ptr(h, lock); | 4523 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, |
3937 | 4524 BOOST_THREAD_FWD_REF(Fp) c) { |
3938 return BOOST_THREAD_FUTURE<Rp>(h); | 4525 shared_ptr<future_executor_continuation_shared_state<Ex,F,Rp, Fp> > |
3939 } | 4526 h(new future_executor_continuation_shared_state<Ex, F,Rp, Fp>(ex, boost::move(f), boost::forward<Fp>(c))); |
3940 | 4527 lock.lock(); |
3941 } | 4528 h->parent.future_->set_continuation_ptr(h, lock); |
4529 lock.unlock(); | |
4530 | |
4531 return BOOST_THREAD_FUTURE<Rp>(h); | |
4532 } | |
4533 #endif | |
4534 | |
4535 //////////////////////////////// | |
4536 // make_shared_future_deferred_continuation_shared_state | |
4537 //////////////////////////////// | |
4538 template<typename F, typename Rp, typename Fp> | |
4539 BOOST_THREAD_FUTURE<Rp> | |
4540 make_shared_future_deferred_continuation_shared_state( | |
4541 boost::unique_lock<boost::mutex> &lock, | |
4542 F f, BOOST_THREAD_FWD_REF(Fp) c) { | |
4543 shared_ptr<shared_future_deferred_continuation_shared_state<F, Rp, Fp> > | |
4544 h(new shared_future_deferred_continuation_shared_state<F, Rp, Fp>(f, boost::forward<Fp>(c))); | |
4545 lock.lock(); | |
4546 h->parent.future_->set_continuation_ptr(h, lock); | |
4547 lock.unlock(); | |
4548 | |
4549 return BOOST_THREAD_FUTURE<Rp>(h); | |
4550 } | |
4551 //////////////////////////////// | |
4552 // make_shared_future_async_continuation_shared_state | |
4553 //////////////////////////////// | |
4554 template<typename F, typename Rp, typename Fp> | |
4555 BOOST_THREAD_FUTURE<Rp> | |
4556 make_shared_future_async_continuation_shared_state( | |
4557 boost::unique_lock<boost::mutex> &lock, F f, | |
4558 BOOST_THREAD_FWD_REF(Fp) c) { | |
4559 shared_ptr<shared_future_async_continuation_shared_state<F,Rp, Fp> > | |
4560 h(new shared_future_async_continuation_shared_state<F,Rp, Fp>(f, boost::forward<Fp>(c))); | |
4561 lock.lock(); | |
4562 h->parent.future_->set_continuation_ptr(h, lock); | |
4563 lock.unlock(); | |
4564 | |
4565 return BOOST_THREAD_FUTURE<Rp>(h); | |
4566 } | |
4567 //////////////////////////////// | |
4568 // make_shared_future_executor_continuation_shared_state | |
4569 //////////////////////////////// | |
4570 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS | |
4571 template<typename Ex, typename F, typename Rp, typename Fp> | |
4572 BOOST_THREAD_FUTURE<Rp> | |
4573 make_shared_future_executor_continuation_shared_state(Ex& ex, | |
4574 boost::unique_lock<boost::mutex> &lock, F f, | |
4575 BOOST_THREAD_FWD_REF(Fp) c) { | |
4576 shared_ptr<shared_future_executor_continuation_shared_state<Ex, F, Rp, Fp> > | |
4577 h(new shared_future_executor_continuation_shared_state<Ex, F, Rp, Fp>(ex, f, boost::forward<Fp>(c))); | |
4578 lock.lock(); | |
4579 h->parent.future_->set_continuation_ptr(h, lock); | |
4580 lock.unlock(); | |
4581 | |
4582 return BOOST_THREAD_FUTURE<Rp>(h); | |
4583 } | |
4584 #endif | |
4585 } | |
3942 | 4586 |
3943 //////////////////////////////// | 4587 //////////////////////////////// |
3944 // template<typename F> | 4588 // template<typename F> |
3945 // auto future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; | 4589 // auto future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; |
3946 //////////////////////////////// | 4590 //////////////////////////////// |
3947 | 4591 |
3948 template <typename R> | 4592 template <typename R> |
3949 template <typename F> | 4593 template <typename F> |
3950 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type> | 4594 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type> |
3951 BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) | 4595 BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) { |
3952 { | |
3953 | |
3954 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; | 4596 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; |
3955 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); | 4597 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); |
3956 | 4598 |
3957 boost::unique_lock<boost::mutex> lock(this->future_->mutex); | 4599 boost::unique_lock<boost::mutex> lock(this->future_->mutex); |
3958 if (int(policy) & int(launch::async)) | 4600 if (underlying_cast<int>(policy) & int(launch::async)) { |
3959 { | 4601 lock.unlock(); |
3960 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | 4602 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( |
3961 lock, boost::move(*this), boost::forward<F>(func) | 4603 lock, boost::move(*this), boost::forward<F>(func) |
3962 ))); | 4604 ))); |
3963 } | 4605 } else if (underlying_cast<int>(policy) & int(launch::deferred)) { |
3964 else if (int(policy) & int(launch::deferred)) | 4606 this->future_->wait_internal(lock); |
3965 { | 4607 lock.unlock(); |
3966 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | 4608 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( |
3967 lock, boost::move(*this), boost::forward<F>(func) | 4609 lock, boost::move(*this), boost::forward<F>(func) |
3968 ))); | 4610 ))); |
3969 } | 4611 } else { |
3970 else | 4612 lock.unlock(); |
3971 { | |
3972 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | 4613 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( |
3973 lock, boost::move(*this), boost::forward<F>(func) | 4614 lock, boost::move(*this), boost::forward<F>(func) |
3974 ))); | 4615 ))); |
3975 | 4616 } |
3976 } | 4617 } |
3977 | 4618 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS |
3978 } | 4619 template <typename R> |
4620 template <typename Ex, typename F> | |
4621 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type> | |
4622 BOOST_THREAD_FUTURE<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) { | |
4623 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; | |
4624 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); | |
4625 | |
4626 boost::unique_lock<boost::mutex> lock(this->future_->mutex); | |
4627 lock.unlock(); | |
4628 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type, F>(ex, | |
4629 lock, boost::move(*this), boost::forward<F>(func) | |
4630 ))); | |
4631 } | |
4632 #endif | |
3979 template <typename R> | 4633 template <typename R> |
3980 template <typename F> | 4634 template <typename F> |
3981 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type> | 4635 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type> |
3982 BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func) | 4636 BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func) { |
3983 { | |
3984 | |
3985 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; | 4637 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; |
3986 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); | 4638 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); |
3987 | 4639 |
3988 boost::unique_lock<boost::mutex> lock(this->future_->mutex); | 4640 boost::unique_lock<boost::mutex> lock(this->future_->mutex); |
3989 if (int(this->launch_policy(lock)) & int(launch::async)) | 4641 if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::async)) { |
3990 { | 4642 lock.unlock(); |
3991 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | 4643 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( |
3992 lock, boost::move(*this), boost::forward<F>(func) | 4644 lock, boost::move(*this), boost::forward<F>(func) |
3993 ); | 4645 ); |
3994 } | 4646 } else if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::deferred)) { |
3995 else if (int(this->launch_policy(lock)) & int(launch::deferred)) | 4647 this->future_->wait_internal(lock); |
3996 { | 4648 lock.unlock(); |
4649 return boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | |
4650 lock, boost::move(*this), boost::forward<F>(func) | |
4651 ); | |
4652 } else { | |
4653 lock.unlock(); | |
4654 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | |
4655 lock, boost::move(*this), boost::forward<F>(func) | |
4656 ); | |
4657 } | |
4658 } | |
4659 | |
4660 //////////////////////////////// | |
4661 // template<typename F> | |
4662 // auto future<future<R2>>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; | |
4663 //////////////////////////////// | |
4664 | |
4665 template <typename R2> | |
4666 template <typename F> | |
4667 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type> | |
4668 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(launch policy, BOOST_THREAD_FWD_REF(F) func) { | |
4669 typedef BOOST_THREAD_FUTURE<R2> R; | |
4670 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; | |
4671 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); | |
4672 | |
4673 boost::unique_lock<boost::mutex> lock(this->future_->mutex); | |
4674 if (underlying_cast<int>(policy) & int(launch::async)) { | |
4675 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | |
4676 lock, boost::move(*this), boost::forward<F>(func) | |
4677 ))); | |
4678 } else if (underlying_cast<int>(policy) & int(launch::deferred)) { | |
4679 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | |
4680 lock, boost::move(*this), boost::forward<F>(func) | |
4681 ))); | |
4682 } else { | |
4683 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | |
4684 lock, boost::move(*this), boost::forward<F>(func) | |
4685 ))); | |
4686 } | |
4687 } | |
4688 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS | |
4689 template <typename R2> | |
4690 template <typename Ex, typename F> | |
4691 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type> | |
4692 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) { | |
4693 typedef BOOST_THREAD_FUTURE<R2> R; | |
4694 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; | |
4695 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); | |
4696 | |
4697 boost::unique_lock<boost::mutex> lock(this->future_->mutex); | |
4698 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type, F>(ex, | |
4699 lock, boost::move(*this), boost::forward<F>(func) | |
4700 ))); | |
4701 } | |
4702 #endif | |
4703 template <typename R2> | |
4704 template <typename F> | |
4705 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type> | |
4706 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(BOOST_THREAD_FWD_REF(F) func) { | |
4707 typedef BOOST_THREAD_FUTURE<R2> R; | |
4708 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; | |
4709 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); | |
4710 | |
4711 boost::unique_lock<boost::mutex> lock(this->future_->mutex); | |
4712 if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::async)) { | |
4713 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | |
4714 lock, boost::move(*this), boost::forward<F>(func) | |
4715 ); | |
4716 } else if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::deferred)) { | |
3997 this->future_->wait_internal(lock); | 4717 this->future_->wait_internal(lock); |
3998 return boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | 4718 return boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( |
3999 lock, boost::move(*this), boost::forward<F>(func) | 4719 lock, boost::move(*this), boost::forward<F>(func) |
4000 ); | 4720 ); |
4001 } | 4721 } else { |
4002 else | |
4003 { | |
4004 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | 4722 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( |
4005 lock, boost::move(*this), boost::forward<F>(func) | 4723 lock, boost::move(*this), boost::forward<F>(func) |
4006 ); | 4724 ); |
4007 } | 4725 } |
4008 } | 4726 } |
4009 | 4727 |
4010 | 4728 //////////////////////////////// |
4011 //#if 0 && defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) | 4729 // template<typename F> |
4012 // template <typename R> | 4730 // auto shared_future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; |
4013 // template<typename RF> | 4731 //////////////////////////////// |
4014 // BOOST_THREAD_FUTURE<RF> | |
4015 // BOOST_THREAD_FUTURE<R>::then(RF(*func)(BOOST_THREAD_FUTURE<R>&)) | |
4016 // { | |
4017 // | |
4018 // typedef RF future_type; | |
4019 // | |
4020 // if (this->future_) | |
4021 // { | |
4022 // boost::unique_lock<boost::mutex> lock(this->future_->mutex); | |
4023 // detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr = | |
4024 // new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func); | |
4025 // if (ptr==0) | |
4026 // { | |
4027 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>()); | |
4028 // } | |
4029 // this->future_->set_continuation_ptr(ptr, lock); | |
4030 // return ptr->get_future(); | |
4031 // } else { | |
4032 // // fixme what to do when the future has no associated state? | |
4033 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>()); | |
4034 // } | |
4035 // | |
4036 // } | |
4037 // template <typename R> | |
4038 // template<typename RF> | |
4039 // BOOST_THREAD_FUTURE<RF> | |
4040 // BOOST_THREAD_FUTURE<R>::then(launch policy, RF(*func)(BOOST_THREAD_FUTURE<R>&)) | |
4041 // { | |
4042 // | |
4043 // typedef RF future_type; | |
4044 // | |
4045 // if (this->future_) | |
4046 // { | |
4047 // boost::unique_lock<boost::mutex> lock(this->future_->mutex); | |
4048 // detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr = | |
4049 // new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func, policy); | |
4050 // if (ptr==0) | |
4051 // { | |
4052 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>()); | |
4053 // } | |
4054 // this->future_->set_continuation_ptr(ptr, lock); | |
4055 // return ptr->get_future(); | |
4056 // } else { | |
4057 // // fixme what to do when the future has no associated state? | |
4058 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>()); | |
4059 // } | |
4060 // | |
4061 // } | |
4062 //#endif | |
4063 | 4732 |
4064 template <typename R> | 4733 template <typename R> |
4065 template <typename F> | 4734 template <typename F> |
4066 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type> | 4735 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type> |
4067 shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) | 4736 shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) const |
4068 { | 4737 { |
4069 | |
4070 typedef typename boost::result_of<F(shared_future<R>)>::type future_type; | 4738 typedef typename boost::result_of<F(shared_future<R>)>::type future_type; |
4071 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); | 4739 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); |
4072 | 4740 |
4073 boost::unique_lock<boost::mutex> lock(this->future_->mutex); | 4741 boost::unique_lock<boost::mutex> lock(this->future_->mutex); |
4074 if (int(policy) & int(launch::async)) | 4742 if (underlying_cast<int>(policy) & int(launch::async)) { |
4075 { | 4743 lock.unlock(); |
4076 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>( | 4744 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>( |
4077 lock, boost::move(*this), boost::forward<F>(func) | 4745 lock, *this, boost::forward<F>(func) |
4078 ))); | 4746 ))); |
4079 } | 4747 } else if (underlying_cast<int>(policy) & int(launch::deferred)) { |
4080 else if (int(policy) & int(launch::deferred)) | 4748 this->future_->wait_internal(lock); |
4081 { | 4749 lock.unlock(); |
4082 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>( | 4750 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>( |
4083 lock, boost::move(*this), boost::forward<F>(func) | 4751 lock, *this, boost::forward<F>(func) |
4084 ))); | 4752 ))); |
4085 } | 4753 } else { |
4086 else | 4754 lock.unlock(); |
4087 { | 4755 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>( |
4088 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>( | 4756 lock, *this, boost::forward<F>(func) |
4089 lock, boost::move(*this), boost::forward<F>(func) | |
4090 ))); | 4757 ))); |
4091 } | 4758 } |
4092 | 4759 } |
4093 } | 4760 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS |
4761 template <typename R> | |
4762 template <typename Ex, typename F> | |
4763 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type> | |
4764 shared_future<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const | |
4765 { | |
4766 typedef typename boost::result_of<F(shared_future<R>)>::type future_type; | |
4767 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); | |
4768 | |
4769 boost::unique_lock<boost::mutex> lock(this->future_->mutex); | |
4770 lock.unlock(); | |
4771 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type, F>(ex, | |
4772 lock, *this, boost::forward<F>(func) | |
4773 ))); | |
4774 } | |
4775 #endif | |
4776 | |
4094 template <typename R> | 4777 template <typename R> |
4095 template <typename F> | 4778 template <typename F> |
4096 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type> | 4779 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type> |
4097 shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func) | 4780 shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func) const { |
4781 typedef typename boost::result_of<F(shared_future<R>)>::type future_type; | |
4782 | |
4783 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); | |
4784 | |
4785 boost::unique_lock<boost::mutex> lock(this->future_->mutex); | |
4786 if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::async)) { | |
4787 lock.unlock(); | |
4788 return boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>( | |
4789 lock, *this, boost::forward<F>(func)); | |
4790 } else if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::deferred)) { | |
4791 this->future_->wait_internal(lock); | |
4792 lock.unlock(); | |
4793 return boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>( | |
4794 lock, *this, boost::forward<F>(func)); | |
4795 } else { | |
4796 lock.unlock(); | |
4797 return boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>( | |
4798 lock, *this, boost::forward<F>(func)); | |
4799 } | |
4800 } | |
4801 | |
4802 namespace detail | |
4803 { | |
4804 template <typename T> | |
4805 struct mfallbacker_to | |
4098 { | 4806 { |
4099 | 4807 T value_; |
4100 typedef typename boost::result_of<F(shared_future<R>)>::type future_type; | 4808 typedef T result_type; |
4101 | 4809 mfallbacker_to(BOOST_THREAD_RV_REF(T) v) |
4102 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); | 4810 : value_(boost::move(v)) |
4103 | 4811 {} |
4104 boost::unique_lock<boost::mutex> lock(this->future_->mutex); | 4812 |
4105 if (int(this->launch_policy(lock)) & int(launch::async)) | 4813 T operator()(BOOST_THREAD_FUTURE<T> fut) { |
4106 { | 4814 return fut.get_or(boost::move(value_)); |
4107 return boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>( | 4815 } |
4108 lock, boost::move(*this), boost::forward<F>(func) | 4816 }; |
4109 ); | 4817 template <typename T> |
4110 } | 4818 struct cfallbacker_to |
4111 else if (int(this->launch_policy(lock)) & int(launch::deferred)) | |
4112 { | |
4113 this->future_->wait_internal(lock); | |
4114 return boost::detail::make_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>( | |
4115 lock, boost::move(*this), boost::forward<F>(func) | |
4116 ); | |
4117 } | |
4118 else | |
4119 { | |
4120 return boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>( | |
4121 lock, boost::move(*this), boost::forward<F>(func) | |
4122 ); | |
4123 } | |
4124 } | |
4125 namespace detail | |
4126 { | 4819 { |
4127 template <typename T> | 4820 T value_; |
4128 struct mfallbacker_to | 4821 typedef T result_type; |
4129 { | 4822 cfallbacker_to(T const& v) |
4130 T value_; | 4823 : value_(v) |
4131 typedef T result_type; | 4824 {} |
4132 mfallbacker_to(BOOST_THREAD_RV_REF(T) v) | 4825 |
4133 : value_(boost::move(v)) | 4826 T operator()(BOOST_THREAD_FUTURE<T> fut) const { |
4134 {} | 4827 return fut.get_or(value_); |
4135 | 4828 |
4136 T operator()(BOOST_THREAD_FUTURE<T> fut) | 4829 } |
4137 { | 4830 }; |
4138 return fut.get_or(boost::move(value_)); | 4831 } |
4139 | |
4140 } | |
4141 }; | |
4142 template <typename T> | |
4143 struct cfallbacker_to | |
4144 { | |
4145 T value_; | |
4146 typedef T result_type; | |
4147 cfallbacker_to(T const& v) | |
4148 : value_(v) | |
4149 {} | |
4150 | |
4151 T operator()(BOOST_THREAD_FUTURE<T> fut) | |
4152 { | |
4153 return fut.get_or(value_); | |
4154 | |
4155 } | |
4156 }; | |
4157 } | |
4158 //////////////////////////////// | 4832 //////////////////////////////// |
4159 // future<R> future<R>::fallback_to(R&& v); | 4833 // future<R> future<R>::fallback_to(R&& v); |
4160 //////////////////////////////// | 4834 //////////////////////////////// |
4161 | 4835 |
4162 template <typename R> | 4836 template <typename R> |
4163 template <typename R2> | 4837 template <typename R2> |
4164 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type | 4838 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type |
4165 BOOST_THREAD_FUTURE<R>::fallback_to(BOOST_THREAD_RV_REF(R2) v) | 4839 BOOST_THREAD_FUTURE<R>::fallback_to(BOOST_THREAD_RV_REF(R2) v) { |
4166 { | |
4167 return then(detail::mfallbacker_to<R>(boost::move(v))); | 4840 return then(detail::mfallbacker_to<R>(boost::move(v))); |
4168 } | 4841 } |
4169 | 4842 |
4170 template <typename R> | 4843 template <typename R> |
4171 template <typename R2> | 4844 template <typename R2> |
4172 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type | 4845 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type |
4173 BOOST_THREAD_FUTURE<R>::fallback_to(R2 const& v) | 4846 BOOST_THREAD_FUTURE<R>::fallback_to(R2 const& v) { |
4847 return then(detail::cfallbacker_to<R>(v)); | |
4848 } | |
4849 | |
4850 #endif | |
4851 | |
4852 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP | |
4853 namespace detail | |
4854 { | |
4855 ///////////////////////// | |
4856 /// future_unwrap_shared_state | |
4857 ///////////////////////// | |
4858 | |
4859 template<typename F, typename Rp> | |
4860 struct future_unwrap_shared_state: shared_state<Rp> | |
4174 { | 4861 { |
4175 return then(detail::cfallbacker_to<R>(v)); | 4862 F parent; |
4176 } | 4863 public: |
4177 | 4864 explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f) |
4178 #endif | 4865 : parent(boost::move(f)) {} |
4179 | 4866 |
4180 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP | 4867 typename F::value_type parent_value(boost::unique_lock<boost::mutex>& ) { |
4181 namespace detail | 4868 typename F::value_type r = parent.get(); |
4182 { | 4869 r.set_exceptional_if_invalid(); |
4183 | 4870 return boost::move(r); |
4184 ///////////////////////// | 4871 } |
4185 /// future_unwrap_shared_state | 4872 |
4186 ///////////////////////// | 4873 virtual void wait(boost::unique_lock<boost::mutex>& lk, bool ) { // todo see if rethrow must be used |
4187 | 4874 parent_value(lk).wait(); |
4188 template<typename F, typename Rp> | 4875 } |
4189 struct future_unwrap_shared_state: shared_state<Rp> | 4876 virtual Rp get(boost::unique_lock<boost::mutex>& lk) { |
4877 return parent_value(lk).get(); | |
4878 } | |
4879 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | |
4880 typedef shared_ptr<shared_state_base> continuation_ptr_type; | |
4881 | |
4882 virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock) | |
4190 { | 4883 { |
4191 F parent; | 4884 boost::unique_lock<boost::mutex> lk(parent.future_->mutex); |
4192 public: | 4885 parent.future_->set_continuation_ptr(continuation, lk); |
4193 explicit future_unwrap_shared_state( | 4886 } |
4194 BOOST_THREAD_RV_REF(F) f | 4887 #endif |
4195 ) : | 4888 }; |
4196 parent(boost::move(f)) | 4889 |
4197 { | 4890 template <class F, class Rp> |
4198 } | 4891 BOOST_THREAD_FUTURE<Rp> |
4199 virtual void wait(bool ) // todo see if rethrow must be used | 4892 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f) { |
4200 { | 4893 shared_ptr<future_unwrap_shared_state<F, Rp> > |
4201 boost::unique_lock<boost::mutex> lock(mutex); | 4894 h(new future_unwrap_shared_state<F, Rp>(boost::move(f))); |
4202 parent.get().wait(); | 4895 lock.lock(); |
4203 } | 4896 h->parent.future_->set_continuation_ptr(h, lock); |
4204 virtual Rp get() | 4897 lock.unlock(); |
4205 { | 4898 return BOOST_THREAD_FUTURE<Rp>(h); |
4206 boost::unique_lock<boost::mutex> lock(mutex); | 4899 } |
4207 return parent.get().get(); | 4900 } |
4208 } | |
4209 | |
4210 }; | |
4211 | |
4212 template <class F, class Rp> | |
4213 BOOST_THREAD_FUTURE<Rp> | |
4214 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f) | |
4215 { | |
4216 shared_ptr<future_unwrap_shared_state<F, Rp> > | |
4217 h(new future_unwrap_shared_state<F, Rp>(boost::move(f))); | |
4218 h->parent.future_->set_continuation_ptr(h, lock); | |
4219 return BOOST_THREAD_FUTURE<Rp>(h); | |
4220 } | |
4221 } | |
4222 | 4901 |
4223 template <typename R> | 4902 template <typename R> |
4224 inline BOOST_THREAD_FUTURE<R>::BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other): | 4903 inline BOOST_THREAD_FUTURE<R>::BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other) |
4225 base_type(other.unwrap()) | 4904 : base_type(other.unwrap()) {} |
4226 { | |
4227 } | |
4228 | 4905 |
4229 template <typename R2> | 4906 template <typename R2> |
4230 BOOST_THREAD_FUTURE<R2> | 4907 BOOST_THREAD_FUTURE<R2> |
4231 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap() | 4908 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap() |
4232 { | 4909 { |
4233 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); | 4910 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); |
4234 boost::unique_lock<boost::mutex> lock(this->future_->mutex); | 4911 boost::unique_lock<boost::mutex> lock(this->future_->mutex); |
4912 lock.unlock(); | |
4235 return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this)); | 4913 return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this)); |
4236 } | 4914 } |
4237 #endif | 4915 #endif |
4916 | |
4917 #if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY | |
4918 namespace detail | |
4919 { | |
4920 struct input_iterator_tag {}; | |
4921 struct vector_tag {}; | |
4922 struct values_tag {}; | |
4923 template <typename T> | |
4924 struct alias_t { typedef T type; }; | |
4925 | |
4926 BOOST_CONSTEXPR_OR_CONST input_iterator_tag input_iterator_tag_value = {}; | |
4927 BOOST_CONSTEXPR_OR_CONST vector_tag vector_tag_value = {}; | |
4928 BOOST_CONSTEXPR_OR_CONST values_tag values_tag_value = {}; | |
4929 //////////////////////////////// | |
4930 // detail::future_async_when_all_shared_state | |
4931 //////////////////////////////// | |
4932 template<typename F> | |
4933 struct future_when_all_vector_shared_state: future_async_shared_state_base<csbl::vector<F> > | |
4934 { | |
4935 typedef csbl::vector<F> vector_type; | |
4936 typedef typename F::value_type value_type; | |
4937 vector_type vec_; | |
4938 | |
4939 static void run(shared_ptr<boost::detail::shared_state_base> that_) { | |
4940 future_when_all_vector_shared_state* that = dynamic_cast<future_when_all_vector_shared_state*>(that_.get()); | |
4941 try { | |
4942 boost::wait_for_all(that->vec_.begin(), that->vec_.end()); | |
4943 that->mark_finished_with_result(boost::move(that->vec_)); | |
4944 } catch(...) { | |
4945 that->mark_exceptional_finish(); | |
4946 } | |
4947 } | |
4948 bool run_deferred() { | |
4949 | |
4950 bool res = false; | |
4951 for (typename csbl::vector<F>::iterator it = vec_.begin(); it != vec_.end(); ++it) { | |
4952 if (! it->run_if_is_deferred()) | |
4953 { | |
4954 res = true; | |
4955 } | |
4956 } | |
4957 return res; | |
4958 } | |
4959 void init() { | |
4960 if (! run_deferred()) | |
4961 { | |
4962 future_when_all_vector_shared_state::run(this->shared_from_this()); | |
4963 return; | |
4964 } | |
4965 this->thr_ = thread(&future_when_all_vector_shared_state::run, this->shared_from_this()); | |
4966 } | |
4967 | |
4968 public: | |
4969 template< typename InputIterator> | |
4970 future_when_all_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last) | |
4971 : vec_(std::make_move_iterator(first), std::make_move_iterator(last)) | |
4972 { | |
4973 } | |
4974 | |
4975 future_when_all_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v) | |
4976 : vec_(boost::move(v)) | |
4977 { | |
4978 } | |
4979 | |
4980 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
4981 template< typename T0, typename ...T> | |
4982 future_when_all_vector_shared_state(values_tag, BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) { | |
4983 vec_.push_back(boost::forward<T0>(f)); | |
4984 typename alias_t<char[]>::type{ | |
4985 ( //first part of magic unpacker | |
4986 vec_.push_back(boost::forward<T>(futures)),'0' | |
4987 )..., '0' | |
4988 }; //second part of magic unpacker | |
4989 } | |
4990 #endif | |
4991 | |
4992 ~future_when_all_vector_shared_state() {} | |
4993 }; | |
4994 | |
4995 //////////////////////////////// | |
4996 // detail::future_async_when_any_shared_state | |
4997 //////////////////////////////// | |
4998 template<typename F> | |
4999 struct future_when_any_vector_shared_state: future_async_shared_state_base<csbl::vector<F> > | |
5000 { | |
5001 typedef csbl::vector<F> vector_type; | |
5002 typedef typename F::value_type value_type; | |
5003 vector_type vec_; | |
5004 | |
5005 static void run(shared_ptr<boost::detail::shared_state_base> that_) | |
5006 { | |
5007 future_when_any_vector_shared_state* that = dynamic_cast<future_when_any_vector_shared_state*>(that_.get()); | |
5008 try { | |
5009 boost::wait_for_any(that->vec_.begin(), that->vec_.end()); | |
5010 that->mark_finished_with_result(boost::move(that->vec_)); | |
5011 } catch(...) { | |
5012 that->mark_exceptional_finish(); | |
5013 } | |
5014 } | |
5015 bool run_deferred() { | |
5016 | |
5017 for (typename csbl::vector<F>::iterator it = vec_.begin(); it != vec_.end(); ++it) { | |
5018 if (it->run_if_is_deferred_or_ready()) | |
5019 { | |
5020 return true; | |
5021 } | |
5022 } | |
5023 return false; | |
5024 } | |
5025 void init() { | |
5026 if (run_deferred()) | |
5027 { | |
5028 future_when_any_vector_shared_state::run(this->shared_from_this()); | |
5029 return; | |
5030 } | |
5031 | |
5032 this->thr_ = thread(&future_when_any_vector_shared_state::run, this->shared_from_this()); | |
5033 } | |
5034 | |
5035 public: | |
5036 template< typename InputIterator> | |
5037 future_when_any_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last) | |
5038 : vec_(std::make_move_iterator(first), std::make_move_iterator(last)) | |
5039 { | |
5040 } | |
5041 | |
5042 future_when_any_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v) | |
5043 : vec_(boost::move(v)) | |
5044 { | |
5045 } | |
5046 | |
5047 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
5048 template< typename T0, typename ...T> | |
5049 future_when_any_vector_shared_state(values_tag, | |
5050 BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures | |
5051 ) { | |
5052 vec_.push_back(boost::forward<T0>(f)); | |
5053 typename alias_t<char[]>::type{ | |
5054 ( //first part of magic unpacker | |
5055 vec_.push_back(boost::forward<T>(futures)) | |
5056 ,'0' | |
5057 )..., | |
5058 '0' | |
5059 }; //second part of magic unpacker | |
5060 } | |
5061 #endif | |
5062 | |
5063 ~future_when_any_vector_shared_state() {} | |
5064 }; | |
5065 | |
5066 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
5067 struct wait_for_all_fctr { | |
5068 template <class ...T> | |
5069 void operator()(T&&... v) { | |
5070 boost::wait_for_all(boost::forward<T>(v)...); | |
5071 } | |
5072 }; | |
5073 | |
5074 struct wait_for_any_fctr { | |
5075 template <class ...T> | |
5076 void operator()(T&&... v) { | |
5077 boost::wait_for_any(boost::forward<T>(v)...); | |
5078 } | |
5079 }; | |
5080 | |
5081 | |
5082 template <class Tuple, std::size_t i=csbl::tuple_size<Tuple>::value> | |
5083 struct accumulate_run_if_is_deferred { | |
5084 bool operator ()(Tuple& t) | |
5085 { | |
5086 return (! csbl::get<i-1>(t).run_if_is_deferred()) || accumulate_run_if_is_deferred<Tuple,i-1>()(t); | |
5087 } | |
5088 }; | |
5089 template <class Tuple> | |
5090 struct accumulate_run_if_is_deferred<Tuple, 0> { | |
5091 bool operator ()(Tuple& ) | |
5092 { | |
5093 return false; | |
5094 } | |
5095 }; | |
5096 | |
5097 | |
5098 template< typename Tuple, typename T0, typename ...T> | |
5099 struct future_when_all_tuple_shared_state: future_async_shared_state_base<Tuple> | |
5100 { | |
5101 Tuple tup_; | |
5102 typedef typename make_tuple_indices<1+sizeof...(T)>::type Index; | |
5103 | |
5104 static void run(shared_ptr<boost::detail::shared_state_base> that_) { | |
5105 future_when_all_tuple_shared_state* that = dynamic_cast<future_when_all_tuple_shared_state*>(that_.get()); | |
5106 try { | |
5107 // TODO make use of apply(that->tup_, boost::detail::wait_for_all_fctor()); | |
5108 that->wait_for_all(Index()); | |
5109 | |
5110 that->mark_finished_with_result(boost::move(that->tup_)); | |
5111 } catch(...) { | |
5112 that->mark_exceptional_finish(); | |
5113 } | |
5114 } | |
5115 | |
5116 template <size_t ...Indices> | |
5117 void wait_for_all(tuple_indices<Indices...>) { | |
5118 #if defined BOOST_THREAD_PROVIDES_INVOKE | |
5119 return invoke<void>(wait_for_all_fctr(), csbl::get<Indices>(tup_)...); | |
5120 #else | |
5121 return wait_for_all_fctr()(csbl::get<Indices>(tup_)...); | |
5122 #endif | |
5123 } | |
5124 | |
5125 bool run_deferred() { | |
5126 | |
5127 return accumulate_run_if_is_deferred<Tuple>()(tup_); | |
5128 } | |
5129 void init() { | |
5130 if (! run_deferred()) | |
5131 { | |
5132 future_when_all_tuple_shared_state::run(this->shared_from_this()); | |
5133 return; | |
5134 } | |
5135 | |
5136 this->thr_ = thread(&future_when_all_tuple_shared_state::run, this->shared_from_this()); | |
5137 } | |
5138 public: | |
5139 template< typename F, typename ...Fs> | |
5140 future_when_all_tuple_shared_state(values_tag, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures) : | |
5141 tup_(boost::csbl::make_tuple(boost::forward<F>(f), boost::forward<Fs>(futures)...)) | |
5142 { | |
5143 } | |
5144 | |
5145 ~future_when_all_tuple_shared_state() {} | |
5146 | |
5147 }; | |
5148 | |
5149 | |
5150 template <class Tuple, std::size_t i=csbl::tuple_size<Tuple>::value> | |
5151 struct apply_any_run_if_is_deferred_or_ready { | |
5152 bool operator ()(Tuple& t) | |
5153 { | |
5154 if (csbl::get<i-1>(t).run_if_is_deferred_or_ready()) return true; | |
5155 return apply_any_run_if_is_deferred_or_ready<Tuple,i-1>()(t); | |
5156 } | |
5157 }; | |
5158 template <class Tuple> | |
5159 struct apply_any_run_if_is_deferred_or_ready<Tuple, 0> { | |
5160 bool operator ()(Tuple& ) | |
5161 { | |
5162 return false; | |
5163 } | |
5164 }; | |
5165 | |
5166 template< typename Tuple, typename T0, typename ...T > | |
5167 struct future_when_any_tuple_shared_state: future_async_shared_state_base<Tuple> | |
5168 { | |
5169 Tuple tup_; | |
5170 typedef typename make_tuple_indices<1+sizeof...(T)>::type Index; | |
5171 | |
5172 static void run(shared_ptr<boost::detail::shared_state_base> that_) | |
5173 { | |
5174 future_when_any_tuple_shared_state* that = dynamic_cast<future_when_any_tuple_shared_state*>(that_.get()); | |
5175 try { | |
5176 // TODO make use of apply(that->tup_, wait_for_any_fctr); | |
5177 that->wait_for_any(Index()); | |
5178 | |
5179 that->mark_finished_with_result(boost::move(that->tup_)); | |
5180 } catch(...) { | |
5181 that->mark_exceptional_finish(); | |
5182 } | |
5183 } | |
5184 template <size_t ...Indices> | |
5185 void wait_for_any(tuple_indices<Indices...>) { | |
5186 #if defined BOOST_THREAD_PROVIDES_INVOKE | |
5187 return invoke<void>(wait_for_any_fctr(), csbl::get<Indices>(tup_)...); | |
5188 #else | |
5189 return wait_for_any_fctr()(csbl::get<Indices>(tup_)...); | |
5190 #endif | |
5191 } | |
5192 bool run_deferred() { | |
5193 return apply_any_run_if_is_deferred_or_ready<Tuple>()(tup_); | |
5194 } | |
5195 void init() { | |
5196 if (run_deferred()) | |
5197 { | |
5198 future_when_any_tuple_shared_state::run(this->shared_from_this()); | |
5199 return; | |
5200 } | |
5201 | |
5202 this->thr_ = thread(&future_when_any_tuple_shared_state::run, this->shared_from_this()); | |
5203 } | |
5204 | |
5205 public: | |
5206 template< typename F, typename ...Fs> | |
5207 future_when_any_tuple_shared_state(values_tag, | |
5208 BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures | |
5209 ) : | |
5210 tup_(boost::csbl::make_tuple(boost::forward<F>(f), boost::forward<Fs>(futures)...)) | |
5211 { | |
5212 } | |
5213 | |
5214 ~future_when_any_tuple_shared_state() {} | |
5215 }; | |
5216 #endif | |
5217 | |
5218 } | |
5219 | |
5220 template< typename InputIterator> | |
5221 typename boost::disable_if<is_future_type<InputIterator>, | |
5222 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> > | |
5223 >::type | |
5224 when_all(InputIterator first, InputIterator last) { | |
5225 typedef typename InputIterator::value_type value_type; | |
5226 typedef csbl::vector<value_type> container_type; | |
5227 typedef detail::future_when_all_vector_shared_state<value_type> factory_type; | |
5228 | |
5229 if (first==last) return make_ready_future(container_type()); | |
5230 shared_ptr<factory_type > | |
5231 h(new factory_type(detail::input_iterator_tag_value, first,last)); | |
5232 h->init(); | |
5233 return BOOST_THREAD_FUTURE<container_type>(h); | |
5234 } | |
5235 | |
5236 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all() { | |
5237 return make_ready_future(csbl::tuple<>()); | |
5238 } | |
5239 | |
5240 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
5241 template< typename T0, typename ...T> | |
5242 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> > | |
5243 when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) { | |
5244 typedef csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> container_type; | |
5245 typedef detail::future_when_all_tuple_shared_state<container_type, typename decay<T0>::type, typename decay<T>::type...> factory_type; | |
5246 | |
5247 shared_ptr<factory_type> | |
5248 h(new factory_type(detail::values_tag_value, boost::forward<T0>(f), boost::forward<T>(futures)...)); | |
5249 h->init(); | |
5250 return BOOST_THREAD_FUTURE<container_type>(h); | |
5251 } | |
5252 #endif | |
5253 | |
5254 template< typename InputIterator> | |
5255 typename boost::disable_if<is_future_type<InputIterator>, | |
5256 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> > | |
5257 >::type | |
5258 when_any(InputIterator first, InputIterator last) { | |
5259 typedef typename InputIterator::value_type value_type; | |
5260 typedef csbl::vector<value_type> container_type; | |
5261 typedef detail::future_when_any_vector_shared_state<value_type> factory_type; | |
5262 | |
5263 if (first==last) return make_ready_future(container_type()); | |
5264 shared_ptr<factory_type > | |
5265 h(new factory_type(detail::input_iterator_tag_value, first,last)); | |
5266 h->init(); | |
5267 return BOOST_THREAD_FUTURE<container_type>(h); | |
5268 } | |
5269 | |
5270 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any() { | |
5271 return make_ready_future(csbl::tuple<>()); | |
5272 } | |
5273 | |
5274 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
5275 template< typename T0, typename ...T> | |
5276 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> > | |
5277 when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) { | |
5278 typedef csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> container_type; | |
5279 typedef detail::future_when_any_tuple_shared_state<container_type, typename decay<T0>::type, typename decay<T>::type...> factory_type; | |
5280 | |
5281 shared_ptr<factory_type> | |
5282 h(new factory_type(detail::values_tag_value, boost::forward<T0>(f), boost::forward<T>(futures)...)); | |
5283 h->init(); | |
5284 return BOOST_THREAD_FUTURE<container_type>(h); | |
5285 } | |
5286 #endif | |
5287 #endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY | |
4238 } | 5288 } |
4239 | 5289 |
4240 #endif // BOOST_NO_EXCEPTION | 5290 #endif // BOOST_NO_EXCEPTION |
4241 #endif // header | 5291 #endif // header |