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