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