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