Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/thread/future.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 // (C) Copyright 2008-10 Anthony Williams | |
2 // (C) Copyright 2011-2013 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 #ifndef BOOST_NO_EXCEPTIONS | |
17 | |
18 //#include <boost/thread/detail/log.hpp> | |
19 #include <boost/detail/scoped_enum_emulation.hpp> | |
20 #include <stdexcept> | |
21 #include <boost/thread/detail/move.hpp> | |
22 #include <boost/thread/detail/async_func.hpp> | |
23 #include <boost/thread/thread_time.hpp> | |
24 #include <boost/thread/mutex.hpp> | |
25 #include <boost/thread/condition_variable.hpp> | |
26 #include <boost/thread/lock_algorithms.hpp> | |
27 #include <boost/thread/lock_types.hpp> | |
28 #include <boost/exception_ptr.hpp> | |
29 #include <boost/shared_ptr.hpp> | |
30 #include <boost/scoped_ptr.hpp> | |
31 #include <boost/type_traits/is_fundamental.hpp> | |
32 #include <boost/thread/detail/is_convertible.hpp> | |
33 #include <boost/type_traits/remove_reference.hpp> | |
34 #include <boost/type_traits/remove_cv.hpp> | |
35 #include <boost/type_traits/is_void.hpp> | |
36 #include <boost/mpl/if.hpp> | |
37 #include <boost/config.hpp> | |
38 #include <boost/throw_exception.hpp> | |
39 #include <algorithm> | |
40 #include <boost/function.hpp> | |
41 #include <boost/bind.hpp> | |
42 #include <boost/ref.hpp> | |
43 #include <boost/scoped_array.hpp> | |
44 #include <boost/enable_shared_from_this.hpp> | |
45 #include <boost/utility/enable_if.hpp> | |
46 #include <list> | |
47 #include <boost/next_prior.hpp> | |
48 #include <vector> | |
49 | |
50 #include <boost/thread/future_error_code.hpp> | |
51 #ifdef BOOST_THREAD_USES_CHRONO | |
52 #include <boost/chrono/system_clocks.hpp> | |
53 #endif | |
54 | |
55 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS | |
56 #include <boost/thread/detail/memory.hpp> | |
57 #endif | |
58 | |
59 #include <boost/utility/result_of.hpp> | |
60 #include <boost/thread/thread_only.hpp> | |
61 | |
62 #if defined BOOST_THREAD_PROVIDES_FUTURE | |
63 #define BOOST_THREAD_FUTURE future | |
64 #else | |
65 #define BOOST_THREAD_FUTURE unique_future | |
66 #endif | |
67 | |
68 namespace boost | |
69 { | |
70 | |
71 //enum class launch | |
72 BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch) | |
73 { | |
74 none = 0, | |
75 async = 1, | |
76 deferred = 2, | |
77 any = async | deferred | |
78 } | |
79 BOOST_SCOPED_ENUM_DECLARE_END(launch) | |
80 | |
81 //enum class future_status | |
82 BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status) | |
83 { | |
84 ready, | |
85 timeout, | |
86 deferred | |
87 } | |
88 BOOST_SCOPED_ENUM_DECLARE_END(future_status) | |
89 | |
90 class BOOST_SYMBOL_VISIBLE future_error | |
91 : public std::logic_error | |
92 { | |
93 system::error_code ec_; | |
94 public: | |
95 future_error(system::error_code ec) | |
96 : logic_error(ec.message()), | |
97 ec_(ec) | |
98 { | |
99 } | |
100 | |
101 const system::error_code& code() const BOOST_NOEXCEPT | |
102 { | |
103 return ec_; | |
104 } | |
105 }; | |
106 | |
107 class BOOST_SYMBOL_VISIBLE future_uninitialized: | |
108 public future_error | |
109 { | |
110 public: | |
111 future_uninitialized() : | |
112 future_error(system::make_error_code(future_errc::no_state)) | |
113 {} | |
114 }; | |
115 class BOOST_SYMBOL_VISIBLE broken_promise: | |
116 public future_error | |
117 { | |
118 public: | |
119 broken_promise(): | |
120 future_error(system::make_error_code(future_errc::broken_promise)) | |
121 {} | |
122 }; | |
123 class BOOST_SYMBOL_VISIBLE future_already_retrieved: | |
124 public future_error | |
125 { | |
126 public: | |
127 future_already_retrieved(): | |
128 future_error(system::make_error_code(future_errc::future_already_retrieved)) | |
129 {} | |
130 }; | |
131 class BOOST_SYMBOL_VISIBLE promise_already_satisfied: | |
132 public future_error | |
133 { | |
134 public: | |
135 promise_already_satisfied(): | |
136 future_error(system::make_error_code(future_errc::promise_already_satisfied)) | |
137 {} | |
138 }; | |
139 | |
140 class BOOST_SYMBOL_VISIBLE task_already_started: | |
141 public future_error | |
142 { | |
143 public: | |
144 task_already_started(): | |
145 future_error(system::make_error_code(future_errc::promise_already_satisfied)) | |
146 {} | |
147 }; | |
148 | |
149 class BOOST_SYMBOL_VISIBLE task_moved: | |
150 public future_error | |
151 { | |
152 public: | |
153 task_moved(): | |
154 future_error(system::make_error_code(future_errc::no_state)) | |
155 {} | |
156 }; | |
157 | |
158 class promise_moved: | |
159 public future_error | |
160 { | |
161 public: | |
162 promise_moved(): | |
163 future_error(system::make_error_code(future_errc::no_state)) | |
164 {} | |
165 }; | |
166 | |
167 namespace future_state | |
168 { | |
169 enum state { uninitialized, waiting, ready, moved, deferred }; | |
170 } | |
171 | |
172 namespace detail | |
173 { | |
174 struct relocker | |
175 { | |
176 boost::unique_lock<boost::mutex>& lock_; | |
177 bool unlocked_; | |
178 | |
179 relocker(boost::unique_lock<boost::mutex>& lk): | |
180 lock_(lk) | |
181 { | |
182 lock_.unlock(); | |
183 unlocked_=true; | |
184 } | |
185 ~relocker() | |
186 { | |
187 if (unlocked_) { | |
188 lock_.lock(); | |
189 } | |
190 } | |
191 void lock() { | |
192 if (unlocked_) { | |
193 lock_.lock(); | |
194 unlocked_=false; | |
195 } | |
196 } | |
197 private: | |
198 relocker& operator=(relocker const&); | |
199 }; | |
200 | |
201 struct shared_state_base : enable_shared_from_this<shared_state_base> | |
202 { | |
203 typedef std::list<boost::condition_variable_any*> waiter_list; | |
204 // This type should be only included conditionally if interruptions are allowed, but is included to maintain the same layout. | |
205 typedef shared_ptr<shared_state_base> continuation_ptr_type; | |
206 | |
207 boost::exception_ptr exception; | |
208 bool done; | |
209 bool is_deferred_; | |
210 launch policy_; | |
211 bool is_constructed; | |
212 mutable boost::mutex mutex; | |
213 boost::condition_variable waiters; | |
214 waiter_list external_waiters; | |
215 boost::function<void()> callback; | |
216 // This declaration should be only included conditionally if interruptions are allowed, but is included to maintain the same layout. | |
217 bool thread_was_interrupted; | |
218 // This declaration should be only included conditionally, but is included to maintain the same layout. | |
219 continuation_ptr_type continuation_ptr; | |
220 | |
221 // This declaration should be only included conditionally, but is included to maintain the same layout. | |
222 virtual void launch_continuation(boost::unique_lock<boost::mutex>&) | |
223 { | |
224 } | |
225 | |
226 shared_state_base(): | |
227 done(false), | |
228 is_deferred_(false), | |
229 policy_(launch::none), | |
230 is_constructed(false), | |
231 thread_was_interrupted(false), | |
232 continuation_ptr() | |
233 {} | |
234 virtual ~shared_state_base() | |
235 {} | |
236 | |
237 void set_deferred() | |
238 { | |
239 is_deferred_ = true; | |
240 policy_ = launch::deferred; | |
241 } | |
242 void set_async() | |
243 { | |
244 is_deferred_ = false; | |
245 policy_ = launch::async; | |
246 } | |
247 | |
248 waiter_list::iterator register_external_waiter(boost::condition_variable_any& cv) | |
249 { | |
250 boost::unique_lock<boost::mutex> lock(mutex); | |
251 do_callback(lock); | |
252 return external_waiters.insert(external_waiters.end(),&cv); | |
253 } | |
254 | |
255 void remove_external_waiter(waiter_list::iterator it) | |
256 { | |
257 boost::lock_guard<boost::mutex> lock(mutex); | |
258 external_waiters.erase(it); | |
259 } | |
260 | |
261 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | |
262 void do_continuation(boost::unique_lock<boost::mutex>& lock) | |
263 { | |
264 if (continuation_ptr) { | |
265 continuation_ptr->launch_continuation(lock); | |
266 if (! lock.owns_lock()) | |
267 lock.lock(); | |
268 continuation_ptr.reset(); | |
269 } | |
270 } | |
271 #else | |
272 void do_continuation(boost::unique_lock<boost::mutex>&) | |
273 { | |
274 } | |
275 #endif | |
276 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | |
277 void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock) | |
278 { | |
279 continuation_ptr= continuation; | |
280 if (done) { | |
281 do_continuation(lock); | |
282 } | |
283 } | |
284 #endif | |
285 void mark_finished_internal(boost::unique_lock<boost::mutex>& lock) | |
286 { | |
287 done=true; | |
288 waiters.notify_all(); | |
289 for(waiter_list::const_iterator it=external_waiters.begin(), | |
290 end=external_waiters.end();it!=end;++it) | |
291 { | |
292 (*it)->notify_all(); | |
293 } | |
294 do_continuation(lock); | |
295 } | |
296 void make_ready() | |
297 { | |
298 boost::unique_lock<boost::mutex> lock(mutex); | |
299 mark_finished_internal(lock); | |
300 } | |
301 | |
302 void do_callback(boost::unique_lock<boost::mutex>& lock) | |
303 { | |
304 if(callback && !done) | |
305 { | |
306 boost::function<void()> local_callback=callback; | |
307 relocker relock(lock); | |
308 local_callback(); | |
309 } | |
310 } | |
311 | |
312 void wait_internal(boost::unique_lock<boost::mutex> &lk, bool rethrow=true) | |
313 { | |
314 do_callback(lk); | |
315 //if (!done) // fixme why this doesn't work? | |
316 { | |
317 if (is_deferred_) | |
318 { | |
319 is_deferred_=false; | |
320 execute(lk); | |
321 //lk.unlock(); | |
322 } | |
323 else | |
324 { | |
325 while(!done) | |
326 { | |
327 waiters.wait(lk); | |
328 } | |
329 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
330 if(rethrow && thread_was_interrupted) | |
331 { | |
332 throw boost::thread_interrupted(); | |
333 } | |
334 #endif | |
335 if(rethrow && exception) | |
336 { | |
337 boost::rethrow_exception(exception); | |
338 } | |
339 } | |
340 } | |
341 } | |
342 | |
343 virtual void wait(bool rethrow=true) | |
344 { | |
345 boost::unique_lock<boost::mutex> lock(mutex); | |
346 wait_internal(lock, rethrow); | |
347 } | |
348 | |
349 #if defined BOOST_THREAD_USES_DATETIME | |
350 bool timed_wait_until(boost::system_time const& target_time) | |
351 { | |
352 boost::unique_lock<boost::mutex> lock(mutex); | |
353 if (is_deferred_) | |
354 return false; | |
355 | |
356 do_callback(lock); | |
357 while(!done) | |
358 { | |
359 bool const success=waiters.timed_wait(lock,target_time); | |
360 if(!success && !done) | |
361 { | |
362 return false; | |
363 } | |
364 } | |
365 return true; | |
366 } | |
367 #endif | |
368 #ifdef BOOST_THREAD_USES_CHRONO | |
369 | |
370 template <class Clock, class Duration> | |
371 future_status | |
372 wait_until(const chrono::time_point<Clock, Duration>& abs_time) | |
373 { | |
374 boost::unique_lock<boost::mutex> lock(mutex); | |
375 if (is_deferred_) | |
376 return future_status::deferred; | |
377 do_callback(lock); | |
378 while(!done) | |
379 { | |
380 cv_status const st=waiters.wait_until(lock,abs_time); | |
381 if(st==cv_status::timeout && !done) | |
382 { | |
383 return future_status::timeout; | |
384 } | |
385 } | |
386 return future_status::ready; | |
387 } | |
388 #endif | |
389 void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock<boost::mutex>& lock) | |
390 { | |
391 exception=e; | |
392 mark_finished_internal(lock); | |
393 } | |
394 | |
395 void mark_exceptional_finish() | |
396 { | |
397 boost::unique_lock<boost::mutex> lock(mutex); | |
398 mark_exceptional_finish_internal(boost::current_exception(), lock); | |
399 } | |
400 | |
401 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
402 void mark_interrupted_finish() | |
403 { | |
404 boost::unique_lock<boost::mutex> lock(mutex); | |
405 thread_was_interrupted=true; | |
406 mark_finished_internal(lock); | |
407 } | |
408 | |
409 void set_interrupted_at_thread_exit() | |
410 { | |
411 unique_lock<boost::mutex> lk(mutex); | |
412 thread_was_interrupted=true; | |
413 if (has_value(lk)) | |
414 { | |
415 throw_exception(promise_already_satisfied()); | |
416 } | |
417 detail::make_ready_at_thread_exit(shared_from_this()); | |
418 } | |
419 #endif | |
420 | |
421 void set_exception_at_thread_exit(exception_ptr e) | |
422 { | |
423 unique_lock<boost::mutex> lk(mutex); | |
424 if (has_value(lk)) | |
425 { | |
426 throw_exception(promise_already_satisfied()); | |
427 } | |
428 exception=e; | |
429 this->is_constructed = true; | |
430 detail::make_ready_at_thread_exit(shared_from_this()); | |
431 | |
432 } | |
433 | |
434 bool has_value() const | |
435 { | |
436 boost::lock_guard<boost::mutex> lock(mutex); | |
437 return done && !(exception | |
438 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
439 || thread_was_interrupted | |
440 #endif | |
441 ); | |
442 } | |
443 | |
444 bool has_value(unique_lock<boost::mutex>& ) const | |
445 { | |
446 return done && !(exception | |
447 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
448 || thread_was_interrupted | |
449 #endif | |
450 ); | |
451 } | |
452 | |
453 bool has_exception() const | |
454 { | |
455 boost::lock_guard<boost::mutex> lock(mutex); | |
456 return done && (exception | |
457 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
458 || thread_was_interrupted | |
459 #endif | |
460 ); | |
461 } | |
462 | |
463 bool has_exception(unique_lock<boost::mutex>&) const | |
464 { | |
465 return done && (exception | |
466 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
467 || thread_was_interrupted | |
468 #endif | |
469 ); | |
470 } | |
471 | |
472 bool is_deferred(boost::lock_guard<boost::mutex>&) const { | |
473 return is_deferred_; | |
474 } | |
475 | |
476 launch launch_policy(boost::unique_lock<boost::mutex>&) const | |
477 { | |
478 return policy_; | |
479 } | |
480 | |
481 future_state::state get_state() const | |
482 { | |
483 boost::lock_guard<boost::mutex> guard(mutex); | |
484 if(!done) | |
485 { | |
486 return future_state::waiting; | |
487 } | |
488 else | |
489 { | |
490 return future_state::ready; | |
491 } | |
492 } | |
493 | |
494 exception_ptr get_exception_ptr() | |
495 { | |
496 boost::unique_lock<boost::mutex> lock(mutex); | |
497 return get_exception_ptr(lock); | |
498 } | |
499 exception_ptr get_exception_ptr(boost::unique_lock<boost::mutex>& lock) | |
500 { | |
501 wait_internal(lock, false); | |
502 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
503 if(thread_was_interrupted) | |
504 { | |
505 return copy_exception(boost::thread_interrupted()); | |
506 } | |
507 #endif | |
508 return exception; | |
509 } | |
510 | |
511 template<typename F,typename U> | |
512 void set_wait_callback(F f,U* u) | |
513 { | |
514 boost::lock_guard<boost::mutex> lock(mutex); | |
515 callback=boost::bind(f,boost::ref(*u)); | |
516 } | |
517 | |
518 virtual void execute(boost::unique_lock<boost::mutex>&) {} | |
519 | |
520 private: | |
521 shared_state_base(shared_state_base const&); | |
522 shared_state_base& operator=(shared_state_base const&); | |
523 }; | |
524 | |
525 template<typename T> | |
526 struct future_traits | |
527 { | |
528 typedef boost::scoped_ptr<T> storage_type; | |
529 struct dummy; | |
530 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
531 typedef T const& source_reference_type; | |
532 //typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type; | |
533 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type; | |
534 //typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type; | |
535 typedef T move_dest_type; | |
536 #elif defined BOOST_THREAD_USES_MOVE | |
537 typedef typename boost::mpl::if_c<boost::is_fundamental<T>::value,T,T&>::type source_reference_type; | |
538 //typedef typename boost::mpl::if_c<boost::is_fundamental<T>::value,T,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type; | |
539 //typedef typename boost::mpl::if_c<boost::enable_move_utility_emulation<T>::value,BOOST_THREAD_RV_REF(T),T>::type move_dest_type; | |
540 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type; | |
541 typedef T move_dest_type; | |
542 #else | |
543 typedef T& source_reference_type; | |
544 typedef typename boost::mpl::if_<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type; | |
545 typedef typename boost::mpl::if_<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T>::type move_dest_type; | |
546 #endif | |
547 | |
548 | |
549 typedef const T& shared_future_get_result_type; | |
550 | |
551 static void init(storage_type& storage,source_reference_type t) | |
552 { | |
553 storage.reset(new T(t)); | |
554 } | |
555 | |
556 static void init(storage_type& storage,rvalue_source_type t) | |
557 { | |
558 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES | |
559 storage.reset(new T(boost::forward<T>(t))); | |
560 #else | |
561 storage.reset(new T(static_cast<rvalue_source_type>(t))); | |
562 #endif | |
563 } | |
564 | |
565 static void cleanup(storage_type& storage) | |
566 { | |
567 storage.reset(); | |
568 } | |
569 }; | |
570 | |
571 template<typename T> | |
572 struct future_traits<T&> | |
573 { | |
574 typedef T* storage_type; | |
575 typedef T& source_reference_type; | |
576 //struct rvalue_source_type | |
577 //{}; | |
578 typedef T& move_dest_type; | |
579 typedef T& shared_future_get_result_type; | |
580 | |
581 static void init(storage_type& storage,T& t) | |
582 { | |
583 storage=&t; | |
584 } | |
585 | |
586 static void cleanup(storage_type& storage) | |
587 { | |
588 storage=0; | |
589 } | |
590 }; | |
591 | |
592 template<> | |
593 struct future_traits<void> | |
594 { | |
595 typedef bool storage_type; | |
596 typedef void move_dest_type; | |
597 typedef void shared_future_get_result_type; | |
598 | |
599 static void init(storage_type& storage) | |
600 { | |
601 storage=true; | |
602 } | |
603 | |
604 static void cleanup(storage_type& storage) | |
605 { | |
606 storage=false; | |
607 } | |
608 | |
609 }; | |
610 | |
611 // Used to create stand-alone futures | |
612 template<typename T> | |
613 struct shared_state: | |
614 detail::shared_state_base | |
615 { | |
616 typedef typename future_traits<T>::storage_type storage_type; | |
617 typedef typename future_traits<T>::source_reference_type source_reference_type; | |
618 typedef typename future_traits<T>::rvalue_source_type rvalue_source_type; | |
619 typedef typename future_traits<T>::move_dest_type move_dest_type; | |
620 typedef typename future_traits<T>::shared_future_get_result_type shared_future_get_result_type; | |
621 | |
622 storage_type result; | |
623 | |
624 shared_state(): | |
625 result(0) | |
626 {} | |
627 | |
628 ~shared_state() | |
629 {} | |
630 | |
631 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock) | |
632 { | |
633 future_traits<T>::init(result,result_); | |
634 this->mark_finished_internal(lock); | |
635 } | |
636 | |
637 void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock) | |
638 { | |
639 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES | |
640 future_traits<T>::init(result,boost::forward<T>(result_)); | |
641 #else | |
642 future_traits<T>::init(result,static_cast<rvalue_source_type>(result_)); | |
643 #endif | |
644 this->mark_finished_internal(lock); | |
645 } | |
646 | |
647 void mark_finished_with_result(source_reference_type result_) | |
648 { | |
649 boost::unique_lock<boost::mutex> lock(mutex); | |
650 this->mark_finished_with_result_internal(result_, lock); | |
651 } | |
652 | |
653 void mark_finished_with_result(rvalue_source_type result_) | |
654 { | |
655 boost::unique_lock<boost::mutex> lock(mutex); | |
656 | |
657 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES | |
658 mark_finished_with_result_internal(boost::forward<T>(result_), lock); | |
659 #else | |
660 mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock); | |
661 #endif | |
662 } | |
663 | |
664 virtual move_dest_type get() | |
665 { | |
666 wait(); | |
667 return boost::move(*result); | |
668 } | |
669 | |
670 virtual shared_future_get_result_type get_sh() | |
671 { | |
672 wait(); | |
673 return *result; | |
674 } | |
675 | |
676 //void set_value_at_thread_exit(const T & result_) | |
677 void set_value_at_thread_exit(source_reference_type result_) | |
678 { | |
679 unique_lock<boost::mutex> lk(this->mutex); | |
680 if (this->has_value(lk)) | |
681 { | |
682 throw_exception(promise_already_satisfied()); | |
683 } | |
684 //future_traits<T>::init(result,result_); | |
685 result.reset(new T(result_)); | |
686 | |
687 this->is_constructed = true; | |
688 detail::make_ready_at_thread_exit(shared_from_this()); | |
689 } | |
690 //void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T) result_) | |
691 void set_value_at_thread_exit(rvalue_source_type result_) | |
692 { | |
693 unique_lock<boost::mutex> lk(this->mutex); | |
694 if (this->has_value(lk)) | |
695 throw_exception(promise_already_satisfied()); | |
696 result.reset(new T(boost::move(result_))); | |
697 //future_traits<T>::init(result,static_cast<rvalue_source_type>(result_)); | |
698 this->is_constructed = true; | |
699 detail::make_ready_at_thread_exit(shared_from_this()); | |
700 } | |
701 | |
702 | |
703 private: | |
704 shared_state(shared_state const&); | |
705 shared_state& operator=(shared_state const&); | |
706 }; | |
707 | |
708 template<typename T> | |
709 struct shared_state<T&>: | |
710 detail::shared_state_base | |
711 { | |
712 typedef typename future_traits<T&>::storage_type storage_type; | |
713 typedef typename future_traits<T&>::source_reference_type source_reference_type; | |
714 typedef typename future_traits<T&>::move_dest_type move_dest_type; | |
715 typedef typename future_traits<T&>::shared_future_get_result_type shared_future_get_result_type; | |
716 | |
717 T* result; | |
718 | |
719 shared_state(): | |
720 result(0) | |
721 {} | |
722 | |
723 ~shared_state() | |
724 { | |
725 } | |
726 | |
727 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock) | |
728 { | |
729 //future_traits<T>::init(result,result_); | |
730 result= &result_; | |
731 mark_finished_internal(lock); | |
732 } | |
733 | |
734 void mark_finished_with_result(source_reference_type result_) | |
735 { | |
736 boost::unique_lock<boost::mutex> lock(mutex); | |
737 mark_finished_with_result_internal(result_, lock); | |
738 } | |
739 | |
740 virtual T& get() | |
741 { | |
742 wait(); | |
743 return *result; | |
744 } | |
745 | |
746 virtual T& get_sh() | |
747 { | |
748 wait(); | |
749 return *result; | |
750 } | |
751 | |
752 void set_value_at_thread_exit(T& result_) | |
753 { | |
754 unique_lock<boost::mutex> lk(this->mutex); | |
755 if (this->has_value(lk)) | |
756 throw_exception(promise_already_satisfied()); | |
757 //future_traits<T>::init(result,result_); | |
758 result= &result_; | |
759 this->is_constructed = true; | |
760 detail::make_ready_at_thread_exit(shared_from_this()); | |
761 } | |
762 | |
763 private: | |
764 shared_state(shared_state const&); | |
765 shared_state& operator=(shared_state const&); | |
766 }; | |
767 | |
768 template<> | |
769 struct shared_state<void>: | |
770 detail::shared_state_base | |
771 { | |
772 typedef void shared_future_get_result_type; | |
773 | |
774 shared_state() | |
775 {} | |
776 | |
777 void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock) | |
778 { | |
779 mark_finished_internal(lock); | |
780 } | |
781 | |
782 void mark_finished_with_result() | |
783 { | |
784 boost::unique_lock<boost::mutex> lock(mutex); | |
785 mark_finished_with_result_internal(lock); | |
786 } | |
787 | |
788 virtual void get() | |
789 { | |
790 this->wait(); | |
791 } | |
792 | |
793 virtual void get_sh() | |
794 { | |
795 wait(); | |
796 } | |
797 | |
798 void set_value_at_thread_exit() | |
799 { | |
800 unique_lock<boost::mutex> lk(this->mutex); | |
801 if (this->has_value(lk)) | |
802 { | |
803 throw_exception(promise_already_satisfied()); | |
804 } | |
805 this->is_constructed = true; | |
806 detail::make_ready_at_thread_exit(shared_from_this()); | |
807 } | |
808 private: | |
809 shared_state(shared_state const&); | |
810 shared_state& operator=(shared_state const&); | |
811 }; | |
812 | |
813 ///////////////////////// | |
814 /// future_async_shared_state_base | |
815 ///////////////////////// | |
816 template<typename Rp> | |
817 struct future_async_shared_state_base: shared_state<Rp> | |
818 { | |
819 typedef shared_state<Rp> base_type; | |
820 protected: | |
821 boost::thread thr_; | |
822 void join() | |
823 { | |
824 if (thr_.joinable()) thr_.join(); | |
825 } | |
826 public: | |
827 future_async_shared_state_base() | |
828 { | |
829 this->set_async(); | |
830 } | |
831 explicit future_async_shared_state_base(BOOST_THREAD_RV_REF(boost::thread) th) : | |
832 thr_(boost::move(th)) | |
833 { | |
834 this->set_async(); | |
835 } | |
836 | |
837 ~future_async_shared_state_base() | |
838 { | |
839 join(); | |
840 } | |
841 | |
842 virtual void wait(bool rethrow) | |
843 { | |
844 join(); | |
845 this->base_type::wait(rethrow); | |
846 } | |
847 }; | |
848 | |
849 ///////////////////////// | |
850 /// future_async_shared_state | |
851 ///////////////////////// | |
852 template<typename Rp, typename Fp> | |
853 struct future_async_shared_state: future_async_shared_state_base<Rp> | |
854 { | |
855 typedef future_async_shared_state_base<Rp> base_type; | |
856 | |
857 public: | |
858 explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) : | |
859 base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f))) | |
860 { | |
861 } | |
862 | |
863 static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f) | |
864 { | |
865 try | |
866 { | |
867 that->mark_finished_with_result(f()); | |
868 } | |
869 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
870 catch(thread_interrupted& ) | |
871 { | |
872 that->mark_interrupted_finish(); | |
873 } | |
874 #endif | |
875 catch(...) | |
876 { | |
877 that->mark_exceptional_finish(); | |
878 } | |
879 } | |
880 }; | |
881 | |
882 template<typename Fp> | |
883 struct future_async_shared_state<void, Fp>: public future_async_shared_state_base<void> | |
884 { | |
885 typedef future_async_shared_state_base<void> base_type; | |
886 | |
887 public: | |
888 explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) : | |
889 base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f))) | |
890 { | |
891 } | |
892 | |
893 static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f) | |
894 { | |
895 try | |
896 { | |
897 f(); | |
898 that->mark_finished_with_result(); | |
899 } | |
900 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
901 catch(thread_interrupted& ) | |
902 { | |
903 that->mark_interrupted_finish(); | |
904 } | |
905 #endif | |
906 catch(...) | |
907 { | |
908 that->mark_exceptional_finish(); | |
909 } | |
910 } | |
911 }; | |
912 | |
913 template<typename Rp, typename Fp> | |
914 struct future_async_shared_state<Rp&, Fp>: future_async_shared_state_base<Rp&> | |
915 { | |
916 typedef future_async_shared_state_base<Rp&> base_type; | |
917 | |
918 public: | |
919 explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) : | |
920 base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f))) | |
921 { | |
922 } | |
923 | |
924 static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f) | |
925 { | |
926 try | |
927 { | |
928 that->mark_finished_with_result(f()); | |
929 } | |
930 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
931 catch(thread_interrupted& ) | |
932 { | |
933 that->mark_interrupted_finish(); | |
934 } | |
935 #endif | |
936 catch(...) | |
937 { | |
938 that->mark_exceptional_finish(); | |
939 } | |
940 } | |
941 }; | |
942 | |
943 ////////////////////////// | |
944 /// future_deferred_shared_state | |
945 ////////////////////////// | |
946 template<typename Rp, typename Fp> | |
947 struct future_deferred_shared_state: shared_state<Rp> | |
948 { | |
949 typedef shared_state<Rp> base_type; | |
950 Fp func_; | |
951 | |
952 public: | |
953 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) | |
954 : func_(boost::forward<Fp>(f)) | |
955 { | |
956 this->set_deferred(); | |
957 } | |
958 | |
959 virtual void execute(boost::unique_lock<boost::mutex>& lck) { | |
960 try | |
961 { | |
962 Fp local_fuct=boost::move(func_); | |
963 relocker relock(lck); | |
964 Rp res = local_fuct(); | |
965 relock.lock(); | |
966 this->mark_finished_with_result_internal(boost::move(res), lck); | |
967 } | |
968 catch (...) | |
969 { | |
970 this->mark_exceptional_finish_internal(current_exception(), lck); | |
971 } | |
972 } | |
973 }; | |
974 template<typename Rp, typename Fp> | |
975 struct future_deferred_shared_state<Rp&,Fp>: shared_state<Rp&> | |
976 { | |
977 typedef shared_state<Rp&> base_type; | |
978 Fp func_; | |
979 | |
980 public: | |
981 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) | |
982 : func_(boost::forward<Fp>(f)) | |
983 { | |
984 this->set_deferred(); | |
985 } | |
986 | |
987 virtual void execute(boost::unique_lock<boost::mutex>& lck) { | |
988 try | |
989 { | |
990 this->mark_finished_with_result_internal(func_(), lck); | |
991 } | |
992 catch (...) | |
993 { | |
994 this->mark_exceptional_finish_internal(current_exception(), lck); | |
995 } | |
996 } | |
997 }; | |
998 | |
999 template<typename Fp> | |
1000 struct future_deferred_shared_state<void,Fp>: shared_state<void> | |
1001 { | |
1002 typedef shared_state<void> base_type; | |
1003 Fp func_; | |
1004 | |
1005 public: | |
1006 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) | |
1007 : func_(boost::forward<Fp>(f)) | |
1008 { | |
1009 this->set_deferred(); | |
1010 } | |
1011 | |
1012 virtual void execute(boost::unique_lock<boost::mutex>& lck) { | |
1013 try | |
1014 { | |
1015 Fp local_fuct=boost::move(func_); | |
1016 relocker relock(lck); | |
1017 local_fuct(); | |
1018 relock.lock(); | |
1019 this->mark_finished_with_result_internal(lck); | |
1020 } | |
1021 catch (...) | |
1022 { | |
1023 this->mark_exceptional_finish_internal(current_exception(), lck); | |
1024 } | |
1025 } | |
1026 }; | |
1027 | |
1028 // template<typename T, typename Allocator> | |
1029 // struct shared_state_alloc: public shared_state<T> | |
1030 // { | |
1031 // typedef shared_state<T> base; | |
1032 // Allocator alloc_; | |
1033 // | |
1034 // public: | |
1035 // explicit shared_state_alloc(const Allocator& a) | |
1036 // : alloc_(a) {} | |
1037 // | |
1038 // }; | |
1039 class future_waiter | |
1040 { | |
1041 struct registered_waiter; | |
1042 typedef std::vector<int>::size_type count_type; | |
1043 | |
1044 struct registered_waiter | |
1045 { | |
1046 boost::shared_ptr<detail::shared_state_base> future_; | |
1047 detail::shared_state_base::waiter_list::iterator wait_iterator; | |
1048 count_type index; | |
1049 | |
1050 registered_waiter(boost::shared_ptr<detail::shared_state_base> const& a_future, | |
1051 detail::shared_state_base::waiter_list::iterator wait_iterator_, | |
1052 count_type index_): | |
1053 future_(a_future),wait_iterator(wait_iterator_),index(index_) | |
1054 {} | |
1055 }; | |
1056 | |
1057 struct all_futures_lock | |
1058 { | |
1059 #ifdef _MANAGED | |
1060 typedef std::ptrdiff_t count_type_portable; | |
1061 #else | |
1062 typedef count_type count_type_portable; | |
1063 #endif | |
1064 count_type_portable count; | |
1065 boost::scoped_array<boost::unique_lock<boost::mutex> > locks; | |
1066 | |
1067 all_futures_lock(std::vector<registered_waiter>& futures): | |
1068 count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count]) | |
1069 { | |
1070 for(count_type_portable i=0;i<count;++i) | |
1071 { | |
1072 #if defined __DECCXX || defined __SUNPRO_CC || defined __hpux | |
1073 locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex).move(); | |
1074 #else | |
1075 locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex); | |
1076 #endif | |
1077 } | |
1078 } | |
1079 | |
1080 void lock() | |
1081 { | |
1082 boost::lock(locks.get(),locks.get()+count); | |
1083 } | |
1084 | |
1085 void unlock() | |
1086 { | |
1087 for(count_type_portable i=0;i<count;++i) | |
1088 { | |
1089 locks[i].unlock(); | |
1090 } | |
1091 } | |
1092 }; | |
1093 | |
1094 boost::condition_variable_any cv; | |
1095 std::vector<registered_waiter> futures; | |
1096 count_type future_count; | |
1097 | |
1098 public: | |
1099 future_waiter(): | |
1100 future_count(0) | |
1101 {} | |
1102 | |
1103 template<typename F> | |
1104 void add(F& f) | |
1105 { | |
1106 if(f.future_) | |
1107 { | |
1108 futures.push_back(registered_waiter(f.future_,f.future_->register_external_waiter(cv),future_count)); | |
1109 } | |
1110 ++future_count; | |
1111 } | |
1112 | |
1113 count_type wait() | |
1114 { | |
1115 all_futures_lock lk(futures); | |
1116 for(;;) | |
1117 { | |
1118 for(count_type i=0;i<futures.size();++i) | |
1119 { | |
1120 if(futures[i].future_->done) | |
1121 { | |
1122 return futures[i].index; | |
1123 } | |
1124 } | |
1125 cv.wait(lk); | |
1126 } | |
1127 } | |
1128 | |
1129 ~future_waiter() | |
1130 { | |
1131 for(count_type i=0;i<futures.size();++i) | |
1132 { | |
1133 futures[i].future_->remove_external_waiter(futures[i].wait_iterator); | |
1134 } | |
1135 } | |
1136 | |
1137 }; | |
1138 | |
1139 } | |
1140 | |
1141 template <typename R> | |
1142 class BOOST_THREAD_FUTURE; | |
1143 | |
1144 template <typename R> | |
1145 class shared_future; | |
1146 | |
1147 template<typename T> | |
1148 struct is_future_type | |
1149 { | |
1150 BOOST_STATIC_CONSTANT(bool, value=false); | |
1151 typedef void type; | |
1152 }; | |
1153 | |
1154 template<typename T> | |
1155 struct is_future_type<BOOST_THREAD_FUTURE<T> > | |
1156 { | |
1157 BOOST_STATIC_CONSTANT(bool, value=true); | |
1158 typedef T type; | |
1159 }; | |
1160 | |
1161 template<typename T> | |
1162 struct is_future_type<shared_future<T> > | |
1163 { | |
1164 BOOST_STATIC_CONSTANT(bool, value=true); | |
1165 typedef T type; | |
1166 }; | |
1167 | |
1168 template<typename Iterator> | |
1169 typename boost::disable_if<is_future_type<Iterator>,void>::type wait_for_all(Iterator begin,Iterator end) | |
1170 { | |
1171 for(Iterator current=begin;current!=end;++current) | |
1172 { | |
1173 current->wait(); | |
1174 } | |
1175 } | |
1176 | |
1177 template<typename F1,typename F2> | |
1178 typename boost::enable_if<is_future_type<F1>,void>::type wait_for_all(F1& f1,F2& f2) | |
1179 { | |
1180 f1.wait(); | |
1181 f2.wait(); | |
1182 } | |
1183 | |
1184 template<typename F1,typename F2,typename F3> | |
1185 void wait_for_all(F1& f1,F2& f2,F3& f3) | |
1186 { | |
1187 f1.wait(); | |
1188 f2.wait(); | |
1189 f3.wait(); | |
1190 } | |
1191 | |
1192 template<typename F1,typename F2,typename F3,typename F4> | |
1193 void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4) | |
1194 { | |
1195 f1.wait(); | |
1196 f2.wait(); | |
1197 f3.wait(); | |
1198 f4.wait(); | |
1199 } | |
1200 | |
1201 template<typename F1,typename F2,typename F3,typename F4,typename F5> | |
1202 void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5) | |
1203 { | |
1204 f1.wait(); | |
1205 f2.wait(); | |
1206 f3.wait(); | |
1207 f4.wait(); | |
1208 f5.wait(); | |
1209 } | |
1210 | |
1211 template<typename Iterator> | |
1212 typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end) | |
1213 { | |
1214 if(begin==end) | |
1215 return end; | |
1216 | |
1217 detail::future_waiter waiter; | |
1218 for(Iterator current=begin;current!=end;++current) | |
1219 { | |
1220 waiter.add(*current); | |
1221 } | |
1222 return boost::next(begin,waiter.wait()); | |
1223 } | |
1224 | |
1225 template<typename F1,typename F2> | |
1226 typename boost::enable_if<is_future_type<F1>,unsigned>::type wait_for_any(F1& f1,F2& f2) | |
1227 { | |
1228 detail::future_waiter waiter; | |
1229 waiter.add(f1); | |
1230 waiter.add(f2); | |
1231 return waiter.wait(); | |
1232 } | |
1233 | |
1234 template<typename F1,typename F2,typename F3> | |
1235 unsigned wait_for_any(F1& f1,F2& f2,F3& f3) | |
1236 { | |
1237 detail::future_waiter waiter; | |
1238 waiter.add(f1); | |
1239 waiter.add(f2); | |
1240 waiter.add(f3); | |
1241 return waiter.wait(); | |
1242 } | |
1243 | |
1244 template<typename F1,typename F2,typename F3,typename F4> | |
1245 unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4) | |
1246 { | |
1247 detail::future_waiter waiter; | |
1248 waiter.add(f1); | |
1249 waiter.add(f2); | |
1250 waiter.add(f3); | |
1251 waiter.add(f4); | |
1252 return waiter.wait(); | |
1253 } | |
1254 | |
1255 template<typename F1,typename F2,typename F3,typename F4,typename F5> | |
1256 unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5) | |
1257 { | |
1258 detail::future_waiter waiter; | |
1259 waiter.add(f1); | |
1260 waiter.add(f2); | |
1261 waiter.add(f3); | |
1262 waiter.add(f4); | |
1263 waiter.add(f5); | |
1264 return waiter.wait(); | |
1265 } | |
1266 | |
1267 template <typename R> | |
1268 class promise; | |
1269 | |
1270 template <typename R> | |
1271 class packaged_task; | |
1272 | |
1273 namespace detail | |
1274 { | |
1275 /// Common implementation for all the futures independently of the return type | |
1276 class base_future | |
1277 { | |
1278 //BOOST_THREAD_MOVABLE(base_future) | |
1279 | |
1280 }; | |
1281 /// Common implementation for future and shared_future. | |
1282 template <typename R> | |
1283 class basic_future : public base_future | |
1284 { | |
1285 protected: | |
1286 public: | |
1287 | |
1288 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr; | |
1289 | |
1290 future_ptr future_; | |
1291 | |
1292 basic_future(future_ptr a_future): | |
1293 future_(a_future) | |
1294 { | |
1295 } | |
1296 // Copy construction from a shared_future | |
1297 explicit basic_future(const shared_future<R>&) BOOST_NOEXCEPT; | |
1298 | |
1299 public: | |
1300 typedef future_state::state state; | |
1301 | |
1302 BOOST_THREAD_MOVABLE(basic_future) | |
1303 basic_future(): future_() {} | |
1304 ~basic_future() {} | |
1305 | |
1306 basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT: | |
1307 future_(BOOST_THREAD_RV(other).future_) | |
1308 { | |
1309 BOOST_THREAD_RV(other).future_.reset(); | |
1310 } | |
1311 basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT | |
1312 { | |
1313 future_=BOOST_THREAD_RV(other).future_; | |
1314 BOOST_THREAD_RV(other).future_.reset(); | |
1315 return *this; | |
1316 } | |
1317 void swap(basic_future& that) BOOST_NOEXCEPT | |
1318 { | |
1319 future_.swap(that.future_); | |
1320 } | |
1321 // functions to check state, and wait for ready | |
1322 state get_state() const | |
1323 { | |
1324 if(!future_) | |
1325 { | |
1326 return future_state::uninitialized; | |
1327 } | |
1328 return future_->get_state(); | |
1329 } | |
1330 | |
1331 bool is_ready() const | |
1332 { | |
1333 return get_state()==future_state::ready; | |
1334 } | |
1335 | |
1336 bool has_exception() const | |
1337 { | |
1338 return future_ && future_->has_exception(); | |
1339 } | |
1340 | |
1341 bool has_value() const | |
1342 { | |
1343 return future_ && future_->has_value(); | |
1344 } | |
1345 | |
1346 launch launch_policy(boost::unique_lock<boost::mutex>& lk) const | |
1347 { | |
1348 if ( future_ ) return future_->launch_policy(lk); | |
1349 else return launch(launch::none); | |
1350 } | |
1351 | |
1352 exception_ptr get_exception_ptr() | |
1353 { | |
1354 return future_ | |
1355 ? future_->get_exception_ptr() | |
1356 : exception_ptr(); | |
1357 } | |
1358 | |
1359 bool valid() const BOOST_NOEXCEPT | |
1360 { | |
1361 return future_ != 0; | |
1362 } | |
1363 | |
1364 | |
1365 void wait() const | |
1366 { | |
1367 if(!future_) | |
1368 { | |
1369 boost::throw_exception(future_uninitialized()); | |
1370 } | |
1371 future_->wait(false); | |
1372 } | |
1373 | |
1374 #if defined BOOST_THREAD_USES_DATETIME | |
1375 template<typename Duration> | |
1376 bool timed_wait(Duration const& rel_time) const | |
1377 { | |
1378 return timed_wait_until(boost::get_system_time()+rel_time); | |
1379 } | |
1380 | |
1381 bool timed_wait_until(boost::system_time const& abs_time) const | |
1382 { | |
1383 if(!future_) | |
1384 { | |
1385 boost::throw_exception(future_uninitialized()); | |
1386 } | |
1387 return future_->timed_wait_until(abs_time); | |
1388 } | |
1389 #endif | |
1390 #ifdef BOOST_THREAD_USES_CHRONO | |
1391 template <class Rep, class Period> | |
1392 future_status | |
1393 wait_for(const chrono::duration<Rep, Period>& rel_time) const | |
1394 { | |
1395 return wait_until(chrono::steady_clock::now() + rel_time); | |
1396 | |
1397 } | |
1398 template <class Clock, class Duration> | |
1399 future_status | |
1400 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const | |
1401 { | |
1402 if(!future_) | |
1403 { | |
1404 boost::throw_exception(future_uninitialized()); | |
1405 } | |
1406 return future_->wait_until(abs_time); | |
1407 } | |
1408 #endif | |
1409 | |
1410 }; | |
1411 | |
1412 } // detail | |
1413 BOOST_THREAD_DCL_MOVABLE_BEG(R) detail::basic_future<R> BOOST_THREAD_DCL_MOVABLE_END | |
1414 | |
1415 namespace detail | |
1416 { | |
1417 #if (!defined _MSC_VER || _MSC_VER >= 1400) // _MSC_VER == 1400 on MSVC 2005 | |
1418 template <class Rp, class Fp> | |
1419 BOOST_THREAD_FUTURE<Rp> | |
1420 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f); | |
1421 | |
1422 template <class Rp, class Fp> | |
1423 BOOST_THREAD_FUTURE<Rp> | |
1424 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); | |
1425 #endif // #if (!defined _MSC_VER || _MSC_VER >= 1400) | |
1426 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | |
1427 template<typename F, typename Rp, typename Fp> | |
1428 struct future_deferred_continuation_shared_state; | |
1429 template<typename F, typename Rp, typename Fp> | |
1430 struct future_async_continuation_shared_state; | |
1431 | |
1432 template <class F, class Rp, class Fp> | |
1433 BOOST_THREAD_FUTURE<Rp> | |
1434 make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); | |
1435 | |
1436 template <class F, class Rp, class Fp> | |
1437 BOOST_THREAD_FUTURE<Rp> | |
1438 make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); | |
1439 #endif | |
1440 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP | |
1441 template<typename F, typename Rp> | |
1442 struct future_unwrap_shared_state; | |
1443 template <class F, class Rp> | |
1444 inline BOOST_THREAD_FUTURE<Rp> | |
1445 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f); | |
1446 #endif | |
1447 } | |
1448 | |
1449 template <typename R> | |
1450 class BOOST_THREAD_FUTURE : public detail::basic_future<R> | |
1451 { | |
1452 private: | |
1453 typedef detail::basic_future<R> base_type; | |
1454 typedef typename base_type::future_ptr future_ptr; | |
1455 | |
1456 friend class shared_future<R>; | |
1457 friend class promise<R>; | |
1458 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | |
1459 template <typename, typename, typename> | |
1460 friend struct detail::future_async_continuation_shared_state; | |
1461 template <typename, typename, typename> | |
1462 friend struct detail::future_deferred_continuation_shared_state; | |
1463 | |
1464 template <class F, class Rp, class Fp> | |
1465 friend BOOST_THREAD_FUTURE<Rp> | |
1466 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); | |
1467 | |
1468 template <class F, class Rp, class Fp> | |
1469 friend BOOST_THREAD_FUTURE<Rp> | |
1470 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); | |
1471 #endif | |
1472 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP | |
1473 template<typename F, typename Rp> | |
1474 friend struct detail::future_unwrap_shared_state; | |
1475 template <class F, class Rp> | |
1476 friend BOOST_THREAD_FUTURE<Rp> | |
1477 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f); | |
1478 #endif | |
1479 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
1480 template <class> friend class packaged_task; // todo check if this works in windows | |
1481 #else | |
1482 friend class packaged_task<R>; | |
1483 #endif | |
1484 friend class detail::future_waiter; | |
1485 | |
1486 template <class Rp, class Fp> | |
1487 friend BOOST_THREAD_FUTURE<Rp> | |
1488 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f); | |
1489 | |
1490 template <class Rp, class Fp> | |
1491 friend BOOST_THREAD_FUTURE<Rp> | |
1492 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); | |
1493 | |
1494 | |
1495 typedef typename detail::future_traits<R>::move_dest_type move_dest_type; | |
1496 | |
1497 BOOST_THREAD_FUTURE(future_ptr a_future): | |
1498 base_type(a_future) | |
1499 { | |
1500 } | |
1501 | |
1502 public: | |
1503 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE) | |
1504 typedef future_state::state state; | |
1505 typedef R value_type; // EXTENSION | |
1506 | |
1507 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {} | |
1508 | |
1509 ~BOOST_THREAD_FUTURE() {} | |
1510 | |
1511 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: | |
1512 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) | |
1513 { | |
1514 } | |
1515 inline BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION | |
1516 | |
1517 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT | |
1518 { | |
1519 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))); | |
1520 return *this; | |
1521 } | |
1522 | |
1523 shared_future<R> share() | |
1524 { | |
1525 return shared_future<R>(::boost::move(*this)); | |
1526 } | |
1527 | |
1528 void swap(BOOST_THREAD_FUTURE& other) | |
1529 { | |
1530 static_cast<base_type*>(this)->swap(other); | |
1531 } | |
1532 | |
1533 // todo this function must be private and friendship provided to the internal users. | |
1534 void set_async() | |
1535 { | |
1536 this->future_->set_async(); | |
1537 } | |
1538 // todo this function must be private and friendship provided to the internal users. | |
1539 void set_deferred() | |
1540 { | |
1541 this->future_->set_deferred(); | |
1542 } | |
1543 | |
1544 // retrieving the value | |
1545 move_dest_type get() | |
1546 { | |
1547 if(!this->future_) | |
1548 { | |
1549 boost::throw_exception(future_uninitialized()); | |
1550 } | |
1551 future_ptr fut_=this->future_; | |
1552 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET | |
1553 this->future_.reset(); | |
1554 #endif | |
1555 return fut_->get(); | |
1556 } | |
1557 | |
1558 template <typename R2> | |
1559 typename boost::disable_if< is_void<R2>, move_dest_type>::type | |
1560 get_or(BOOST_THREAD_RV_REF(R2) v) | |
1561 { | |
1562 if(!this->future_) | |
1563 { | |
1564 boost::throw_exception(future_uninitialized()); | |
1565 } | |
1566 this->future_->wait(false); | |
1567 future_ptr fut_=this->future_; | |
1568 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET | |
1569 this->future_.reset(); | |
1570 #endif | |
1571 if (fut_->has_value()) { | |
1572 return fut_->get(); | |
1573 } | |
1574 else { | |
1575 return boost::move(v); | |
1576 } | |
1577 } | |
1578 | |
1579 template <typename R2> | |
1580 typename boost::disable_if< is_void<R2>, move_dest_type>::type | |
1581 get_or(R2 const& v) // EXTENSION | |
1582 { | |
1583 if(!this->future_) | |
1584 { | |
1585 boost::throw_exception(future_uninitialized()); | |
1586 } | |
1587 this->future_->wait(false); | |
1588 future_ptr fut_=this->future_; | |
1589 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET | |
1590 this->future_.reset(); | |
1591 #endif | |
1592 if (fut_->has_value()) { | |
1593 return fut_->get(); | |
1594 } | |
1595 else { | |
1596 return v; | |
1597 } | |
1598 } | |
1599 | |
1600 | |
1601 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | |
1602 | |
1603 // template<typename F> | |
1604 // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; | |
1605 | |
1606 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) | |
1607 // template<typename RF> | |
1608 // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&)); | |
1609 // template<typename RF> | |
1610 // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(BOOST_THREAD_FUTURE&)); | |
1611 //#endif | |
1612 template<typename F> | |
1613 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> | |
1614 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION | |
1615 template<typename F> | |
1616 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> | |
1617 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION | |
1618 | |
1619 template <typename R2> | |
1620 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type | |
1621 fallback_to(BOOST_THREAD_RV_REF(R2) v); // EXTENSION | |
1622 template <typename R2> | |
1623 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type | |
1624 fallback_to(R2 const& v); // EXTENSION | |
1625 | |
1626 #endif | |
1627 | |
1628 //#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP | |
1629 // inline | |
1630 // typename boost::enable_if< | |
1631 // is_future_type<value_type>, | |
1632 // value_type | |
1633 // //BOOST_THREAD_FUTURE<typename is_future_type<value_type>::type> | |
1634 // >::type | |
1635 // unwrap(); | |
1636 //#endif | |
1637 | |
1638 }; | |
1639 | |
1640 BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END | |
1641 | |
1642 template <typename R2> | |
1643 class BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> > : public detail::basic_future<BOOST_THREAD_FUTURE<R2> > | |
1644 { | |
1645 typedef BOOST_THREAD_FUTURE<R2> R; | |
1646 | |
1647 private: | |
1648 typedef detail::basic_future<R> base_type; | |
1649 typedef typename base_type::future_ptr future_ptr; | |
1650 | |
1651 friend class shared_future<R>; | |
1652 friend class promise<R>; | |
1653 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | |
1654 template <typename, typename, typename> | |
1655 friend struct detail::future_async_continuation_shared_state; | |
1656 template <typename, typename, typename> | |
1657 friend struct detail::future_deferred_continuation_shared_state; | |
1658 | |
1659 template <class F, class Rp, class Fp> | |
1660 friend BOOST_THREAD_FUTURE<Rp> | |
1661 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); | |
1662 | |
1663 template <class F, class Rp, class Fp> | |
1664 friend BOOST_THREAD_FUTURE<Rp> | |
1665 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); | |
1666 #endif | |
1667 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP | |
1668 template<typename F, typename Rp> | |
1669 friend struct detail::future_unwrap_shared_state; | |
1670 template <class F, class Rp> | |
1671 friend BOOST_THREAD_FUTURE<Rp> | |
1672 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f); | |
1673 #endif | |
1674 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
1675 template <class> friend class packaged_task; // todo check if this works in windows | |
1676 #else | |
1677 friend class packaged_task<R>; | |
1678 #endif | |
1679 friend class detail::future_waiter; | |
1680 | |
1681 template <class Rp, class Fp> | |
1682 friend BOOST_THREAD_FUTURE<Rp> | |
1683 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f); | |
1684 | |
1685 template <class Rp, class Fp> | |
1686 friend BOOST_THREAD_FUTURE<Rp> | |
1687 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); | |
1688 | |
1689 | |
1690 typedef typename detail::future_traits<R>::move_dest_type move_dest_type; | |
1691 | |
1692 BOOST_THREAD_FUTURE(future_ptr a_future): | |
1693 base_type(a_future) | |
1694 { | |
1695 } | |
1696 | |
1697 public: | |
1698 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE) | |
1699 typedef future_state::state state; | |
1700 typedef R value_type; // EXTENSION | |
1701 | |
1702 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {} | |
1703 | |
1704 ~BOOST_THREAD_FUTURE() {} | |
1705 | |
1706 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: | |
1707 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) | |
1708 { | |
1709 } | |
1710 | |
1711 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT | |
1712 { | |
1713 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))); | |
1714 return *this; | |
1715 } | |
1716 | |
1717 shared_future<R> share() | |
1718 { | |
1719 return shared_future<R>(::boost::move(*this)); | |
1720 } | |
1721 | |
1722 void swap(BOOST_THREAD_FUTURE& other) | |
1723 { | |
1724 static_cast<base_type*>(this)->swap(other); | |
1725 } | |
1726 | |
1727 // todo this function must be private and friendship provided to the internal users. | |
1728 void set_async() | |
1729 { | |
1730 this->future_->set_async(); | |
1731 } | |
1732 // todo this function must be private and friendship provided to the internal users. | |
1733 void set_deferred() | |
1734 { | |
1735 this->future_->set_deferred(); | |
1736 } | |
1737 | |
1738 // retrieving the value | |
1739 move_dest_type get() | |
1740 { | |
1741 if(!this->future_) | |
1742 { | |
1743 boost::throw_exception(future_uninitialized()); | |
1744 } | |
1745 future_ptr fut_=this->future_; | |
1746 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET | |
1747 this->future_.reset(); | |
1748 #endif | |
1749 return fut_->get(); | |
1750 } | |
1751 move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION | |
1752 { | |
1753 if(!this->future_) | |
1754 { | |
1755 boost::throw_exception(future_uninitialized()); | |
1756 } | |
1757 this->future_->wait(false); | |
1758 future_ptr fut_=this->future_; | |
1759 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET | |
1760 this->future_.reset(); | |
1761 #endif | |
1762 if (fut_->has_value()) return fut_->get(); | |
1763 else return boost::move(v); | |
1764 } | |
1765 | |
1766 move_dest_type get_or(R const& v) // EXTENSION | |
1767 { | |
1768 if(!this->future_) | |
1769 { | |
1770 boost::throw_exception(future_uninitialized()); | |
1771 } | |
1772 this->future_->wait(false); | |
1773 future_ptr fut_=this->future_; | |
1774 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET | |
1775 this->future_.reset(); | |
1776 #endif | |
1777 if (fut_->has_value()) return fut_->get(); | |
1778 else return v; | |
1779 } | |
1780 | |
1781 | |
1782 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | |
1783 | |
1784 // template<typename F> | |
1785 // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; | |
1786 | |
1787 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) | |
1788 // template<typename RF> | |
1789 // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&)); | |
1790 // template<typename RF> | |
1791 // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(BOOST_THREAD_FUTURE&)); | |
1792 //#endif | |
1793 template<typename F> | |
1794 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> | |
1795 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION | |
1796 template<typename F> | |
1797 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> | |
1798 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION | |
1799 #endif | |
1800 | |
1801 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP | |
1802 inline | |
1803 BOOST_THREAD_FUTURE<R2> | |
1804 unwrap(); // EXTENSION | |
1805 #endif | |
1806 | |
1807 }; | |
1808 | |
1809 template <typename R> | |
1810 class shared_future : public detail::basic_future<R> | |
1811 { | |
1812 | |
1813 typedef detail::basic_future<R> base_type; | |
1814 typedef typename base_type::future_ptr future_ptr; | |
1815 | |
1816 friend class detail::future_waiter; | |
1817 friend class promise<R>; | |
1818 | |
1819 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | |
1820 template <typename, typename, typename> | |
1821 friend struct detail::future_async_continuation_shared_state; | |
1822 template <typename, typename, typename> | |
1823 friend struct detail::future_deferred_continuation_shared_state; | |
1824 | |
1825 template <class F, class Rp, class Fp> | |
1826 friend BOOST_THREAD_FUTURE<Rp> | |
1827 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); | |
1828 | |
1829 template <class F, class Rp, class Fp> | |
1830 friend BOOST_THREAD_FUTURE<Rp> | |
1831 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); | |
1832 #endif | |
1833 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
1834 template <class> friend class packaged_task;// todo check if this works in windows | |
1835 #else | |
1836 friend class packaged_task<R>; | |
1837 #endif | |
1838 shared_future(future_ptr a_future): | |
1839 base_type(a_future) | |
1840 {} | |
1841 | |
1842 public: | |
1843 BOOST_THREAD_MOVABLE(shared_future) | |
1844 typedef R value_type; // EXTENSION | |
1845 | |
1846 shared_future(shared_future const& other): | |
1847 base_type(other) | |
1848 {} | |
1849 | |
1850 typedef future_state::state state; | |
1851 | |
1852 BOOST_CONSTEXPR shared_future() | |
1853 {} | |
1854 | |
1855 ~shared_future() | |
1856 {} | |
1857 | |
1858 shared_future& operator=(shared_future const& other) | |
1859 { | |
1860 shared_future(other).swap(*this); | |
1861 return *this; | |
1862 } | |
1863 shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT : | |
1864 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) | |
1865 { | |
1866 BOOST_THREAD_RV(other).future_.reset(); | |
1867 } | |
1868 shared_future(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT : | |
1869 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) | |
1870 { | |
1871 } | |
1872 | |
1873 shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT | |
1874 { | |
1875 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))); | |
1876 return *this; | |
1877 } | |
1878 shared_future& operator=(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT | |
1879 { | |
1880 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))); | |
1881 return *this; | |
1882 } | |
1883 | |
1884 void swap(shared_future& other) BOOST_NOEXCEPT | |
1885 { | |
1886 static_cast<base_type*>(this)->swap(other); | |
1887 } | |
1888 | |
1889 // retrieving the value | |
1890 typename detail::shared_state<R>::shared_future_get_result_type get() | |
1891 { | |
1892 if(!this->future_) | |
1893 { | |
1894 boost::throw_exception(future_uninitialized()); | |
1895 } | |
1896 | |
1897 return this->future_->get_sh(); | |
1898 } | |
1899 | |
1900 template <typename R2> | |
1901 typename boost::disable_if< is_void<R2>, typename detail::shared_state<R>::shared_future_get_result_type>::type | |
1902 get_or(BOOST_THREAD_RV_REF(R2) v) // EXTENSION | |
1903 { | |
1904 if(!this->future_) | |
1905 { | |
1906 boost::throw_exception(future_uninitialized()); | |
1907 } | |
1908 future_ptr fut_=this->future_; | |
1909 fut_->wait(); | |
1910 if (fut_->has_value()) return fut_->get_sh(); | |
1911 else return boost::move(v); | |
1912 } | |
1913 | |
1914 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | |
1915 | |
1916 // template<typename F> | |
1917 // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; | |
1918 // template<typename F> | |
1919 // auto then(launch, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; | |
1920 | |
1921 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) | |
1922 // template<typename RF> | |
1923 // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(shared_future&)); | |
1924 // template<typename RF> | |
1925 // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(shared_future&)); | |
1926 //#endif | |
1927 template<typename F> | |
1928 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type> | |
1929 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION | |
1930 template<typename F> | |
1931 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type> | |
1932 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION | |
1933 #endif | |
1934 //#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP | |
1935 // inline | |
1936 // typename boost::enable_if_c< | |
1937 // is_future_type<value_type>::value, | |
1938 // BOOST_THREAD_FUTURE<typename is_future_type<value_type>::type> | |
1939 // >::type | |
1940 // unwrap(); | |
1941 //#endif | |
1942 | |
1943 }; | |
1944 | |
1945 BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END | |
1946 | |
1947 namespace detail | |
1948 { | |
1949 /// Copy construction from a shared_future | |
1950 template <typename R> | |
1951 inline basic_future<R>::basic_future(const shared_future<R>& other) BOOST_NOEXCEPT | |
1952 : future_(other.future_) | |
1953 { | |
1954 } | |
1955 } | |
1956 | |
1957 template <typename R> | |
1958 class promise | |
1959 { | |
1960 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr; | |
1961 | |
1962 future_ptr future_; | |
1963 bool future_obtained; | |
1964 | |
1965 void lazy_init() | |
1966 { | |
1967 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY | |
1968 #include <boost/detail/atomic_undef_macros.hpp> | |
1969 if(!atomic_load(&future_)) | |
1970 { | |
1971 future_ptr blank; | |
1972 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R>)); | |
1973 } | |
1974 #include <boost/detail/atomic_redef_macros.hpp> | |
1975 #endif | |
1976 } | |
1977 | |
1978 public: | |
1979 BOOST_THREAD_MOVABLE_ONLY(promise) | |
1980 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS | |
1981 template <class Allocator> | |
1982 promise(boost::allocator_arg_t, Allocator a) | |
1983 { | |
1984 typedef typename Allocator::template rebind<detail::shared_state<R> >::other A2; | |
1985 A2 a2(a); | |
1986 typedef thread_detail::allocator_destructor<A2> D; | |
1987 | |
1988 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R>(), D(a2, 1) ); | |
1989 future_obtained = false; | |
1990 } | |
1991 #endif | |
1992 promise(): | |
1993 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY | |
1994 future_(), | |
1995 #else | |
1996 future_(new detail::shared_state<R>()), | |
1997 #endif | |
1998 future_obtained(false) | |
1999 {} | |
2000 | |
2001 ~promise() | |
2002 { | |
2003 if(future_) | |
2004 { | |
2005 boost::unique_lock<boost::mutex> lock(future_->mutex); | |
2006 | |
2007 if(!future_->done && !future_->is_constructed) | |
2008 { | |
2009 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock); | |
2010 } | |
2011 } | |
2012 } | |
2013 | |
2014 // Assignment | |
2015 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT : | |
2016 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained) | |
2017 { | |
2018 BOOST_THREAD_RV(rhs).future_.reset(); | |
2019 BOOST_THREAD_RV(rhs).future_obtained=false; | |
2020 } | |
2021 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT | |
2022 { | |
2023 future_=BOOST_THREAD_RV(rhs).future_; | |
2024 future_obtained=BOOST_THREAD_RV(rhs).future_obtained; | |
2025 BOOST_THREAD_RV(rhs).future_.reset(); | |
2026 BOOST_THREAD_RV(rhs).future_obtained=false; | |
2027 return *this; | |
2028 } | |
2029 | |
2030 void swap(promise& other) | |
2031 { | |
2032 future_.swap(other.future_); | |
2033 std::swap(future_obtained,other.future_obtained); | |
2034 } | |
2035 | |
2036 // Result retrieval | |
2037 BOOST_THREAD_FUTURE<R> get_future() | |
2038 { | |
2039 lazy_init(); | |
2040 if (future_.get()==0) | |
2041 { | |
2042 boost::throw_exception(promise_moved()); | |
2043 } | |
2044 if (future_obtained) | |
2045 { | |
2046 boost::throw_exception(future_already_retrieved()); | |
2047 } | |
2048 future_obtained=true; | |
2049 return BOOST_THREAD_FUTURE<R>(future_); | |
2050 } | |
2051 | |
2052 void set_value(typename detail::future_traits<R>::source_reference_type r) | |
2053 { | |
2054 lazy_init(); | |
2055 boost::unique_lock<boost::mutex> lock(future_->mutex); | |
2056 if(future_->done) | |
2057 { | |
2058 boost::throw_exception(promise_already_satisfied()); | |
2059 } | |
2060 future_->mark_finished_with_result_internal(r, lock); | |
2061 } | |
2062 | |
2063 // void set_value(R && r); | |
2064 void set_value(typename detail::future_traits<R>::rvalue_source_type r) | |
2065 { | |
2066 lazy_init(); | |
2067 boost::unique_lock<boost::mutex> lock(future_->mutex); | |
2068 if(future_->done) | |
2069 { | |
2070 boost::throw_exception(promise_already_satisfied()); | |
2071 } | |
2072 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES | |
2073 future_->mark_finished_with_result_internal(boost::forward<R>(r), lock); | |
2074 #else | |
2075 future_->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r), lock); | |
2076 #endif | |
2077 } | |
2078 | |
2079 void set_exception(boost::exception_ptr p) | |
2080 { | |
2081 lazy_init(); | |
2082 boost::unique_lock<boost::mutex> lock(future_->mutex); | |
2083 if(future_->done) | |
2084 { | |
2085 boost::throw_exception(promise_already_satisfied()); | |
2086 } | |
2087 future_->mark_exceptional_finish_internal(p, lock); | |
2088 } | |
2089 template <typename E> | |
2090 void set_exception(E ex) | |
2091 { | |
2092 set_exception(copy_exception(ex)); | |
2093 } | |
2094 // setting the result with deferred notification | |
2095 void set_value_at_thread_exit(const R& r) | |
2096 { | |
2097 if (future_.get()==0) | |
2098 { | |
2099 boost::throw_exception(promise_moved()); | |
2100 } | |
2101 future_->set_value_at_thread_exit(r); | |
2102 } | |
2103 | |
2104 void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r) | |
2105 { | |
2106 if (future_.get()==0) | |
2107 { | |
2108 boost::throw_exception(promise_moved()); | |
2109 } | |
2110 future_->set_value_at_thread_exit(boost::move(r)); | |
2111 } | |
2112 void set_exception_at_thread_exit(exception_ptr e) | |
2113 { | |
2114 if (future_.get()==0) | |
2115 { | |
2116 boost::throw_exception(promise_moved()); | |
2117 } | |
2118 future_->set_exception_at_thread_exit(e); | |
2119 } | |
2120 template <typename E> | |
2121 void set_exception_at_thread_exit(E ex) | |
2122 { | |
2123 set_exception_at_thread_exit(copy_exception(ex)); | |
2124 } | |
2125 | |
2126 template<typename F> | |
2127 void set_wait_callback(F f) | |
2128 { | |
2129 lazy_init(); | |
2130 future_->set_wait_callback(f,this); | |
2131 } | |
2132 | |
2133 }; | |
2134 | |
2135 template <typename R> | |
2136 class promise<R&> | |
2137 { | |
2138 typedef boost::shared_ptr<detail::shared_state<R&> > future_ptr; | |
2139 | |
2140 future_ptr future_; | |
2141 bool future_obtained; | |
2142 | |
2143 void lazy_init() | |
2144 { | |
2145 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY | |
2146 #include <boost/detail/atomic_undef_macros.hpp> | |
2147 if(!atomic_load(&future_)) | |
2148 { | |
2149 future_ptr blank; | |
2150 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R&>)); | |
2151 } | |
2152 #include <boost/detail/atomic_redef_macros.hpp> | |
2153 #endif | |
2154 } | |
2155 | |
2156 public: | |
2157 BOOST_THREAD_MOVABLE_ONLY(promise) | |
2158 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS | |
2159 template <class Allocator> | |
2160 promise(boost::allocator_arg_t, Allocator a) | |
2161 { | |
2162 typedef typename Allocator::template rebind<detail::shared_state<R&> >::other A2; | |
2163 A2 a2(a); | |
2164 typedef thread_detail::allocator_destructor<A2> D; | |
2165 | |
2166 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R&>(), D(a2, 1) ); | |
2167 future_obtained = false; | |
2168 } | |
2169 #endif | |
2170 promise(): | |
2171 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY | |
2172 future_(), | |
2173 #else | |
2174 future_(new detail::shared_state<R&>()), | |
2175 #endif | |
2176 future_obtained(false) | |
2177 {} | |
2178 | |
2179 ~promise() | |
2180 { | |
2181 if(future_) | |
2182 { | |
2183 boost::unique_lock<boost::mutex> lock(future_->mutex); | |
2184 | |
2185 if(!future_->done && !future_->is_constructed) | |
2186 { | |
2187 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock); | |
2188 } | |
2189 } | |
2190 } | |
2191 | |
2192 // Assignment | |
2193 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT : | |
2194 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained) | |
2195 { | |
2196 BOOST_THREAD_RV(rhs).future_.reset(); | |
2197 BOOST_THREAD_RV(rhs).future_obtained=false; | |
2198 } | |
2199 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT | |
2200 { | |
2201 future_=BOOST_THREAD_RV(rhs).future_; | |
2202 future_obtained=BOOST_THREAD_RV(rhs).future_obtained; | |
2203 BOOST_THREAD_RV(rhs).future_.reset(); | |
2204 BOOST_THREAD_RV(rhs).future_obtained=false; | |
2205 return *this; | |
2206 } | |
2207 | |
2208 void swap(promise& other) | |
2209 { | |
2210 future_.swap(other.future_); | |
2211 std::swap(future_obtained,other.future_obtained); | |
2212 } | |
2213 | |
2214 // Result retrieval | |
2215 BOOST_THREAD_FUTURE<R&> get_future() | |
2216 { | |
2217 lazy_init(); | |
2218 if (future_.get()==0) | |
2219 { | |
2220 boost::throw_exception(promise_moved()); | |
2221 } | |
2222 if (future_obtained) | |
2223 { | |
2224 boost::throw_exception(future_already_retrieved()); | |
2225 } | |
2226 future_obtained=true; | |
2227 return BOOST_THREAD_FUTURE<R&>(future_); | |
2228 } | |
2229 | |
2230 void set_value(R& r) | |
2231 { | |
2232 lazy_init(); | |
2233 boost::unique_lock<boost::mutex> lock(future_->mutex); | |
2234 if(future_->done) | |
2235 { | |
2236 boost::throw_exception(promise_already_satisfied()); | |
2237 } | |
2238 future_->mark_finished_with_result_internal(r, lock); | |
2239 } | |
2240 | |
2241 void set_exception(boost::exception_ptr p) | |
2242 { | |
2243 lazy_init(); | |
2244 boost::unique_lock<boost::mutex> lock(future_->mutex); | |
2245 if(future_->done) | |
2246 { | |
2247 boost::throw_exception(promise_already_satisfied()); | |
2248 } | |
2249 future_->mark_exceptional_finish_internal(p, lock); | |
2250 } | |
2251 template <typename E> | |
2252 void set_exception(E ex) | |
2253 { | |
2254 set_exception(copy_exception(ex)); | |
2255 } | |
2256 | |
2257 // setting the result with deferred notification | |
2258 void set_value_at_thread_exit(R& r) | |
2259 { | |
2260 if (future_.get()==0) | |
2261 { | |
2262 boost::throw_exception(promise_moved()); | |
2263 } | |
2264 future_->set_value_at_thread_exit(r); | |
2265 } | |
2266 | |
2267 void set_exception_at_thread_exit(exception_ptr e) | |
2268 { | |
2269 if (future_.get()==0) | |
2270 { | |
2271 boost::throw_exception(promise_moved()); | |
2272 } | |
2273 future_->set_exception_at_thread_exit(e); | |
2274 } | |
2275 template <typename E> | |
2276 void set_exception_at_thread_exit(E ex) | |
2277 { | |
2278 set_exception_at_thread_exit(copy_exception(ex)); | |
2279 } | |
2280 | |
2281 template<typename F> | |
2282 void set_wait_callback(F f) | |
2283 { | |
2284 lazy_init(); | |
2285 future_->set_wait_callback(f,this); | |
2286 } | |
2287 | |
2288 }; | |
2289 template <> | |
2290 class promise<void> | |
2291 { | |
2292 typedef boost::shared_ptr<detail::shared_state<void> > future_ptr; | |
2293 | |
2294 future_ptr future_; | |
2295 bool future_obtained; | |
2296 | |
2297 void lazy_init() | |
2298 { | |
2299 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY | |
2300 if(!atomic_load(&future_)) | |
2301 { | |
2302 future_ptr blank; | |
2303 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<void>)); | |
2304 } | |
2305 #endif | |
2306 } | |
2307 public: | |
2308 BOOST_THREAD_MOVABLE_ONLY(promise) | |
2309 | |
2310 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS | |
2311 template <class Allocator> | |
2312 promise(boost::allocator_arg_t, Allocator a) | |
2313 { | |
2314 typedef typename Allocator::template rebind<detail::shared_state<void> >::other A2; | |
2315 A2 a2(a); | |
2316 typedef thread_detail::allocator_destructor<A2> D; | |
2317 | |
2318 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<void>(), D(a2, 1) ); | |
2319 future_obtained = false; | |
2320 } | |
2321 #endif | |
2322 promise(): | |
2323 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY | |
2324 future_(), | |
2325 #else | |
2326 future_(new detail::shared_state<void>), | |
2327 #endif | |
2328 future_obtained(false) | |
2329 {} | |
2330 | |
2331 ~promise() | |
2332 { | |
2333 if(future_) | |
2334 { | |
2335 boost::unique_lock<boost::mutex> lock(future_->mutex); | |
2336 | |
2337 if(!future_->done && !future_->is_constructed) | |
2338 { | |
2339 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock); | |
2340 } | |
2341 } | |
2342 } | |
2343 | |
2344 // Assignment | |
2345 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT : | |
2346 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained) | |
2347 { | |
2348 // we need to release the future as shared_ptr doesn't implements move semantics | |
2349 BOOST_THREAD_RV(rhs).future_.reset(); | |
2350 BOOST_THREAD_RV(rhs).future_obtained=false; | |
2351 } | |
2352 | |
2353 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT | |
2354 { | |
2355 future_=BOOST_THREAD_RV(rhs).future_; | |
2356 future_obtained=BOOST_THREAD_RV(rhs).future_obtained; | |
2357 BOOST_THREAD_RV(rhs).future_.reset(); | |
2358 BOOST_THREAD_RV(rhs).future_obtained=false; | |
2359 return *this; | |
2360 } | |
2361 | |
2362 void swap(promise& other) | |
2363 { | |
2364 future_.swap(other.future_); | |
2365 std::swap(future_obtained,other.future_obtained); | |
2366 } | |
2367 | |
2368 // Result retrieval | |
2369 BOOST_THREAD_FUTURE<void> get_future() | |
2370 { | |
2371 lazy_init(); | |
2372 | |
2373 if (future_.get()==0) | |
2374 { | |
2375 boost::throw_exception(promise_moved()); | |
2376 } | |
2377 if(future_obtained) | |
2378 { | |
2379 boost::throw_exception(future_already_retrieved()); | |
2380 } | |
2381 future_obtained=true; | |
2382 return BOOST_THREAD_FUTURE<void>(future_); | |
2383 } | |
2384 | |
2385 void set_value() | |
2386 { | |
2387 lazy_init(); | |
2388 boost::unique_lock<boost::mutex> lock(future_->mutex); | |
2389 if(future_->done) | |
2390 { | |
2391 boost::throw_exception(promise_already_satisfied()); | |
2392 } | |
2393 future_->mark_finished_with_result_internal(lock); | |
2394 } | |
2395 | |
2396 void set_exception(boost::exception_ptr p) | |
2397 { | |
2398 lazy_init(); | |
2399 boost::unique_lock<boost::mutex> lock(future_->mutex); | |
2400 if(future_->done) | |
2401 { | |
2402 boost::throw_exception(promise_already_satisfied()); | |
2403 } | |
2404 future_->mark_exceptional_finish_internal(p,lock); | |
2405 } | |
2406 template <typename E> | |
2407 void set_exception(E ex) | |
2408 { | |
2409 set_exception(copy_exception(ex)); | |
2410 } | |
2411 | |
2412 // setting the result with deferred notification | |
2413 void set_value_at_thread_exit() | |
2414 { | |
2415 if (future_.get()==0) | |
2416 { | |
2417 boost::throw_exception(promise_moved()); | |
2418 } | |
2419 future_->set_value_at_thread_exit(); | |
2420 } | |
2421 | |
2422 void set_exception_at_thread_exit(exception_ptr e) | |
2423 { | |
2424 if (future_.get()==0) | |
2425 { | |
2426 boost::throw_exception(promise_moved()); | |
2427 } | |
2428 future_->set_exception_at_thread_exit(e); | |
2429 } | |
2430 template <typename E> | |
2431 void set_exception_at_thread_exit(E ex) | |
2432 { | |
2433 set_exception_at_thread_exit(copy_exception(ex)); | |
2434 } | |
2435 | |
2436 template<typename F> | |
2437 void set_wait_callback(F f) | |
2438 { | |
2439 lazy_init(); | |
2440 future_->set_wait_callback(f,this); | |
2441 } | |
2442 | |
2443 }; | |
2444 | |
2445 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS | |
2446 namespace container | |
2447 { | |
2448 template <class R, class Alloc> | |
2449 struct uses_allocator<promise<R> , Alloc> : true_type | |
2450 { | |
2451 }; | |
2452 } | |
2453 #endif | |
2454 | |
2455 BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END | |
2456 | |
2457 namespace detail | |
2458 { | |
2459 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
2460 template<typename R> | |
2461 struct task_base_shared_state; | |
2462 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2463 template<typename R, typename ...ArgTypes> | |
2464 struct task_base_shared_state<R(ArgTypes...)>: | |
2465 #else | |
2466 template<typename R> | |
2467 struct task_base_shared_state<R()>: | |
2468 #endif | |
2469 #else | |
2470 template<typename R> | |
2471 struct task_base_shared_state: | |
2472 #endif | |
2473 detail::shared_state<R> | |
2474 { | |
2475 bool started; | |
2476 | |
2477 task_base_shared_state(): | |
2478 started(false) | |
2479 {} | |
2480 | |
2481 void reset() | |
2482 { | |
2483 started=false; | |
2484 } | |
2485 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2486 virtual void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0; | |
2487 void run(BOOST_THREAD_RV_REF(ArgTypes) ... args) | |
2488 #else | |
2489 virtual void do_run()=0; | |
2490 void run() | |
2491 #endif | |
2492 { | |
2493 { | |
2494 boost::lock_guard<boost::mutex> lk(this->mutex); | |
2495 if(started) | |
2496 { | |
2497 boost::throw_exception(task_already_started()); | |
2498 } | |
2499 started=true; | |
2500 } | |
2501 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2502 do_run(boost::forward<ArgTypes>(args)...); | |
2503 #else | |
2504 do_run(); | |
2505 #endif | |
2506 } | |
2507 | |
2508 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2509 virtual void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0; | |
2510 void apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) | |
2511 #else | |
2512 virtual void do_apply()=0; | |
2513 void apply() | |
2514 #endif | |
2515 { | |
2516 { | |
2517 boost::lock_guard<boost::mutex> lk(this->mutex); | |
2518 if(started) | |
2519 { | |
2520 boost::throw_exception(task_already_started()); | |
2521 } | |
2522 started=true; | |
2523 } | |
2524 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2525 do_apply(boost::forward<ArgTypes>(args)...); | |
2526 #else | |
2527 do_apply(); | |
2528 #endif | |
2529 } | |
2530 | |
2531 void owner_destroyed() | |
2532 { | |
2533 boost::unique_lock<boost::mutex> lk(this->mutex); | |
2534 if(!started) | |
2535 { | |
2536 started=true; | |
2537 this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk); | |
2538 } | |
2539 } | |
2540 | |
2541 }; | |
2542 | |
2543 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
2544 template<typename F, typename R> | |
2545 struct task_shared_state; | |
2546 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2547 template<typename F, typename R, typename ...ArgTypes> | |
2548 struct task_shared_state<F, R(ArgTypes...)>: | |
2549 task_base_shared_state<R(ArgTypes...)> | |
2550 #else | |
2551 template<typename F, typename R> | |
2552 struct task_shared_state<F, R()>: | |
2553 task_base_shared_state<R()> | |
2554 #endif | |
2555 #else | |
2556 template<typename F, typename R> | |
2557 struct task_shared_state: | |
2558 task_base_shared_state<R> | |
2559 #endif | |
2560 { | |
2561 private: | |
2562 task_shared_state(task_shared_state&); | |
2563 public: | |
2564 F f; | |
2565 task_shared_state(F const& f_): | |
2566 f(f_) | |
2567 {} | |
2568 task_shared_state(BOOST_THREAD_RV_REF(F) f_): | |
2569 f(boost::move(f_)) | |
2570 {} | |
2571 | |
2572 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2573 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) | |
2574 { | |
2575 try | |
2576 { | |
2577 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...)); | |
2578 } | |
2579 #else | |
2580 void do_apply() | |
2581 { | |
2582 try | |
2583 { | |
2584 this->set_value_at_thread_exit(f()); | |
2585 } | |
2586 #endif | |
2587 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2588 catch(thread_interrupted& ) | |
2589 { | |
2590 this->set_interrupted_at_thread_exit(); | |
2591 } | |
2592 #endif | |
2593 catch(...) | |
2594 { | |
2595 this->set_exception_at_thread_exit(current_exception()); | |
2596 } | |
2597 } | |
2598 | |
2599 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2600 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) | |
2601 { | |
2602 try | |
2603 { | |
2604 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...)); | |
2605 } | |
2606 #else | |
2607 void do_run() | |
2608 { | |
2609 try | |
2610 { | |
2611 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES | |
2612 R res((f())); | |
2613 this->mark_finished_with_result(boost::move(res)); | |
2614 #else | |
2615 this->mark_finished_with_result(f()); | |
2616 #endif | |
2617 } | |
2618 #endif | |
2619 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2620 catch(thread_interrupted& ) | |
2621 { | |
2622 this->mark_interrupted_finish(); | |
2623 } | |
2624 #endif | |
2625 catch(...) | |
2626 { | |
2627 this->mark_exceptional_finish(); | |
2628 } | |
2629 } | |
2630 }; | |
2631 | |
2632 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
2633 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2634 template<typename F, typename R, typename ...ArgTypes> | |
2635 struct task_shared_state<F, R&(ArgTypes...)>: | |
2636 task_base_shared_state<R&(ArgTypes...)> | |
2637 #else | |
2638 template<typename F, typename R> | |
2639 struct task_shared_state<F, R&()>: | |
2640 task_base_shared_state<R&()> | |
2641 #endif | |
2642 #else | |
2643 template<typename F, typename R> | |
2644 struct task_shared_state<F,R&>: | |
2645 task_base_shared_state<R&> | |
2646 #endif | |
2647 { | |
2648 private: | |
2649 task_shared_state(task_shared_state&); | |
2650 public: | |
2651 F f; | |
2652 task_shared_state(F const& f_): | |
2653 f(f_) | |
2654 {} | |
2655 task_shared_state(BOOST_THREAD_RV_REF(F) f_): | |
2656 f(boost::move(f_)) | |
2657 {} | |
2658 | |
2659 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2660 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) | |
2661 { | |
2662 try | |
2663 { | |
2664 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...)); | |
2665 } | |
2666 #else | |
2667 void do_apply() | |
2668 { | |
2669 try | |
2670 { | |
2671 this->set_value_at_thread_exit(f()); | |
2672 } | |
2673 #endif | |
2674 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2675 catch(thread_interrupted& ) | |
2676 { | |
2677 this->set_interrupted_at_thread_exit(); | |
2678 } | |
2679 #endif | |
2680 catch(...) | |
2681 { | |
2682 this->set_exception_at_thread_exit(current_exception()); | |
2683 } | |
2684 } | |
2685 | |
2686 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2687 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) | |
2688 { | |
2689 try | |
2690 { | |
2691 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...)); | |
2692 } | |
2693 #else | |
2694 void do_run() | |
2695 { | |
2696 try | |
2697 { | |
2698 R& res((f())); | |
2699 this->mark_finished_with_result(res); | |
2700 } | |
2701 #endif | |
2702 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2703 catch(thread_interrupted& ) | |
2704 { | |
2705 this->mark_interrupted_finish(); | |
2706 } | |
2707 #endif | |
2708 catch(...) | |
2709 { | |
2710 this->mark_exceptional_finish(); | |
2711 } | |
2712 } | |
2713 }; | |
2714 | |
2715 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) | |
2716 | |
2717 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
2718 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2719 template<typename R, typename ...ArgTypes> | |
2720 struct task_shared_state<R (*)(ArgTypes...), R(ArgTypes...)>: | |
2721 task_base_shared_state<R(ArgTypes...)> | |
2722 #else | |
2723 template<typename R> | |
2724 struct task_shared_state<R (*)(), R()>: | |
2725 task_base_shared_state<R()> | |
2726 #endif | |
2727 #else | |
2728 template<typename R> | |
2729 struct task_shared_state<R (*)(), R> : | |
2730 task_base_shared_state<R> | |
2731 #endif | |
2732 { | |
2733 private: | |
2734 task_shared_state(task_shared_state&); | |
2735 public: | |
2736 R (*f)(); | |
2737 task_shared_state(R (*f_)()): | |
2738 f(f_) | |
2739 {} | |
2740 | |
2741 | |
2742 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2743 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) | |
2744 { | |
2745 try | |
2746 { | |
2747 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...)); | |
2748 } | |
2749 #else | |
2750 void do_apply() | |
2751 { | |
2752 try | |
2753 { | |
2754 R r((f())); | |
2755 this->set_value_at_thread_exit(boost::move(r)); | |
2756 } | |
2757 #endif | |
2758 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2759 catch(thread_interrupted& ) | |
2760 { | |
2761 this->set_interrupted_at_thread_exit(); | |
2762 } | |
2763 #endif | |
2764 catch(...) | |
2765 { | |
2766 this->set_exception_at_thread_exit(current_exception()); | |
2767 } | |
2768 } | |
2769 | |
2770 | |
2771 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2772 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) | |
2773 { | |
2774 try | |
2775 { | |
2776 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...)); | |
2777 } | |
2778 #else | |
2779 void do_run() | |
2780 { | |
2781 try | |
2782 { | |
2783 R res((f())); | |
2784 this->mark_finished_with_result(boost::move(res)); | |
2785 } | |
2786 #endif | |
2787 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2788 catch(thread_interrupted& ) | |
2789 { | |
2790 this->mark_interrupted_finish(); | |
2791 } | |
2792 #endif | |
2793 catch(...) | |
2794 { | |
2795 this->mark_exceptional_finish(); | |
2796 } | |
2797 } | |
2798 }; | |
2799 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
2800 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2801 template<typename R, typename ...ArgTypes> | |
2802 struct task_shared_state<R& (*)(ArgTypes...), R&(ArgTypes...)>: | |
2803 task_base_shared_state<R&(ArgTypes...)> | |
2804 #else | |
2805 template<typename R> | |
2806 struct task_shared_state<R& (*)(), R&()>: | |
2807 task_base_shared_state<R&()> | |
2808 #endif | |
2809 #else | |
2810 template<typename R> | |
2811 struct task_shared_state<R& (*)(), R&> : | |
2812 task_base_shared_state<R&> | |
2813 #endif | |
2814 { | |
2815 private: | |
2816 task_shared_state(task_shared_state&); | |
2817 public: | |
2818 R& (*f)(); | |
2819 task_shared_state(R& (*f_)()): | |
2820 f(f_) | |
2821 {} | |
2822 | |
2823 | |
2824 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2825 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) | |
2826 { | |
2827 try | |
2828 { | |
2829 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...)); | |
2830 } | |
2831 #else | |
2832 void do_apply() | |
2833 { | |
2834 try | |
2835 { | |
2836 this->set_value_at_thread_exit(f()); | |
2837 } | |
2838 #endif | |
2839 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2840 catch(thread_interrupted& ) | |
2841 { | |
2842 this->set_interrupted_at_thread_exit(); | |
2843 } | |
2844 #endif | |
2845 catch(...) | |
2846 { | |
2847 this->set_exception_at_thread_exit(current_exception()); | |
2848 } | |
2849 } | |
2850 | |
2851 | |
2852 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2853 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) | |
2854 { | |
2855 try | |
2856 { | |
2857 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...)); | |
2858 } | |
2859 #else | |
2860 void do_run() | |
2861 { | |
2862 try | |
2863 { | |
2864 this->mark_finished_with_result(f()); | |
2865 } | |
2866 #endif | |
2867 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2868 catch(thread_interrupted& ) | |
2869 { | |
2870 this->mark_interrupted_finish(); | |
2871 } | |
2872 #endif | |
2873 catch(...) | |
2874 { | |
2875 this->mark_exceptional_finish(); | |
2876 } | |
2877 } | |
2878 }; | |
2879 #endif | |
2880 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
2881 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2882 template<typename F, typename ...ArgTypes> | |
2883 struct task_shared_state<F, void(ArgTypes...)>: | |
2884 task_base_shared_state<void(ArgTypes...)> | |
2885 #else | |
2886 template<typename F> | |
2887 struct task_shared_state<F, void()>: | |
2888 task_base_shared_state<void()> | |
2889 #endif | |
2890 #else | |
2891 template<typename F> | |
2892 struct task_shared_state<F,void>: | |
2893 task_base_shared_state<void> | |
2894 #endif | |
2895 { | |
2896 private: | |
2897 task_shared_state(task_shared_state&); | |
2898 public: | |
2899 F f; | |
2900 task_shared_state(F const& f_): | |
2901 f(f_) | |
2902 {} | |
2903 task_shared_state(BOOST_THREAD_RV_REF(F) f_): | |
2904 f(boost::move(f_)) | |
2905 {} | |
2906 | |
2907 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2908 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) | |
2909 { | |
2910 try | |
2911 { | |
2912 f(boost::forward<ArgTypes>(args)...); | |
2913 #else | |
2914 void do_apply() | |
2915 { | |
2916 try | |
2917 { | |
2918 f(); | |
2919 #endif | |
2920 this->set_value_at_thread_exit(); | |
2921 } | |
2922 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2923 catch(thread_interrupted& ) | |
2924 { | |
2925 this->set_interrupted_at_thread_exit(); | |
2926 } | |
2927 #endif | |
2928 catch(...) | |
2929 { | |
2930 this->set_exception_at_thread_exit(current_exception()); | |
2931 } | |
2932 } | |
2933 | |
2934 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2935 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) | |
2936 { | |
2937 try | |
2938 { | |
2939 f(boost::forward<ArgTypes>(args)...); | |
2940 #else | |
2941 void do_run() | |
2942 { | |
2943 try | |
2944 { | |
2945 f(); | |
2946 #endif | |
2947 this->mark_finished_with_result(); | |
2948 } | |
2949 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
2950 catch(thread_interrupted& ) | |
2951 { | |
2952 this->mark_interrupted_finish(); | |
2953 } | |
2954 #endif | |
2955 catch(...) | |
2956 { | |
2957 this->mark_exceptional_finish(); | |
2958 } | |
2959 } | |
2960 }; | |
2961 | |
2962 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
2963 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2964 template<typename ...ArgTypes> | |
2965 struct task_shared_state<void (*)(ArgTypes...), void(ArgTypes...)>: | |
2966 task_base_shared_state<void(ArgTypes...)> | |
2967 #else | |
2968 template<> | |
2969 struct task_shared_state<void (*)(), void()>: | |
2970 task_base_shared_state<void()> | |
2971 #endif | |
2972 #else | |
2973 template<> | |
2974 struct task_shared_state<void (*)(),void>: | |
2975 task_base_shared_state<void> | |
2976 #endif | |
2977 { | |
2978 private: | |
2979 task_shared_state(task_shared_state&); | |
2980 public: | |
2981 void (*f)(); | |
2982 task_shared_state(void (*f_)()): | |
2983 f(f_) | |
2984 {} | |
2985 | |
2986 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
2987 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) | |
2988 { | |
2989 try | |
2990 { | |
2991 f(boost::forward<ArgTypes>(args)...); | |
2992 #else | |
2993 void do_apply() | |
2994 { | |
2995 try | |
2996 { | |
2997 f(); | |
2998 #endif | |
2999 this->set_value_at_thread_exit(); | |
3000 } | |
3001 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
3002 catch(thread_interrupted& ) | |
3003 { | |
3004 this->set_interrupted_at_thread_exit(); | |
3005 } | |
3006 #endif | |
3007 catch(...) | |
3008 { | |
3009 this->set_exception_at_thread_exit(current_exception()); | |
3010 } | |
3011 } | |
3012 | |
3013 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3014 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) | |
3015 { | |
3016 try | |
3017 { | |
3018 f(boost::forward<ArgTypes>(args)...); | |
3019 #else | |
3020 void do_run() | |
3021 { | |
3022 try | |
3023 { | |
3024 f(); | |
3025 #endif | |
3026 this->mark_finished_with_result(); | |
3027 } | |
3028 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
3029 catch(thread_interrupted& ) | |
3030 { | |
3031 this->mark_interrupted_finish(); | |
3032 } | |
3033 #endif | |
3034 catch(...) | |
3035 { | |
3036 this->mark_exceptional_finish(); | |
3037 } | |
3038 } | |
3039 }; | |
3040 } | |
3041 | |
3042 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
3043 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3044 template<typename R, typename ...ArgTypes> | |
3045 class packaged_task<R(ArgTypes...)> | |
3046 { | |
3047 typedef boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task_ptr; | |
3048 boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task; | |
3049 #else | |
3050 template<typename R> | |
3051 class packaged_task<R()> | |
3052 { | |
3053 typedef boost::shared_ptr<detail::task_base_shared_state<R()> > task_ptr; | |
3054 boost::shared_ptr<detail::task_base_shared_state<R()> > task; | |
3055 #endif | |
3056 #else | |
3057 template<typename R> | |
3058 class packaged_task | |
3059 { | |
3060 typedef boost::shared_ptr<detail::task_base_shared_state<R> > task_ptr; | |
3061 boost::shared_ptr<detail::task_base_shared_state<R> > task; | |
3062 #endif | |
3063 bool future_obtained; | |
3064 struct dummy; | |
3065 | |
3066 public: | |
3067 typedef R result_type; | |
3068 BOOST_THREAD_MOVABLE_ONLY(packaged_task) | |
3069 | |
3070 packaged_task(): | |
3071 future_obtained(false) | |
3072 {} | |
3073 | |
3074 // construction and destruction | |
3075 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) | |
3076 | |
3077 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
3078 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3079 explicit packaged_task(R(*f)(), BOOST_THREAD_FWD_REF(ArgTypes)... args) | |
3080 { | |
3081 typedef R(*FR)(BOOST_THREAD_FWD_REF(ArgTypes)...); | |
3082 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type; | |
3083 task= task_ptr(new task_shared_state_type(f, boost::forward<ArgTypes>(args)...)); | |
3084 future_obtained=false; | |
3085 } | |
3086 #else | |
3087 explicit packaged_task(R(*f)()) | |
3088 { | |
3089 typedef R(*FR)(); | |
3090 typedef detail::task_shared_state<FR,R()> task_shared_state_type; | |
3091 task= task_ptr(new task_shared_state_type(f)); | |
3092 future_obtained=false; | |
3093 } | |
3094 #endif | |
3095 #else | |
3096 explicit packaged_task(R(*f)()) | |
3097 { | |
3098 typedef R(*FR)(); | |
3099 typedef detail::task_shared_state<FR,R> task_shared_state_type; | |
3100 task= task_ptr(new task_shared_state_type(f)); | |
3101 future_obtained=false; | |
3102 } | |
3103 #endif | |
3104 #endif | |
3105 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
3106 template <class F> | |
3107 explicit packaged_task(BOOST_THREAD_FWD_REF(F) f | |
3108 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0 | |
3109 ) | |
3110 { | |
3111 typedef typename remove_cv<typename remove_reference<F>::type>::type FR; | |
3112 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
3113 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3114 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type; | |
3115 #else | |
3116 typedef detail::task_shared_state<FR,R()> task_shared_state_type; | |
3117 #endif | |
3118 #else | |
3119 typedef detail::task_shared_state<FR,R> task_shared_state_type; | |
3120 #endif | |
3121 task = task_ptr(new task_shared_state_type(boost::forward<F>(f))); | |
3122 future_obtained = false; | |
3123 | |
3124 } | |
3125 | |
3126 #else | |
3127 template <class F> | |
3128 explicit packaged_task(F const& f | |
3129 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0 | |
3130 ) | |
3131 { | |
3132 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
3133 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3134 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type; | |
3135 #else | |
3136 typedef detail::task_shared_state<F,R()> task_shared_state_type; | |
3137 #endif | |
3138 #else | |
3139 typedef detail::task_shared_state<F,R> task_shared_state_type; | |
3140 #endif | |
3141 task = task_ptr(new task_shared_state_type(f)); | |
3142 future_obtained=false; | |
3143 } | |
3144 template <class F> | |
3145 explicit packaged_task(BOOST_THREAD_RV_REF(F) f) | |
3146 { | |
3147 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
3148 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3149 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type; | |
3150 task = task_ptr(new task_shared_state_type(boost::forward<F>(f))); | |
3151 #else | |
3152 typedef detail::task_shared_state<F,R()> task_shared_state_type; | |
3153 task = task_ptr(new task_shared_state_type(boost::move(f))); // TODO forward | |
3154 #endif | |
3155 #else | |
3156 typedef detail::task_shared_state<F,R> task_shared_state_type; | |
3157 task = task_ptr(new task_shared_state_type(boost::forward<F>(f))); | |
3158 #endif | |
3159 future_obtained=false; | |
3160 | |
3161 } | |
3162 #endif | |
3163 | |
3164 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS | |
3165 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) | |
3166 template <class Allocator> | |
3167 packaged_task(boost::allocator_arg_t, Allocator a, R(*f)()) | |
3168 { | |
3169 typedef R(*FR)(); | |
3170 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
3171 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3172 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type; | |
3173 #else | |
3174 typedef detail::task_shared_state<FR,R()> task_shared_state_type; | |
3175 #endif | |
3176 #else | |
3177 typedef detail::task_shared_state<FR,R> task_shared_state_type; | |
3178 #endif | |
3179 typedef typename Allocator::template rebind<task_shared_state_type>::other A2; | |
3180 A2 a2(a); | |
3181 typedef thread_detail::allocator_destructor<A2> D; | |
3182 | |
3183 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) ); | |
3184 future_obtained = false; | |
3185 } | |
3186 #endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR | |
3187 | |
3188 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES | |
3189 template <class F, class Allocator> | |
3190 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_REF(F) f) | |
3191 { | |
3192 typedef typename remove_cv<typename remove_reference<F>::type>::type FR; | |
3193 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
3194 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3195 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type; | |
3196 #else | |
3197 typedef detail::task_shared_state<FR,R()> task_shared_state_type; | |
3198 #endif | |
3199 #else | |
3200 typedef detail::task_shared_state<FR,R> task_shared_state_type; | |
3201 #endif | |
3202 typedef typename Allocator::template rebind<task_shared_state_type>::other A2; | |
3203 A2 a2(a); | |
3204 typedef thread_detail::allocator_destructor<A2> D; | |
3205 | |
3206 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) ); | |
3207 future_obtained = false; | |
3208 } | |
3209 #else // ! defined BOOST_NO_CXX11_RVALUE_REFERENCES | |
3210 template <class F, class Allocator> | |
3211 packaged_task(boost::allocator_arg_t, Allocator a, const F& f) | |
3212 { | |
3213 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
3214 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3215 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type; | |
3216 #else | |
3217 typedef detail::task_shared_state<F,R()> task_shared_state_type; | |
3218 #endif | |
3219 #else | |
3220 typedef detail::task_shared_state<F,R> task_shared_state_type; | |
3221 #endif | |
3222 typedef typename Allocator::template rebind<task_shared_state_type>::other A2; | |
3223 A2 a2(a); | |
3224 typedef thread_detail::allocator_destructor<A2> D; | |
3225 | |
3226 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) ); | |
3227 future_obtained = false; | |
3228 } | |
3229 template <class F, class Allocator> | |
3230 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f) | |
3231 { | |
3232 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
3233 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3234 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type; | |
3235 #else | |
3236 typedef detail::task_shared_state<F,R()> task_shared_state_type; | |
3237 #endif | |
3238 #else | |
3239 typedef detail::task_shared_state<F,R> task_shared_state_type; | |
3240 #endif | |
3241 typedef typename Allocator::template rebind<task_shared_state_type>::other A2; | |
3242 A2 a2(a); | |
3243 typedef thread_detail::allocator_destructor<A2> D; | |
3244 | |
3245 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3246 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) ); | |
3247 #else | |
3248 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) ); // TODO forward | |
3249 #endif | |
3250 future_obtained = false; | |
3251 } | |
3252 | |
3253 #endif //BOOST_NO_CXX11_RVALUE_REFERENCES | |
3254 #endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS | |
3255 | |
3256 ~packaged_task() | |
3257 { | |
3258 if(task) | |
3259 { | |
3260 task->owner_destroyed(); | |
3261 } | |
3262 } | |
3263 | |
3264 // assignment | |
3265 packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT : | |
3266 future_obtained(BOOST_THREAD_RV(other).future_obtained) | |
3267 { | |
3268 task.swap(BOOST_THREAD_RV(other).task); | |
3269 BOOST_THREAD_RV(other).future_obtained=false; | |
3270 } | |
3271 packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT | |
3272 { | |
3273 | |
3274 // todo use forward | |
3275 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES | |
3276 packaged_task temp(boost::move(other)); | |
3277 #else | |
3278 packaged_task temp(static_cast<BOOST_THREAD_RV_REF(packaged_task)>(other)); | |
3279 #endif | |
3280 swap(temp); | |
3281 return *this; | |
3282 } | |
3283 | |
3284 void reset() | |
3285 { | |
3286 if (!valid()) | |
3287 throw future_error(system::make_error_code(future_errc::no_state)); | |
3288 task->reset(); | |
3289 future_obtained=false; | |
3290 } | |
3291 | |
3292 void swap(packaged_task& other) BOOST_NOEXCEPT | |
3293 { | |
3294 task.swap(other.task); | |
3295 std::swap(future_obtained,other.future_obtained); | |
3296 } | |
3297 bool valid() const BOOST_NOEXCEPT | |
3298 { | |
3299 return task.get()!=0; | |
3300 } | |
3301 | |
3302 // result retrieval | |
3303 BOOST_THREAD_FUTURE<R> get_future() | |
3304 { | |
3305 if(!task) | |
3306 { | |
3307 boost::throw_exception(task_moved()); | |
3308 } | |
3309 else if(!future_obtained) | |
3310 { | |
3311 future_obtained=true; | |
3312 return BOOST_THREAD_FUTURE<R>(task); | |
3313 } | |
3314 else | |
3315 { | |
3316 boost::throw_exception(future_already_retrieved()); | |
3317 } | |
3318 //return BOOST_THREAD_FUTURE<R>(); | |
3319 } | |
3320 | |
3321 // execution | |
3322 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3323 void operator()(BOOST_THREAD_RV_REF(ArgTypes)... args) | |
3324 { | |
3325 if(!task) | |
3326 { | |
3327 boost::throw_exception(task_moved()); | |
3328 } | |
3329 task->run(boost::forward<ArgTypes>(args)...); | |
3330 } | |
3331 void make_ready_at_thread_exit(ArgTypes... args) | |
3332 { | |
3333 if(!task) | |
3334 { | |
3335 boost::throw_exception(task_moved()); | |
3336 } | |
3337 if (task->has_value()) | |
3338 { | |
3339 boost::throw_exception(promise_already_satisfied()); | |
3340 } | |
3341 task->apply(boost::forward<ArgTypes>(args)...); | |
3342 } | |
3343 #else | |
3344 void operator()() | |
3345 { | |
3346 if(!task) | |
3347 { | |
3348 boost::throw_exception(task_moved()); | |
3349 } | |
3350 task->run(); | |
3351 } | |
3352 void make_ready_at_thread_exit() | |
3353 { | |
3354 if(!task) | |
3355 { | |
3356 boost::throw_exception(task_moved()); | |
3357 } | |
3358 if (task->has_value()) | |
3359 boost::throw_exception(promise_already_satisfied()); | |
3360 task->apply(); | |
3361 } | |
3362 #endif | |
3363 template<typename F> | |
3364 void set_wait_callback(F f) | |
3365 { | |
3366 task->set_wait_callback(f,this); | |
3367 } | |
3368 }; | |
3369 | |
3370 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS | |
3371 namespace container | |
3372 { | |
3373 template <class R, class Alloc> | |
3374 struct uses_allocator<packaged_task<R>, Alloc> | |
3375 : public true_type {}; | |
3376 } | |
3377 #endif | |
3378 | |
3379 BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END | |
3380 | |
3381 namespace detail | |
3382 { | |
3383 //////////////////////////////// | |
3384 // make_future_deferred_shared_state | |
3385 //////////////////////////////// | |
3386 template <class Rp, class Fp> | |
3387 BOOST_THREAD_FUTURE<Rp> | |
3388 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) | |
3389 { | |
3390 shared_ptr<future_deferred_shared_state<Rp, Fp> > | |
3391 h(new future_deferred_shared_state<Rp, Fp>(boost::forward<Fp>(f))); | |
3392 return BOOST_THREAD_FUTURE<Rp>(h); | |
3393 } | |
3394 | |
3395 //////////////////////////////// | |
3396 // make_future_async_shared_state | |
3397 //////////////////////////////// | |
3398 template <class Rp, class Fp> | |
3399 BOOST_THREAD_FUTURE<Rp> | |
3400 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) | |
3401 { | |
3402 shared_ptr<future_async_shared_state<Rp, Fp> > | |
3403 h(new future_async_shared_state<Rp, Fp>(boost::forward<Fp>(f))); | |
3404 return BOOST_THREAD_FUTURE<Rp>(h); | |
3405 } | |
3406 | |
3407 } | |
3408 | |
3409 //////////////////////////////// | |
3410 // template <class F, class... ArgTypes> | |
3411 // future<R> async(launch policy, F&&, ArgTypes&&...); | |
3412 //////////////////////////////// | |
3413 | |
3414 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR | |
3415 | |
3416 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
3417 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3418 template <class R, class... ArgTypes> | |
3419 BOOST_THREAD_FUTURE<R> | |
3420 async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) | |
3421 { | |
3422 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...); | |
3423 typedef detail::async_func<typename decay<F>::type, typename decay<ArgTypes>::type...> BF; | |
3424 typedef typename BF::result_type Rp; | |
3425 #else | |
3426 template <class R> | |
3427 BOOST_THREAD_FUTURE<R> | |
3428 async(launch policy, R(*f)()) | |
3429 { | |
3430 typedef packaged_task<R()> packaged_task_type; | |
3431 #endif | |
3432 #else | |
3433 template <class R> | |
3434 BOOST_THREAD_FUTURE<R> | |
3435 async(launch policy, R(*f)()) | |
3436 { | |
3437 typedef packaged_task<R> packaged_task_type; | |
3438 #endif | |
3439 if (int(policy) & int(launch::async)) | |
3440 { | |
3441 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3442 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>( | |
3443 BF( | |
3444 thread_detail::decay_copy(boost::forward<F>(f)) | |
3445 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... | |
3446 ) | |
3447 )); | |
3448 #else | |
3449 packaged_task_type pt( f ); | |
3450 | |
3451 BOOST_THREAD_FUTURE<R> ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future()); | |
3452 ret.set_async(); | |
3453 boost::thread( boost::move(pt) ).detach(); | |
3454 return ::boost::move(ret); | |
3455 #endif | |
3456 } | |
3457 else if (int(policy) & int(launch::deferred)) | |
3458 { | |
3459 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3460 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>( | |
3461 BF( | |
3462 thread_detail::decay_copy(boost::forward<F>(f)) | |
3463 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... | |
3464 ) | |
3465 )); | |
3466 #else | |
3467 std::terminate(); | |
3468 BOOST_THREAD_FUTURE<R> ret; | |
3469 return ::boost::move(ret); | |
3470 | |
3471 #endif | |
3472 } else { | |
3473 std::terminate(); | |
3474 BOOST_THREAD_FUTURE<R> ret; | |
3475 return ::boost::move(ret); | |
3476 } | |
3477 } | |
3478 | |
3479 #endif | |
3480 | |
3481 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK | |
3482 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3483 | |
3484 template <class F, class ...ArgTypes> | |
3485 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type( | |
3486 typename decay<ArgTypes>::type... | |
3487 )>::type> | |
3488 async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) | |
3489 { | |
3490 | |
3491 typedef typename boost::result_of<typename decay<F>::type( | |
3492 typename decay<ArgTypes>::type... | |
3493 )>::type R; | |
3494 | |
3495 typedef detail::async_func<typename decay<F>::type, typename decay<ArgTypes>::type...> BF; | |
3496 typedef typename BF::result_type Rp; | |
3497 | |
3498 #else | |
3499 template <class F> | |
3500 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type> | |
3501 async(launch policy, BOOST_THREAD_FWD_REF(F) f) | |
3502 { | |
3503 typedef typename boost::result_of<typename decay<F>::type()>::type R; | |
3504 typedef packaged_task<R()> packaged_task_type; | |
3505 | |
3506 #endif | |
3507 #else | |
3508 template <class F> | |
3509 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type> | |
3510 async(launch policy, BOOST_THREAD_FWD_REF(F) f) | |
3511 { | |
3512 typedef typename boost::result_of<typename decay<F>::type()>::type R; | |
3513 typedef packaged_task<R> packaged_task_type; | |
3514 | |
3515 #endif | |
3516 | |
3517 if (int(policy) & int(launch::async)) | |
3518 { | |
3519 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3520 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>( | |
3521 BF( | |
3522 thread_detail::decay_copy(boost::forward<F>(f)) | |
3523 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... | |
3524 ) | |
3525 )); | |
3526 #else | |
3527 packaged_task_type pt( boost::forward<F>(f) ); | |
3528 | |
3529 BOOST_THREAD_FUTURE<R> ret = pt.get_future(); | |
3530 ret.set_async(); | |
3531 boost::thread( boost::move(pt) ).detach(); | |
3532 return ::boost::move(ret); | |
3533 #endif | |
3534 } | |
3535 else if (int(policy) & int(launch::deferred)) | |
3536 { | |
3537 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3538 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>( | |
3539 BF( | |
3540 thread_detail::decay_copy(boost::forward<F>(f)) | |
3541 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... | |
3542 ) | |
3543 )); | |
3544 #else | |
3545 std::terminate(); | |
3546 BOOST_THREAD_FUTURE<R> ret; | |
3547 return ::boost::move(ret); | |
3548 // return boost::detail::make_future_deferred_shared_state<Rp>( | |
3549 // BF( | |
3550 // thread_detail::decay_copy(boost::forward<F>(f)) | |
3551 // ) | |
3552 // ); | |
3553 #endif | |
3554 | |
3555 } else { | |
3556 std::terminate(); | |
3557 BOOST_THREAD_FUTURE<R> ret; | |
3558 return ::boost::move(ret); | |
3559 } | |
3560 } | |
3561 | |
3562 //////////////////////////////// | |
3563 // template <class F, class... ArgTypes> | |
3564 // future<R> async(F&&, ArgTypes&&...); | |
3565 //////////////////////////////// | |
3566 | |
3567 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR | |
3568 | |
3569 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3570 template <class R, class... ArgTypes> | |
3571 BOOST_THREAD_FUTURE<R> | |
3572 async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) | |
3573 { | |
3574 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward<ArgTypes>(args)...)); | |
3575 } | |
3576 #else | |
3577 template <class R> | |
3578 BOOST_THREAD_FUTURE<R> | |
3579 async(R(*f)()) | |
3580 { | |
3581 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f)); | |
3582 } | |
3583 #endif | |
3584 #endif | |
3585 | |
3586 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
3587 template <class F, class ...ArgTypes> | |
3588 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type( | |
3589 typename decay<ArgTypes>::type... | |
3590 )>::type> | |
3591 async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) | |
3592 { | |
3593 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f), boost::forward<ArgTypes>(args)...)); | |
3594 } | |
3595 #else | |
3596 template <class F> | |
3597 BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type> | |
3598 async(BOOST_THREAD_RV_REF(F) f) | |
3599 { | |
3600 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f))); | |
3601 } | |
3602 #endif | |
3603 | |
3604 | |
3605 //////////////////////////////// | |
3606 // make_future deprecated | |
3607 //////////////////////////////// | |
3608 template <typename T> | |
3609 BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value) | |
3610 { | |
3611 typedef typename decay<T>::type future_value_type; | |
3612 promise<future_value_type> p; | |
3613 p.set_value(boost::forward<future_value_type>(value)); | |
3614 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | |
3615 } | |
3616 | |
3617 #if defined BOOST_THREAD_USES_MOVE | |
3618 inline BOOST_THREAD_FUTURE<void> make_future() | |
3619 { | |
3620 promise<void> p; | |
3621 p.set_value(); | |
3622 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | |
3623 } | |
3624 #endif | |
3625 | |
3626 //////////////////////////////// | |
3627 // make_ready_future | |
3628 //////////////////////////////// | |
3629 template <typename T> | |
3630 BOOST_THREAD_FUTURE<typename decay<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value) | |
3631 { | |
3632 typedef typename decay<T>::type future_value_type; | |
3633 promise<future_value_type> p; | |
3634 p.set_value(boost::forward<future_value_type>(value)); | |
3635 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | |
3636 } | |
3637 | |
3638 #if defined BOOST_THREAD_USES_MOVE | |
3639 inline BOOST_THREAD_FUTURE<void> make_ready_future() | |
3640 { | |
3641 promise<void> p; | |
3642 p.set_value(); | |
3643 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | |
3644 } | |
3645 #endif | |
3646 | |
3647 template <typename T> | |
3648 BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr ex) | |
3649 { | |
3650 promise<T> p; | |
3651 p.set_exception(ex); | |
3652 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | |
3653 } | |
3654 template <typename T, typename E> | |
3655 BOOST_THREAD_FUTURE<T> make_ready_future(E ex) | |
3656 { | |
3657 promise<T> p; | |
3658 p.set_exception(boost::copy_exception(ex)); | |
3659 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | |
3660 } | |
3661 | |
3662 #if 0 | |
3663 template<typename CLOSURE> | |
3664 make_future(CLOSURE closure) -> BOOST_THREAD_FUTURE<decltype(closure())> { | |
3665 typedef decltype(closure()) T; | |
3666 promise<T> p; | |
3667 try | |
3668 { | |
3669 p.set_value(closure()); | |
3670 } | |
3671 catch(...) | |
3672 { | |
3673 p.set_exception(std::current_exception()); | |
3674 } | |
3675 return BOOST_THREAD_MAKE_RV_REF(p.get_future()); | |
3676 } | |
3677 #endif | |
3678 | |
3679 //////////////////////////////// | |
3680 // make_shared_future deprecated | |
3681 //////////////////////////////// | |
3682 template <typename T> | |
3683 shared_future<typename decay<T>::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value) | |
3684 { | |
3685 typedef typename decay<T>::type future_type; | |
3686 promise<future_type> p; | |
3687 p.set_value(boost::forward<T>(value)); | |
3688 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share()); | |
3689 } | |
3690 | |
3691 | |
3692 inline shared_future<void> make_shared_future() | |
3693 { | |
3694 promise<void> p; | |
3695 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share()); | |
3696 | |
3697 } | |
3698 | |
3699 // //////////////////////////////// | |
3700 // // make_ready_shared_future | |
3701 // //////////////////////////////// | |
3702 // template <typename T> | |
3703 // shared_future<typename decay<T>::type> make_ready_shared_future(BOOST_THREAD_FWD_REF(T) value) | |
3704 // { | |
3705 // typedef typename decay<T>::type future_type; | |
3706 // promise<future_type> p; | |
3707 // p.set_value(boost::forward<T>(value)); | |
3708 // return p.get_future().share(); | |
3709 // } | |
3710 // | |
3711 // | |
3712 // inline shared_future<void> make_ready_shared_future() | |
3713 // { | |
3714 // promise<void> p; | |
3715 // return BOOST_THREAD_MAKE_RV_REF(p.get_future().share()); | |
3716 // | |
3717 // } | |
3718 // | |
3719 // //////////////////////////////// | |
3720 // // make_exceptional_shared_future | |
3721 // //////////////////////////////// | |
3722 // template <typename T> | |
3723 // shared_future<T> make_exceptional_shared_future(exception_ptr ex) | |
3724 // { | |
3725 // promise<T> p; | |
3726 // p.set_exception(ex); | |
3727 // return p.get_future().share(); | |
3728 // } | |
3729 | |
3730 //////////////////////////////// | |
3731 // detail::future_async_continuation_shared_state | |
3732 //////////////////////////////// | |
3733 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION | |
3734 namespace detail | |
3735 { | |
3736 | |
3737 ///////////////////////// | |
3738 /// future_async_continuation_shared_state | |
3739 ///////////////////////// | |
3740 | |
3741 template<typename F, typename Rp, typename Fp> | |
3742 struct future_async_continuation_shared_state: future_async_shared_state_base<Rp> | |
3743 { | |
3744 F parent; | |
3745 Fp continuation; | |
3746 | |
3747 public: | |
3748 future_async_continuation_shared_state( | |
3749 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c | |
3750 ) : | |
3751 parent(boost::move(f)), | |
3752 continuation(boost::move(c)) | |
3753 { | |
3754 } | |
3755 | |
3756 void launch_continuation(boost::unique_lock<boost::mutex>& lock) | |
3757 { | |
3758 lock.unlock(); | |
3759 this->thr_ = thread(&future_async_continuation_shared_state::run, this); | |
3760 } | |
3761 | |
3762 static void run(future_async_continuation_shared_state* that) | |
3763 { | |
3764 try | |
3765 { | |
3766 that->mark_finished_with_result(that->continuation(boost::move(that->parent))); | |
3767 } | |
3768 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
3769 catch(thread_interrupted& ) | |
3770 { | |
3771 that->mark_interrupted_finish(); | |
3772 } | |
3773 #endif | |
3774 catch(...) | |
3775 { | |
3776 that->mark_exceptional_finish(); | |
3777 } | |
3778 } | |
3779 ~future_async_continuation_shared_state() | |
3780 { | |
3781 this->join(); | |
3782 } | |
3783 }; | |
3784 | |
3785 template<typename F, typename Fp> | |
3786 struct future_async_continuation_shared_state<F, void, Fp>: public future_async_shared_state_base<void> | |
3787 { | |
3788 F parent; | |
3789 Fp continuation; | |
3790 | |
3791 public: | |
3792 future_async_continuation_shared_state( | |
3793 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c | |
3794 ) : | |
3795 parent(boost::move(f)), | |
3796 continuation(boost::move(c)) | |
3797 { | |
3798 } | |
3799 | |
3800 void launch_continuation(boost::unique_lock<boost::mutex>& lk) | |
3801 { | |
3802 lk.unlock(); | |
3803 this->thr_ = thread(&future_async_continuation_shared_state::run, this); | |
3804 } | |
3805 | |
3806 static void run(future_async_continuation_shared_state* that) | |
3807 { | |
3808 try | |
3809 { | |
3810 that->continuation(boost::move(that->parent)); | |
3811 that->mark_finished_with_result(); | |
3812 } | |
3813 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
3814 catch(thread_interrupted& ) | |
3815 { | |
3816 that->mark_interrupted_finish(); | |
3817 } | |
3818 #endif | |
3819 catch(...) | |
3820 { | |
3821 that->mark_exceptional_finish(); | |
3822 } | |
3823 } | |
3824 ~future_async_continuation_shared_state() | |
3825 { | |
3826 this->join(); | |
3827 } | |
3828 }; | |
3829 | |
3830 | |
3831 ////////////////////////// | |
3832 /// future_deferred_continuation_shared_state | |
3833 ////////////////////////// | |
3834 template<typename F, typename Rp, typename Fp> | |
3835 struct future_deferred_continuation_shared_state: shared_state<Rp> | |
3836 { | |
3837 F parent; | |
3838 Fp continuation; | |
3839 | |
3840 public: | |
3841 future_deferred_continuation_shared_state( | |
3842 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c | |
3843 ) : | |
3844 parent(boost::move(f)), | |
3845 continuation(boost::move(c)) | |
3846 { | |
3847 this->set_deferred(); | |
3848 } | |
3849 | |
3850 virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk) | |
3851 { | |
3852 execute(lk); | |
3853 } | |
3854 | |
3855 virtual void execute(boost::unique_lock<boost::mutex>& lck) { | |
3856 try | |
3857 { | |
3858 Fp local_fuct=boost::move(continuation); | |
3859 F ftmp = boost::move(parent); | |
3860 relocker relock(lck); | |
3861 Rp res = local_fuct(boost::move(ftmp)); | |
3862 relock.lock(); | |
3863 this->mark_finished_with_result_internal(boost::move(res), lck); | |
3864 } | |
3865 catch (...) | |
3866 { | |
3867 this->mark_exceptional_finish_internal(current_exception(), lck); | |
3868 } | |
3869 } | |
3870 }; | |
3871 | |
3872 template<typename F, typename Fp> | |
3873 struct future_deferred_continuation_shared_state<F,void,Fp>: shared_state<void> | |
3874 { | |
3875 F parent; | |
3876 Fp continuation; | |
3877 | |
3878 public: | |
3879 future_deferred_continuation_shared_state( | |
3880 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c | |
3881 ): | |
3882 parent(boost::move(f)), | |
3883 continuation(boost::move(c)) | |
3884 { | |
3885 this->set_deferred(); | |
3886 } | |
3887 | |
3888 virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk) | |
3889 { | |
3890 execute(lk); | |
3891 } | |
3892 virtual void execute(boost::unique_lock<boost::mutex>& lck) { | |
3893 try | |
3894 { | |
3895 Fp local_fuct=boost::move(continuation); | |
3896 F ftmp = boost::move(parent); | |
3897 relocker relock(lck); | |
3898 local_fuct(boost::move(ftmp)); | |
3899 relock.lock(); | |
3900 this->mark_finished_with_result_internal(lck); | |
3901 } | |
3902 catch (...) | |
3903 { | |
3904 this->mark_exceptional_finish_internal(current_exception(), lck); | |
3905 } | |
3906 } | |
3907 }; | |
3908 | |
3909 //////////////////////////////// | |
3910 // make_future_deferred_continuation_shared_state | |
3911 //////////////////////////////// | |
3912 template<typename F, typename Rp, typename Fp> | |
3913 BOOST_THREAD_FUTURE<Rp> | |
3914 make_future_deferred_continuation_shared_state( | |
3915 boost::unique_lock<boost::mutex> &lock, | |
3916 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c | |
3917 ) | |
3918 { | |
3919 shared_ptr<future_deferred_continuation_shared_state<F, Rp, Fp> > | |
3920 h(new future_deferred_continuation_shared_state<F, Rp, Fp>(boost::move(f), boost::forward<Fp>(c))); | |
3921 h->parent.future_->set_continuation_ptr(h, lock); | |
3922 return BOOST_THREAD_FUTURE<Rp>(h); | |
3923 } | |
3924 | |
3925 //////////////////////////////// | |
3926 // make_future_async_continuation_shared_state | |
3927 //////////////////////////////// | |
3928 template<typename F, typename Rp, typename Fp> | |
3929 BOOST_THREAD_FUTURE<Rp> | |
3930 make_future_async_continuation_shared_state( | |
3931 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c | |
3932 ) | |
3933 { | |
3934 shared_ptr<future_async_continuation_shared_state<F,Rp, Fp> > | |
3935 h(new future_async_continuation_shared_state<F,Rp, Fp>(boost::move(f), boost::forward<Fp>(c))); | |
3936 h->parent.future_->set_continuation_ptr(h, lock); | |
3937 | |
3938 return BOOST_THREAD_FUTURE<Rp>(h); | |
3939 } | |
3940 | |
3941 } | |
3942 | |
3943 //////////////////////////////// | |
3944 // template<typename F> | |
3945 // auto future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; | |
3946 //////////////////////////////// | |
3947 | |
3948 template <typename R> | |
3949 template <typename F> | |
3950 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type> | |
3951 BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) | |
3952 { | |
3953 | |
3954 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; | |
3955 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); | |
3956 | |
3957 boost::unique_lock<boost::mutex> lock(this->future_->mutex); | |
3958 if (int(policy) & int(launch::async)) | |
3959 { | |
3960 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | |
3961 lock, boost::move(*this), boost::forward<F>(func) | |
3962 ))); | |
3963 } | |
3964 else if (int(policy) & int(launch::deferred)) | |
3965 { | |
3966 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | |
3967 lock, boost::move(*this), boost::forward<F>(func) | |
3968 ))); | |
3969 } | |
3970 else | |
3971 { | |
3972 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | |
3973 lock, boost::move(*this), boost::forward<F>(func) | |
3974 ))); | |
3975 | |
3976 } | |
3977 | |
3978 } | |
3979 template <typename R> | |
3980 template <typename F> | |
3981 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type> | |
3982 BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func) | |
3983 { | |
3984 | |
3985 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; | |
3986 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); | |
3987 | |
3988 boost::unique_lock<boost::mutex> lock(this->future_->mutex); | |
3989 if (int(this->launch_policy(lock)) & int(launch::async)) | |
3990 { | |
3991 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | |
3992 lock, boost::move(*this), boost::forward<F>(func) | |
3993 ); | |
3994 } | |
3995 else if (int(this->launch_policy(lock)) & int(launch::deferred)) | |
3996 { | |
3997 this->future_->wait_internal(lock); | |
3998 return boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | |
3999 lock, boost::move(*this), boost::forward<F>(func) | |
4000 ); | |
4001 } | |
4002 else | |
4003 { | |
4004 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( | |
4005 lock, boost::move(*this), boost::forward<F>(func) | |
4006 ); | |
4007 } | |
4008 } | |
4009 | |
4010 | |
4011 //#if 0 && defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) | |
4012 // template <typename R> | |
4013 // template<typename RF> | |
4014 // BOOST_THREAD_FUTURE<RF> | |
4015 // BOOST_THREAD_FUTURE<R>::then(RF(*func)(BOOST_THREAD_FUTURE<R>&)) | |
4016 // { | |
4017 // | |
4018 // typedef RF future_type; | |
4019 // | |
4020 // if (this->future_) | |
4021 // { | |
4022 // boost::unique_lock<boost::mutex> lock(this->future_->mutex); | |
4023 // detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr = | |
4024 // new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func); | |
4025 // if (ptr==0) | |
4026 // { | |
4027 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>()); | |
4028 // } | |
4029 // this->future_->set_continuation_ptr(ptr, lock); | |
4030 // return ptr->get_future(); | |
4031 // } else { | |
4032 // // fixme what to do when the future has no associated state? | |
4033 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>()); | |
4034 // } | |
4035 // | |
4036 // } | |
4037 // template <typename R> | |
4038 // template<typename RF> | |
4039 // BOOST_THREAD_FUTURE<RF> | |
4040 // BOOST_THREAD_FUTURE<R>::then(launch policy, RF(*func)(BOOST_THREAD_FUTURE<R>&)) | |
4041 // { | |
4042 // | |
4043 // typedef RF future_type; | |
4044 // | |
4045 // if (this->future_) | |
4046 // { | |
4047 // boost::unique_lock<boost::mutex> lock(this->future_->mutex); | |
4048 // detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr = | |
4049 // new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func, policy); | |
4050 // if (ptr==0) | |
4051 // { | |
4052 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>()); | |
4053 // } | |
4054 // this->future_->set_continuation_ptr(ptr, lock); | |
4055 // return ptr->get_future(); | |
4056 // } else { | |
4057 // // fixme what to do when the future has no associated state? | |
4058 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>()); | |
4059 // } | |
4060 // | |
4061 // } | |
4062 //#endif | |
4063 | |
4064 template <typename R> | |
4065 template <typename F> | |
4066 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type> | |
4067 shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) | |
4068 { | |
4069 | |
4070 typedef typename boost::result_of<F(shared_future<R>)>::type future_type; | |
4071 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); | |
4072 | |
4073 boost::unique_lock<boost::mutex> lock(this->future_->mutex); | |
4074 if (int(policy) & int(launch::async)) | |
4075 { | |
4076 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>( | |
4077 lock, boost::move(*this), boost::forward<F>(func) | |
4078 ))); | |
4079 } | |
4080 else if (int(policy) & int(launch::deferred)) | |
4081 { | |
4082 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>( | |
4083 lock, boost::move(*this), boost::forward<F>(func) | |
4084 ))); | |
4085 } | |
4086 else | |
4087 { | |
4088 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>( | |
4089 lock, boost::move(*this), boost::forward<F>(func) | |
4090 ))); | |
4091 } | |
4092 | |
4093 } | |
4094 template <typename R> | |
4095 template <typename F> | |
4096 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type> | |
4097 shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func) | |
4098 { | |
4099 | |
4100 typedef typename boost::result_of<F(shared_future<R>)>::type future_type; | |
4101 | |
4102 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); | |
4103 | |
4104 boost::unique_lock<boost::mutex> lock(this->future_->mutex); | |
4105 if (int(this->launch_policy(lock)) & int(launch::async)) | |
4106 { | |
4107 return boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>( | |
4108 lock, boost::move(*this), boost::forward<F>(func) | |
4109 ); | |
4110 } | |
4111 else if (int(this->launch_policy(lock)) & int(launch::deferred)) | |
4112 { | |
4113 this->future_->wait_internal(lock); | |
4114 return boost::detail::make_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>( | |
4115 lock, boost::move(*this), boost::forward<F>(func) | |
4116 ); | |
4117 } | |
4118 else | |
4119 { | |
4120 return boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>( | |
4121 lock, boost::move(*this), boost::forward<F>(func) | |
4122 ); | |
4123 } | |
4124 } | |
4125 namespace detail | |
4126 { | |
4127 template <typename T> | |
4128 struct mfallbacker_to | |
4129 { | |
4130 T value_; | |
4131 typedef T result_type; | |
4132 mfallbacker_to(BOOST_THREAD_RV_REF(T) v) | |
4133 : value_(boost::move(v)) | |
4134 {} | |
4135 | |
4136 T operator()(BOOST_THREAD_FUTURE<T> fut) | |
4137 { | |
4138 return fut.get_or(boost::move(value_)); | |
4139 | |
4140 } | |
4141 }; | |
4142 template <typename T> | |
4143 struct cfallbacker_to | |
4144 { | |
4145 T value_; | |
4146 typedef T result_type; | |
4147 cfallbacker_to(T const& v) | |
4148 : value_(v) | |
4149 {} | |
4150 | |
4151 T operator()(BOOST_THREAD_FUTURE<T> fut) | |
4152 { | |
4153 return fut.get_or(value_); | |
4154 | |
4155 } | |
4156 }; | |
4157 } | |
4158 //////////////////////////////// | |
4159 // future<R> future<R>::fallback_to(R&& v); | |
4160 //////////////////////////////// | |
4161 | |
4162 template <typename R> | |
4163 template <typename R2> | |
4164 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type | |
4165 BOOST_THREAD_FUTURE<R>::fallback_to(BOOST_THREAD_RV_REF(R2) v) | |
4166 { | |
4167 return then(detail::mfallbacker_to<R>(boost::move(v))); | |
4168 } | |
4169 | |
4170 template <typename R> | |
4171 template <typename R2> | |
4172 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type | |
4173 BOOST_THREAD_FUTURE<R>::fallback_to(R2 const& v) | |
4174 { | |
4175 return then(detail::cfallbacker_to<R>(v)); | |
4176 } | |
4177 | |
4178 #endif | |
4179 | |
4180 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP | |
4181 namespace detail | |
4182 { | |
4183 | |
4184 ///////////////////////// | |
4185 /// future_unwrap_shared_state | |
4186 ///////////////////////// | |
4187 | |
4188 template<typename F, typename Rp> | |
4189 struct future_unwrap_shared_state: shared_state<Rp> | |
4190 { | |
4191 F parent; | |
4192 public: | |
4193 explicit future_unwrap_shared_state( | |
4194 BOOST_THREAD_RV_REF(F) f | |
4195 ) : | |
4196 parent(boost::move(f)) | |
4197 { | |
4198 } | |
4199 virtual void wait(bool ) // todo see if rethrow must be used | |
4200 { | |
4201 boost::unique_lock<boost::mutex> lock(mutex); | |
4202 parent.get().wait(); | |
4203 } | |
4204 virtual Rp get() | |
4205 { | |
4206 boost::unique_lock<boost::mutex> lock(mutex); | |
4207 return parent.get().get(); | |
4208 } | |
4209 | |
4210 }; | |
4211 | |
4212 template <class F, class Rp> | |
4213 BOOST_THREAD_FUTURE<Rp> | |
4214 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f) | |
4215 { | |
4216 shared_ptr<future_unwrap_shared_state<F, Rp> > | |
4217 h(new future_unwrap_shared_state<F, Rp>(boost::move(f))); | |
4218 h->parent.future_->set_continuation_ptr(h, lock); | |
4219 return BOOST_THREAD_FUTURE<Rp>(h); | |
4220 } | |
4221 } | |
4222 | |
4223 template <typename R> | |
4224 inline BOOST_THREAD_FUTURE<R>::BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other): | |
4225 base_type(other.unwrap()) | |
4226 { | |
4227 } | |
4228 | |
4229 template <typename R2> | |
4230 BOOST_THREAD_FUTURE<R2> | |
4231 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap() | |
4232 { | |
4233 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); | |
4234 boost::unique_lock<boost::mutex> lock(this->future_->mutex); | |
4235 return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this)); | |
4236 } | |
4237 #endif | |
4238 } | |
4239 | |
4240 #endif // BOOST_NO_EXCEPTION | |
4241 #endif // header |