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