1 | // -*- C++ -*- |
2 | //===--------------------------- future -----------------------------------===// |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef _LIBCPP_FUTURE |
11 | #define _LIBCPP_FUTURE |
12 | |
13 | /* |
14 | future synopsis |
15 | |
16 | namespace std |
17 | { |
18 | |
19 | enum class future_errc |
20 | { |
21 | future_already_retrieved = 1, |
22 | promise_already_satisfied, |
23 | no_state, |
24 | broken_promise |
25 | }; |
26 | |
27 | enum class launch |
28 | { |
29 | async = 1, |
30 | deferred = 2, |
31 | any = async | deferred |
32 | }; |
33 | |
34 | enum class future_status |
35 | { |
36 | ready, |
37 | timeout, |
38 | deferred |
39 | }; |
40 | |
41 | template <> struct is_error_code_enum<future_errc> : public true_type { }; |
42 | error_code make_error_code(future_errc e) noexcept; |
43 | error_condition make_error_condition(future_errc e) noexcept; |
44 | |
45 | const error_category& future_category() noexcept; |
46 | |
47 | class future_error |
48 | : public logic_error |
49 | { |
50 | public: |
51 | future_error(error_code ec); // exposition only |
52 | explicit future_error(future_errc); // C++17 |
53 | const error_code& code() const noexcept; |
54 | const char* what() const noexcept; |
55 | }; |
56 | |
57 | template <class R> |
58 | class promise |
59 | { |
60 | public: |
61 | promise(); |
62 | template <class Allocator> |
63 | promise(allocator_arg_t, const Allocator& a); |
64 | promise(promise&& rhs) noexcept; |
65 | promise(const promise& rhs) = delete; |
66 | ~promise(); |
67 | |
68 | // assignment |
69 | promise& operator=(promise&& rhs) noexcept; |
70 | promise& operator=(const promise& rhs) = delete; |
71 | void swap(promise& other) noexcept; |
72 | |
73 | // retrieving the result |
74 | future<R> get_future(); |
75 | |
76 | // setting the result |
77 | void set_value(const R& r); |
78 | void set_value(R&& r); |
79 | void set_exception(exception_ptr p); |
80 | |
81 | // setting the result with deferred notification |
82 | void set_value_at_thread_exit(const R& r); |
83 | void set_value_at_thread_exit(R&& r); |
84 | void set_exception_at_thread_exit(exception_ptr p); |
85 | }; |
86 | |
87 | template <class R> |
88 | class promise<R&> |
89 | { |
90 | public: |
91 | promise(); |
92 | template <class Allocator> |
93 | promise(allocator_arg_t, const Allocator& a); |
94 | promise(promise&& rhs) noexcept; |
95 | promise(const promise& rhs) = delete; |
96 | ~promise(); |
97 | |
98 | // assignment |
99 | promise& operator=(promise&& rhs) noexcept; |
100 | promise& operator=(const promise& rhs) = delete; |
101 | void swap(promise& other) noexcept; |
102 | |
103 | // retrieving the result |
104 | future<R&> get_future(); |
105 | |
106 | // setting the result |
107 | void set_value(R& r); |
108 | void set_exception(exception_ptr p); |
109 | |
110 | // setting the result with deferred notification |
111 | void set_value_at_thread_exit(R&); |
112 | void set_exception_at_thread_exit(exception_ptr p); |
113 | }; |
114 | |
115 | template <> |
116 | class promise<void> |
117 | { |
118 | public: |
119 | promise(); |
120 | template <class Allocator> |
121 | promise(allocator_arg_t, const Allocator& a); |
122 | promise(promise&& rhs) noexcept; |
123 | promise(const promise& rhs) = delete; |
124 | ~promise(); |
125 | |
126 | // assignment |
127 | promise& operator=(promise&& rhs) noexcept; |
128 | promise& operator=(const promise& rhs) = delete; |
129 | void swap(promise& other) noexcept; |
130 | |
131 | // retrieving the result |
132 | future<void> get_future(); |
133 | |
134 | // setting the result |
135 | void set_value(); |
136 | void set_exception(exception_ptr p); |
137 | |
138 | // setting the result with deferred notification |
139 | void set_value_at_thread_exit(); |
140 | void set_exception_at_thread_exit(exception_ptr p); |
141 | }; |
142 | |
143 | template <class R> void swap(promise<R>& x, promise<R>& y) noexcept; |
144 | |
145 | template <class R, class Alloc> |
146 | struct uses_allocator<promise<R>, Alloc> : public true_type {}; |
147 | |
148 | template <class R> |
149 | class future |
150 | { |
151 | public: |
152 | future() noexcept; |
153 | future(future&&) noexcept; |
154 | future(const future& rhs) = delete; |
155 | ~future(); |
156 | future& operator=(const future& rhs) = delete; |
157 | future& operator=(future&&) noexcept; |
158 | shared_future<R> share() noexcept; |
159 | |
160 | // retrieving the value |
161 | R get(); |
162 | |
163 | // functions to check state |
164 | bool valid() const noexcept; |
165 | |
166 | void wait() const; |
167 | template <class Rep, class Period> |
168 | future_status |
169 | wait_for(const chrono::duration<Rep, Period>& rel_time) const; |
170 | template <class Clock, class Duration> |
171 | future_status |
172 | wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; |
173 | }; |
174 | |
175 | template <class R> |
176 | class future<R&> |
177 | { |
178 | public: |
179 | future() noexcept; |
180 | future(future&&) noexcept; |
181 | future(const future& rhs) = delete; |
182 | ~future(); |
183 | future& operator=(const future& rhs) = delete; |
184 | future& operator=(future&&) noexcept; |
185 | shared_future<R&> share() noexcept; |
186 | |
187 | // retrieving the value |
188 | R& get(); |
189 | |
190 | // functions to check state |
191 | bool valid() const noexcept; |
192 | |
193 | void wait() const; |
194 | template <class Rep, class Period> |
195 | future_status |
196 | wait_for(const chrono::duration<Rep, Period>& rel_time) const; |
197 | template <class Clock, class Duration> |
198 | future_status |
199 | wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; |
200 | }; |
201 | |
202 | template <> |
203 | class future<void> |
204 | { |
205 | public: |
206 | future() noexcept; |
207 | future(future&&) noexcept; |
208 | future(const future& rhs) = delete; |
209 | ~future(); |
210 | future& operator=(const future& rhs) = delete; |
211 | future& operator=(future&&) noexcept; |
212 | shared_future<void> share() noexcept; |
213 | |
214 | // retrieving the value |
215 | void get(); |
216 | |
217 | // functions to check state |
218 | bool valid() const noexcept; |
219 | |
220 | void wait() const; |
221 | template <class Rep, class Period> |
222 | future_status |
223 | wait_for(const chrono::duration<Rep, Period>& rel_time) const; |
224 | template <class Clock, class Duration> |
225 | future_status |
226 | wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; |
227 | }; |
228 | |
229 | template <class R> |
230 | class shared_future |
231 | { |
232 | public: |
233 | shared_future() noexcept; |
234 | shared_future(const shared_future& rhs); |
235 | shared_future(future<R>&&) noexcept; |
236 | shared_future(shared_future&& rhs) noexcept; |
237 | ~shared_future(); |
238 | shared_future& operator=(const shared_future& rhs); |
239 | shared_future& operator=(shared_future&& rhs) noexcept; |
240 | |
241 | // retrieving the value |
242 | const R& get() const; |
243 | |
244 | // functions to check state |
245 | bool valid() const noexcept; |
246 | |
247 | void wait() const; |
248 | template <class Rep, class Period> |
249 | future_status |
250 | wait_for(const chrono::duration<Rep, Period>& rel_time) const; |
251 | template <class Clock, class Duration> |
252 | future_status |
253 | wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; |
254 | }; |
255 | |
256 | template <class R> |
257 | class shared_future<R&> |
258 | { |
259 | public: |
260 | shared_future() noexcept; |
261 | shared_future(const shared_future& rhs); |
262 | shared_future(future<R&>&&) noexcept; |
263 | shared_future(shared_future&& rhs) noexcept; |
264 | ~shared_future(); |
265 | shared_future& operator=(const shared_future& rhs); |
266 | shared_future& operator=(shared_future&& rhs) noexcept; |
267 | |
268 | // retrieving the value |
269 | R& get() const; |
270 | |
271 | // functions to check state |
272 | bool valid() const noexcept; |
273 | |
274 | void wait() const; |
275 | template <class Rep, class Period> |
276 | future_status |
277 | wait_for(const chrono::duration<Rep, Period>& rel_time) const; |
278 | template <class Clock, class Duration> |
279 | future_status |
280 | wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; |
281 | }; |
282 | |
283 | template <> |
284 | class shared_future<void> |
285 | { |
286 | public: |
287 | shared_future() noexcept; |
288 | shared_future(const shared_future& rhs); |
289 | shared_future(future<void>&&) noexcept; |
290 | shared_future(shared_future&& rhs) noexcept; |
291 | ~shared_future(); |
292 | shared_future& operator=(const shared_future& rhs); |
293 | shared_future& operator=(shared_future&& rhs) noexcept; |
294 | |
295 | // retrieving the value |
296 | void get() const; |
297 | |
298 | // functions to check state |
299 | bool valid() const noexcept; |
300 | |
301 | void wait() const; |
302 | template <class Rep, class Period> |
303 | future_status |
304 | wait_for(const chrono::duration<Rep, Period>& rel_time) const; |
305 | template <class Clock, class Duration> |
306 | future_status |
307 | wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; |
308 | }; |
309 | |
310 | template <class F, class... Args> |
311 | future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type> |
312 | async(F&& f, Args&&... args); |
313 | |
314 | template <class F, class... Args> |
315 | future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type> |
316 | async(launch policy, F&& f, Args&&... args); |
317 | |
318 | template <class> class packaged_task; // undefined |
319 | |
320 | template <class R, class... ArgTypes> |
321 | class packaged_task<R(ArgTypes...)> |
322 | { |
323 | public: |
324 | typedef R result_type; // extension |
325 | |
326 | // construction and destruction |
327 | packaged_task() noexcept; |
328 | template <class F> |
329 | explicit packaged_task(F&& f); |
330 | template <class F, class Allocator> |
331 | packaged_task(allocator_arg_t, const Allocator& a, F&& f); |
332 | ~packaged_task(); |
333 | |
334 | // no copy |
335 | packaged_task(const packaged_task&) = delete; |
336 | packaged_task& operator=(const packaged_task&) = delete; |
337 | |
338 | // move support |
339 | packaged_task(packaged_task&& other) noexcept; |
340 | packaged_task& operator=(packaged_task&& other) noexcept; |
341 | void swap(packaged_task& other) noexcept; |
342 | |
343 | bool valid() const noexcept; |
344 | |
345 | // result retrieval |
346 | future<R> get_future(); |
347 | |
348 | // execution |
349 | void operator()(ArgTypes... ); |
350 | void make_ready_at_thread_exit(ArgTypes...); |
351 | |
352 | void reset(); |
353 | }; |
354 | |
355 | template <class R> |
356 | void swap(packaged_task<R(ArgTypes...)&, packaged_task<R(ArgTypes...)>&) noexcept; |
357 | |
358 | template <class R, class Alloc> struct uses_allocator<packaged_task<R>, Alloc>; |
359 | |
360 | } // std |
361 | |
362 | */ |
363 | |
364 | #include <__config> |
365 | #include <system_error> |
366 | #include <memory> |
367 | #include <chrono> |
368 | #include <exception> |
369 | #include <mutex> |
370 | #include <thread> |
371 | |
372 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
373 | #pragma GCC system_header |
374 | #endif |
375 | |
376 | #ifdef _LIBCPP_HAS_NO_THREADS |
377 | #error <future> is not supported on this single threaded system |
378 | #else // !_LIBCPP_HAS_NO_THREADS |
379 | |
380 | _LIBCPP_BEGIN_NAMESPACE_STD |
381 | |
382 | //enum class future_errc |
383 | _LIBCPP_DECLARE_STRONG_ENUM(future_errc) |
384 | { |
385 | future_already_retrieved = 1, |
386 | promise_already_satisfied, |
387 | no_state, |
388 | broken_promise |
389 | }; |
390 | _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(future_errc) |
391 | |
392 | template <> |
393 | struct _LIBCPP_TEMPLATE_VIS is_error_code_enum<future_errc> : public true_type {}; |
394 | |
395 | #ifdef _LIBCPP_HAS_NO_STRONG_ENUMS |
396 | template <> |
397 | struct _LIBCPP_TEMPLATE_VIS is_error_code_enum<future_errc::__lx> : public true_type { }; |
398 | #endif |
399 | |
400 | //enum class launch |
401 | _LIBCPP_DECLARE_STRONG_ENUM(launch) |
402 | { |
403 | async = 1, |
404 | deferred = 2, |
405 | any = async | deferred |
406 | }; |
407 | _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(launch) |
408 | |
409 | #ifndef _LIBCPP_HAS_NO_STRONG_ENUMS |
410 | |
411 | typedef underlying_type<launch>::type __launch_underlying_type; |
412 | |
413 | inline _LIBCPP_INLINE_VISIBILITY |
414 | _LIBCPP_CONSTEXPR |
415 | launch |
416 | operator&(launch __x, launch __y) |
417 | { |
418 | return static_cast<launch>(static_cast<__launch_underlying_type>(__x) & |
419 | static_cast<__launch_underlying_type>(__y)); |
420 | } |
421 | |
422 | inline _LIBCPP_INLINE_VISIBILITY |
423 | _LIBCPP_CONSTEXPR |
424 | launch |
425 | operator|(launch __x, launch __y) |
426 | { |
427 | return static_cast<launch>(static_cast<__launch_underlying_type>(__x) | |
428 | static_cast<__launch_underlying_type>(__y)); |
429 | } |
430 | |
431 | inline _LIBCPP_INLINE_VISIBILITY |
432 | _LIBCPP_CONSTEXPR |
433 | launch |
434 | operator^(launch __x, launch __y) |
435 | { |
436 | return static_cast<launch>(static_cast<__launch_underlying_type>(__x) ^ |
437 | static_cast<__launch_underlying_type>(__y)); |
438 | } |
439 | |
440 | inline _LIBCPP_INLINE_VISIBILITY |
441 | _LIBCPP_CONSTEXPR |
442 | launch |
443 | operator~(launch __x) |
444 | { |
445 | return static_cast<launch>(~static_cast<__launch_underlying_type>(__x) & 3); |
446 | } |
447 | |
448 | inline _LIBCPP_INLINE_VISIBILITY |
449 | launch& |
450 | operator&=(launch& __x, launch __y) |
451 | { |
452 | __x = __x & __y; return __x; |
453 | } |
454 | |
455 | inline _LIBCPP_INLINE_VISIBILITY |
456 | launch& |
457 | operator|=(launch& __x, launch __y) |
458 | { |
459 | __x = __x | __y; return __x; |
460 | } |
461 | |
462 | inline _LIBCPP_INLINE_VISIBILITY |
463 | launch& |
464 | operator^=(launch& __x, launch __y) |
465 | { |
466 | __x = __x ^ __y; return __x; |
467 | } |
468 | |
469 | #endif // !_LIBCPP_HAS_NO_STRONG_ENUMS |
470 | |
471 | //enum class future_status |
472 | _LIBCPP_DECLARE_STRONG_ENUM(future_status) |
473 | { |
474 | ready, |
475 | timeout, |
476 | deferred |
477 | }; |
478 | _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(future_status) |
479 | |
480 | _LIBCPP_FUNC_VIS |
481 | const error_category& future_category() _NOEXCEPT; |
482 | |
483 | inline _LIBCPP_INLINE_VISIBILITY |
484 | error_code |
485 | make_error_code(future_errc __e) _NOEXCEPT |
486 | { |
487 | return error_code(static_cast<int>(__e), future_category()); |
488 | } |
489 | |
490 | inline _LIBCPP_INLINE_VISIBILITY |
491 | error_condition |
492 | make_error_condition(future_errc __e) _NOEXCEPT |
493 | { |
494 | return error_condition(static_cast<int>(__e), future_category()); |
495 | } |
496 | |
497 | class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_FUTURE_ERROR future_error |
498 | : public logic_error |
499 | { |
500 | error_code __ec_; |
501 | public: |
502 | future_error(error_code __ec); |
503 | #if _LIBCPP_STD_VERS > 14 |
504 | explicit future_error(future_errc _Ev) : logic_error(), __ec_(make_error_code(_Ev)) {} |
505 | #endif |
506 | _LIBCPP_INLINE_VISIBILITY |
507 | const error_code& code() const _NOEXCEPT {return __ec_;} |
508 | |
509 | virtual ~future_error() _NOEXCEPT; |
510 | }; |
511 | |
512 | _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY |
513 | #ifndef _LIBCPP_NO_EXCEPTIONS |
514 | _LIBCPP_AVAILABILITY_FUTURE_ERROR |
515 | #endif |
516 | void __throw_future_error(future_errc _Ev) |
517 | { |
518 | #ifndef _LIBCPP_NO_EXCEPTIONS |
519 | throw future_error(make_error_code(_Ev)); |
520 | #else |
521 | ((void)_Ev); |
522 | _VSTD::abort(); |
523 | #endif |
524 | } |
525 | |
526 | class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE __assoc_sub_state |
527 | : public __shared_count |
528 | { |
529 | protected: |
530 | exception_ptr __exception_; |
531 | mutable mutex __mut_; |
532 | mutable condition_variable __cv_; |
533 | unsigned __state_; |
534 | |
535 | virtual void __on_zero_shared() _NOEXCEPT; |
536 | void __sub_wait(unique_lock<mutex>& __lk); |
537 | public: |
538 | enum |
539 | { |
540 | __constructed = 1, |
541 | __future_attached = 2, |
542 | ready = 4, |
543 | deferred = 8 |
544 | }; |
545 | |
546 | _LIBCPP_INLINE_VISIBILITY |
547 | __assoc_sub_state() : __state_(0) {} |
548 | |
549 | _LIBCPP_INLINE_VISIBILITY |
550 | bool __has_value() const |
551 | {return (__state_ & __constructed) || (__exception_ != nullptr);} |
552 | |
553 | _LIBCPP_INLINE_VISIBILITY |
554 | void __attach_future() { |
555 | lock_guard<mutex> __lk(__mut_); |
556 | bool __has_future_attached = (__state_ & __future_attached) != 0; |
557 | if (__has_future_attached) |
558 | __throw_future_error(future_errc::future_already_retrieved); |
559 | this->__add_shared(); |
560 | __state_ |= __future_attached; |
561 | } |
562 | |
563 | _LIBCPP_INLINE_VISIBILITY |
564 | void __set_deferred() {__state_ |= deferred;} |
565 | |
566 | void __make_ready(); |
567 | _LIBCPP_INLINE_VISIBILITY |
568 | bool __is_ready() const {return (__state_ & ready) != 0;} |
569 | |
570 | void set_value(); |
571 | void set_value_at_thread_exit(); |
572 | |
573 | void set_exception(exception_ptr __p); |
574 | void set_exception_at_thread_exit(exception_ptr __p); |
575 | |
576 | void copy(); |
577 | |
578 | void wait(); |
579 | template <class _Rep, class _Period> |
580 | future_status |
581 | _LIBCPP_INLINE_VISIBILITY |
582 | wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const; |
583 | template <class _Clock, class _Duration> |
584 | _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS |
585 | future_status |
586 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const; |
587 | |
588 | virtual void __execute(); |
589 | }; |
590 | |
591 | template <class _Clock, class _Duration> |
592 | future_status |
593 | __assoc_sub_state::wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const |
594 | { |
595 | unique_lock<mutex> __lk(__mut_); |
596 | if (__state_ & deferred) |
597 | return future_status::deferred; |
598 | while (!(__state_ & ready) && _Clock::now() < __abs_time) |
599 | __cv_.wait_until(__lk, __abs_time); |
600 | if (__state_ & ready) |
601 | return future_status::ready; |
602 | return future_status::timeout; |
603 | } |
604 | |
605 | template <class _Rep, class _Period> |
606 | inline |
607 | future_status |
608 | __assoc_sub_state::wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const |
609 | { |
610 | return wait_until(chrono::steady_clock::now() + __rel_time); |
611 | } |
612 | |
613 | template <class _Rp> |
614 | class _LIBCPP_AVAILABILITY_FUTURE _LIBCPP_HIDDEN __assoc_state |
615 | : public __assoc_sub_state |
616 | { |
617 | typedef __assoc_sub_state base; |
618 | typedef typename aligned_storage<sizeof(_Rp), alignment_of<_Rp>::value>::type _Up; |
619 | protected: |
620 | _Up __value_; |
621 | |
622 | virtual void __on_zero_shared() _NOEXCEPT; |
623 | public: |
624 | |
625 | template <class _Arg> |
626 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
627 | void set_value(_Arg&& __arg); |
628 | #else |
629 | void set_value(_Arg& __arg); |
630 | #endif |
631 | |
632 | template <class _Arg> |
633 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
634 | void set_value_at_thread_exit(_Arg&& __arg); |
635 | #else |
636 | void set_value_at_thread_exit(_Arg& __arg); |
637 | #endif |
638 | |
639 | _Rp move(); |
640 | typename add_lvalue_reference<_Rp>::type copy(); |
641 | }; |
642 | |
643 | template <class _Rp> |
644 | void |
645 | __assoc_state<_Rp>::__on_zero_shared() _NOEXCEPT |
646 | { |
647 | if (this->__state_ & base::__constructed) |
648 | reinterpret_cast<_Rp*>(&__value_)->~_Rp(); |
649 | delete this; |
650 | } |
651 | |
652 | template <class _Rp> |
653 | template <class _Arg> |
654 | _LIBCPP_AVAILABILITY_FUTURE |
655 | void |
656 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
657 | __assoc_state<_Rp>::set_value(_Arg&& __arg) |
658 | #else |
659 | __assoc_state<_Rp>::set_value(_Arg& __arg) |
660 | #endif |
661 | { |
662 | unique_lock<mutex> __lk(this->__mut_); |
663 | if (this->__has_value()) |
664 | __throw_future_error(future_errc::promise_already_satisfied); |
665 | ::new(&__value_) _Rp(_VSTD::forward<_Arg>(__arg)); |
666 | this->__state_ |= base::__constructed | base::ready; |
667 | __cv_.notify_all(); |
668 | } |
669 | |
670 | template <class _Rp> |
671 | template <class _Arg> |
672 | void |
673 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
674 | __assoc_state<_Rp>::set_value_at_thread_exit(_Arg&& __arg) |
675 | #else |
676 | __assoc_state<_Rp>::set_value_at_thread_exit(_Arg& __arg) |
677 | #endif |
678 | { |
679 | unique_lock<mutex> __lk(this->__mut_); |
680 | if (this->__has_value()) |
681 | __throw_future_error(future_errc::promise_already_satisfied); |
682 | ::new(&__value_) _Rp(_VSTD::forward<_Arg>(__arg)); |
683 | this->__state_ |= base::__constructed; |
684 | __thread_local_data()->__make_ready_at_thread_exit(this); |
685 | } |
686 | |
687 | template <class _Rp> |
688 | _Rp |
689 | __assoc_state<_Rp>::move() |
690 | { |
691 | unique_lock<mutex> __lk(this->__mut_); |
692 | this->__sub_wait(__lk); |
693 | if (this->__exception_ != nullptr) |
694 | rethrow_exception(this->__exception_); |
695 | return _VSTD::move(*reinterpret_cast<_Rp*>(&__value_)); |
696 | } |
697 | |
698 | template <class _Rp> |
699 | typename add_lvalue_reference<_Rp>::type |
700 | __assoc_state<_Rp>::copy() |
701 | { |
702 | unique_lock<mutex> __lk(this->__mut_); |
703 | this->__sub_wait(__lk); |
704 | if (this->__exception_ != nullptr) |
705 | rethrow_exception(this->__exception_); |
706 | return *reinterpret_cast<_Rp*>(&__value_); |
707 | } |
708 | |
709 | template <class _Rp> |
710 | class _LIBCPP_AVAILABILITY_FUTURE __assoc_state<_Rp&> |
711 | : public __assoc_sub_state |
712 | { |
713 | typedef __assoc_sub_state base; |
714 | typedef _Rp* _Up; |
715 | protected: |
716 | _Up __value_; |
717 | |
718 | virtual void __on_zero_shared() _NOEXCEPT; |
719 | public: |
720 | |
721 | void set_value(_Rp& __arg); |
722 | void set_value_at_thread_exit(_Rp& __arg); |
723 | |
724 | _Rp& copy(); |
725 | }; |
726 | |
727 | template <class _Rp> |
728 | void |
729 | __assoc_state<_Rp&>::__on_zero_shared() _NOEXCEPT |
730 | { |
731 | delete this; |
732 | } |
733 | |
734 | template <class _Rp> |
735 | void |
736 | __assoc_state<_Rp&>::set_value(_Rp& __arg) |
737 | { |
738 | unique_lock<mutex> __lk(this->__mut_); |
739 | if (this->__has_value()) |
740 | __throw_future_error(future_errc::promise_already_satisfied); |
741 | __value_ = _VSTD::addressof(__arg); |
742 | this->__state_ |= base::__constructed | base::ready; |
743 | __cv_.notify_all(); |
744 | } |
745 | |
746 | template <class _Rp> |
747 | void |
748 | __assoc_state<_Rp&>::set_value_at_thread_exit(_Rp& __arg) |
749 | { |
750 | unique_lock<mutex> __lk(this->__mut_); |
751 | if (this->__has_value()) |
752 | __throw_future_error(future_errc::promise_already_satisfied); |
753 | __value_ = _VSTD::addressof(__arg); |
754 | this->__state_ |= base::__constructed; |
755 | __thread_local_data()->__make_ready_at_thread_exit(this); |
756 | } |
757 | |
758 | template <class _Rp> |
759 | _Rp& |
760 | __assoc_state<_Rp&>::copy() |
761 | { |
762 | unique_lock<mutex> __lk(this->__mut_); |
763 | this->__sub_wait(__lk); |
764 | if (this->__exception_ != nullptr) |
765 | rethrow_exception(this->__exception_); |
766 | return *__value_; |
767 | } |
768 | |
769 | template <class _Rp, class _Alloc> |
770 | class _LIBCPP_AVAILABILITY_FUTURE __assoc_state_alloc |
771 | : public __assoc_state<_Rp> |
772 | { |
773 | typedef __assoc_state<_Rp> base; |
774 | _Alloc __alloc_; |
775 | |
776 | virtual void __on_zero_shared() _NOEXCEPT; |
777 | public: |
778 | _LIBCPP_INLINE_VISIBILITY |
779 | explicit __assoc_state_alloc(const _Alloc& __a) |
780 | : __alloc_(__a) {} |
781 | }; |
782 | |
783 | template <class _Rp, class _Alloc> |
784 | void |
785 | __assoc_state_alloc<_Rp, _Alloc>::__on_zero_shared() _NOEXCEPT |
786 | { |
787 | if (this->__state_ & base::__constructed) |
788 | reinterpret_cast<_Rp*>(_VSTD::addressof(this->__value_))->~_Rp(); |
789 | typedef typename __allocator_traits_rebind<_Alloc, __assoc_state_alloc>::type _Al; |
790 | typedef allocator_traits<_Al> _ATraits; |
791 | typedef pointer_traits<typename _ATraits::pointer> _PTraits; |
792 | _Al __a(__alloc_); |
793 | this->~__assoc_state_alloc(); |
794 | __a.deallocate(_PTraits::pointer_to(*this), 1); |
795 | } |
796 | |
797 | template <class _Rp, class _Alloc> |
798 | class _LIBCPP_AVAILABILITY_FUTURE __assoc_state_alloc<_Rp&, _Alloc> |
799 | : public __assoc_state<_Rp&> |
800 | { |
801 | typedef __assoc_state<_Rp&> base; |
802 | _Alloc __alloc_; |
803 | |
804 | virtual void __on_zero_shared() _NOEXCEPT; |
805 | public: |
806 | _LIBCPP_INLINE_VISIBILITY |
807 | explicit __assoc_state_alloc(const _Alloc& __a) |
808 | : __alloc_(__a) {} |
809 | }; |
810 | |
811 | template <class _Rp, class _Alloc> |
812 | void |
813 | __assoc_state_alloc<_Rp&, _Alloc>::__on_zero_shared() _NOEXCEPT |
814 | { |
815 | typedef typename __allocator_traits_rebind<_Alloc, __assoc_state_alloc>::type _Al; |
816 | typedef allocator_traits<_Al> _ATraits; |
817 | typedef pointer_traits<typename _ATraits::pointer> _PTraits; |
818 | _Al __a(__alloc_); |
819 | this->~__assoc_state_alloc(); |
820 | __a.deallocate(_PTraits::pointer_to(*this), 1); |
821 | } |
822 | |
823 | template <class _Alloc> |
824 | class _LIBCPP_AVAILABILITY_FUTURE __assoc_sub_state_alloc |
825 | : public __assoc_sub_state |
826 | { |
827 | typedef __assoc_sub_state base; |
828 | _Alloc __alloc_; |
829 | |
830 | virtual void __on_zero_shared() _NOEXCEPT; |
831 | public: |
832 | _LIBCPP_INLINE_VISIBILITY |
833 | explicit __assoc_sub_state_alloc(const _Alloc& __a) |
834 | : __alloc_(__a) {} |
835 | }; |
836 | |
837 | template <class _Alloc> |
838 | void |
839 | __assoc_sub_state_alloc<_Alloc>::__on_zero_shared() _NOEXCEPT |
840 | { |
841 | typedef typename __allocator_traits_rebind<_Alloc, __assoc_sub_state_alloc>::type _Al; |
842 | typedef allocator_traits<_Al> _ATraits; |
843 | typedef pointer_traits<typename _ATraits::pointer> _PTraits; |
844 | _Al __a(__alloc_); |
845 | this->~__assoc_sub_state_alloc(); |
846 | __a.deallocate(_PTraits::pointer_to(*this), 1); |
847 | } |
848 | |
849 | template <class _Rp, class _Fp> |
850 | class _LIBCPP_AVAILABILITY_FUTURE __deferred_assoc_state |
851 | : public __assoc_state<_Rp> |
852 | { |
853 | typedef __assoc_state<_Rp> base; |
854 | |
855 | _Fp __func_; |
856 | |
857 | public: |
858 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
859 | _LIBCPP_INLINE_VISIBILITY |
860 | explicit __deferred_assoc_state(_Fp&& __f); |
861 | #endif |
862 | |
863 | virtual void __execute(); |
864 | }; |
865 | |
866 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
867 | |
868 | template <class _Rp, class _Fp> |
869 | inline |
870 | __deferred_assoc_state<_Rp, _Fp>::__deferred_assoc_state(_Fp&& __f) |
871 | : __func_(_VSTD::forward<_Fp>(__f)) |
872 | { |
873 | this->__set_deferred(); |
874 | } |
875 | |
876 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
877 | |
878 | template <class _Rp, class _Fp> |
879 | void |
880 | __deferred_assoc_state<_Rp, _Fp>::__execute() |
881 | { |
882 | #ifndef _LIBCPP_NO_EXCEPTIONS |
883 | try |
884 | { |
885 | #endif // _LIBCPP_NO_EXCEPTIONS |
886 | this->set_value(__func_()); |
887 | #ifndef _LIBCPP_NO_EXCEPTIONS |
888 | } |
889 | catch (...) |
890 | { |
891 | this->set_exception(current_exception()); |
892 | } |
893 | #endif // _LIBCPP_NO_EXCEPTIONS |
894 | } |
895 | |
896 | template <class _Fp> |
897 | class _LIBCPP_AVAILABILITY_FUTURE __deferred_assoc_state<void, _Fp> |
898 | : public __assoc_sub_state |
899 | { |
900 | typedef __assoc_sub_state base; |
901 | |
902 | _Fp __func_; |
903 | |
904 | public: |
905 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
906 | _LIBCPP_INLINE_VISIBILITY |
907 | explicit __deferred_assoc_state(_Fp&& __f); |
908 | #endif |
909 | |
910 | virtual void __execute(); |
911 | }; |
912 | |
913 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
914 | |
915 | template <class _Fp> |
916 | inline |
917 | __deferred_assoc_state<void, _Fp>::__deferred_assoc_state(_Fp&& __f) |
918 | : __func_(_VSTD::forward<_Fp>(__f)) |
919 | { |
920 | this->__set_deferred(); |
921 | } |
922 | |
923 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
924 | |
925 | template <class _Fp> |
926 | void |
927 | __deferred_assoc_state<void, _Fp>::__execute() |
928 | { |
929 | #ifndef _LIBCPP_NO_EXCEPTIONS |
930 | try |
931 | { |
932 | #endif // _LIBCPP_NO_EXCEPTIONS |
933 | __func_(); |
934 | this->set_value(); |
935 | #ifndef _LIBCPP_NO_EXCEPTIONS |
936 | } |
937 | catch (...) |
938 | { |
939 | this->set_exception(current_exception()); |
940 | } |
941 | #endif // _LIBCPP_NO_EXCEPTIONS |
942 | } |
943 | |
944 | template <class _Rp, class _Fp> |
945 | class _LIBCPP_AVAILABILITY_FUTURE __async_assoc_state |
946 | : public __assoc_state<_Rp> |
947 | { |
948 | typedef __assoc_state<_Rp> base; |
949 | |
950 | _Fp __func_; |
951 | |
952 | virtual void __on_zero_shared() _NOEXCEPT; |
953 | public: |
954 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
955 | _LIBCPP_INLINE_VISIBILITY |
956 | explicit __async_assoc_state(_Fp&& __f); |
957 | #endif |
958 | |
959 | virtual void __execute(); |
960 | }; |
961 | |
962 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
963 | |
964 | template <class _Rp, class _Fp> |
965 | inline |
966 | __async_assoc_state<_Rp, _Fp>::__async_assoc_state(_Fp&& __f) |
967 | : __func_(_VSTD::forward<_Fp>(__f)) |
968 | { |
969 | } |
970 | |
971 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
972 | |
973 | template <class _Rp, class _Fp> |
974 | void |
975 | __async_assoc_state<_Rp, _Fp>::__execute() |
976 | { |
977 | #ifndef _LIBCPP_NO_EXCEPTIONS |
978 | try |
979 | { |
980 | #endif // _LIBCPP_NO_EXCEPTIONS |
981 | this->set_value(__func_()); |
982 | #ifndef _LIBCPP_NO_EXCEPTIONS |
983 | } |
984 | catch (...) |
985 | { |
986 | this->set_exception(current_exception()); |
987 | } |
988 | #endif // _LIBCPP_NO_EXCEPTIONS |
989 | } |
990 | |
991 | template <class _Rp, class _Fp> |
992 | void |
993 | __async_assoc_state<_Rp, _Fp>::__on_zero_shared() _NOEXCEPT |
994 | { |
995 | this->wait(); |
996 | base::__on_zero_shared(); |
997 | } |
998 | |
999 | template <class _Fp> |
1000 | class _LIBCPP_AVAILABILITY_FUTURE __async_assoc_state<void, _Fp> |
1001 | : public __assoc_sub_state |
1002 | { |
1003 | typedef __assoc_sub_state base; |
1004 | |
1005 | _Fp __func_; |
1006 | |
1007 | virtual void __on_zero_shared() _NOEXCEPT; |
1008 | public: |
1009 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1010 | _LIBCPP_INLINE_VISIBILITY |
1011 | explicit __async_assoc_state(_Fp&& __f); |
1012 | #endif |
1013 | |
1014 | virtual void __execute(); |
1015 | }; |
1016 | |
1017 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1018 | |
1019 | template <class _Fp> |
1020 | inline |
1021 | __async_assoc_state<void, _Fp>::__async_assoc_state(_Fp&& __f) |
1022 | : __func_(_VSTD::forward<_Fp>(__f)) |
1023 | { |
1024 | } |
1025 | |
1026 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1027 | |
1028 | template <class _Fp> |
1029 | void |
1030 | __async_assoc_state<void, _Fp>::__execute() |
1031 | { |
1032 | #ifndef _LIBCPP_NO_EXCEPTIONS |
1033 | try |
1034 | { |
1035 | #endif // _LIBCPP_NO_EXCEPTIONS |
1036 | __func_(); |
1037 | this->set_value(); |
1038 | #ifndef _LIBCPP_NO_EXCEPTIONS |
1039 | } |
1040 | catch (...) |
1041 | { |
1042 | this->set_exception(current_exception()); |
1043 | } |
1044 | #endif // _LIBCPP_NO_EXCEPTIONS |
1045 | } |
1046 | |
1047 | template <class _Fp> |
1048 | void |
1049 | __async_assoc_state<void, _Fp>::__on_zero_shared() _NOEXCEPT |
1050 | { |
1051 | this->wait(); |
1052 | base::__on_zero_shared(); |
1053 | } |
1054 | |
1055 | template <class _Rp> class _LIBCPP_TEMPLATE_VIS promise; |
1056 | template <class _Rp> class _LIBCPP_TEMPLATE_VIS shared_future; |
1057 | |
1058 | // future |
1059 | |
1060 | template <class _Rp> class _LIBCPP_TEMPLATE_VIS future; |
1061 | |
1062 | template <class _Rp, class _Fp> |
1063 | _LIBCPP_INLINE_VISIBILITY future<_Rp> |
1064 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1065 | __make_deferred_assoc_state(_Fp&& __f); |
1066 | #else |
1067 | __make_deferred_assoc_state(_Fp __f); |
1068 | #endif |
1069 | |
1070 | template <class _Rp, class _Fp> |
1071 | _LIBCPP_INLINE_VISIBILITY future<_Rp> |
1072 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1073 | __make_async_assoc_state(_Fp&& __f); |
1074 | #else |
1075 | __make_async_assoc_state(_Fp __f); |
1076 | #endif |
1077 | |
1078 | template <class _Rp> |
1079 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE future |
1080 | { |
1081 | __assoc_state<_Rp>* __state_; |
1082 | |
1083 | explicit future(__assoc_state<_Rp>* __state); |
1084 | |
1085 | template <class> friend class promise; |
1086 | template <class> friend class shared_future; |
1087 | |
1088 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1089 | template <class _R1, class _Fp> |
1090 | friend future<_R1> __make_deferred_assoc_state(_Fp&& __f); |
1091 | template <class _R1, class _Fp> |
1092 | friend future<_R1> __make_async_assoc_state(_Fp&& __f); |
1093 | #else |
1094 | template <class _R1, class _Fp> |
1095 | friend future<_R1> __make_deferred_assoc_state(_Fp __f); |
1096 | template <class _R1, class _Fp> |
1097 | friend future<_R1> __make_async_assoc_state(_Fp __f); |
1098 | #endif |
1099 | |
1100 | public: |
1101 | _LIBCPP_INLINE_VISIBILITY |
1102 | future() _NOEXCEPT : __state_(nullptr) {} |
1103 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1104 | _LIBCPP_INLINE_VISIBILITY |
1105 | future(future&& __rhs) _NOEXCEPT |
1106 | : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} |
1107 | future(const future&) = delete; |
1108 | future& operator=(const future&) = delete; |
1109 | _LIBCPP_INLINE_VISIBILITY |
1110 | future& operator=(future&& __rhs) _NOEXCEPT |
1111 | { |
1112 | future(std::move(__rhs)).swap(*this); |
1113 | return *this; |
1114 | } |
1115 | #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1116 | private: |
1117 | future(const future&); |
1118 | future& operator=(const future&); |
1119 | public: |
1120 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1121 | ~future(); |
1122 | _LIBCPP_INLINE_VISIBILITY |
1123 | shared_future<_Rp> share() _NOEXCEPT; |
1124 | |
1125 | // retrieving the value |
1126 | _Rp get(); |
1127 | |
1128 | _LIBCPP_INLINE_VISIBILITY |
1129 | void swap(future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} |
1130 | |
1131 | // functions to check state |
1132 | _LIBCPP_INLINE_VISIBILITY |
1133 | bool valid() const _NOEXCEPT {return __state_ != nullptr;} |
1134 | |
1135 | _LIBCPP_INLINE_VISIBILITY |
1136 | void wait() const {__state_->wait();} |
1137 | template <class _Rep, class _Period> |
1138 | _LIBCPP_INLINE_VISIBILITY |
1139 | future_status |
1140 | wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const |
1141 | {return __state_->wait_for(__rel_time);} |
1142 | template <class _Clock, class _Duration> |
1143 | _LIBCPP_INLINE_VISIBILITY |
1144 | future_status |
1145 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const |
1146 | {return __state_->wait_until(__abs_time);} |
1147 | }; |
1148 | |
1149 | template <class _Rp> |
1150 | future<_Rp>::future(__assoc_state<_Rp>* __state) |
1151 | : __state_(__state) |
1152 | { |
1153 | __state_->__attach_future(); |
1154 | } |
1155 | |
1156 | struct __release_shared_count |
1157 | { |
1158 | void operator()(__shared_count* p) {p->__release_shared();} |
1159 | }; |
1160 | |
1161 | template <class _Rp> |
1162 | future<_Rp>::~future() |
1163 | { |
1164 | if (__state_) |
1165 | __state_->__release_shared(); |
1166 | } |
1167 | |
1168 | template <class _Rp> |
1169 | _Rp |
1170 | future<_Rp>::get() |
1171 | { |
1172 | unique_ptr<__shared_count, __release_shared_count> __(__state_); |
1173 | __assoc_state<_Rp>* __s = __state_; |
1174 | __state_ = nullptr; |
1175 | return __s->move(); |
1176 | } |
1177 | |
1178 | template <class _Rp> |
1179 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE future<_Rp&> |
1180 | { |
1181 | __assoc_state<_Rp&>* __state_; |
1182 | |
1183 | explicit future(__assoc_state<_Rp&>* __state); |
1184 | |
1185 | template <class> friend class promise; |
1186 | template <class> friend class shared_future; |
1187 | |
1188 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1189 | template <class _R1, class _Fp> |
1190 | friend future<_R1> __make_deferred_assoc_state(_Fp&& __f); |
1191 | template <class _R1, class _Fp> |
1192 | friend future<_R1> __make_async_assoc_state(_Fp&& __f); |
1193 | #else |
1194 | template <class _R1, class _Fp> |
1195 | friend future<_R1> __make_deferred_assoc_state(_Fp __f); |
1196 | template <class _R1, class _Fp> |
1197 | friend future<_R1> __make_async_assoc_state(_Fp __f); |
1198 | #endif |
1199 | |
1200 | public: |
1201 | _LIBCPP_INLINE_VISIBILITY |
1202 | future() _NOEXCEPT : __state_(nullptr) {} |
1203 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1204 | _LIBCPP_INLINE_VISIBILITY |
1205 | future(future&& __rhs) _NOEXCEPT |
1206 | : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} |
1207 | future(const future&) = delete; |
1208 | future& operator=(const future&) = delete; |
1209 | _LIBCPP_INLINE_VISIBILITY |
1210 | future& operator=(future&& __rhs) _NOEXCEPT |
1211 | { |
1212 | future(std::move(__rhs)).swap(*this); |
1213 | return *this; |
1214 | } |
1215 | #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1216 | private: |
1217 | future(const future&); |
1218 | future& operator=(const future&); |
1219 | public: |
1220 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1221 | ~future(); |
1222 | _LIBCPP_INLINE_VISIBILITY |
1223 | shared_future<_Rp&> share() _NOEXCEPT; |
1224 | |
1225 | // retrieving the value |
1226 | _Rp& get(); |
1227 | |
1228 | _LIBCPP_INLINE_VISIBILITY |
1229 | void swap(future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} |
1230 | |
1231 | // functions to check state |
1232 | _LIBCPP_INLINE_VISIBILITY |
1233 | bool valid() const _NOEXCEPT {return __state_ != nullptr;} |
1234 | |
1235 | _LIBCPP_INLINE_VISIBILITY |
1236 | void wait() const {__state_->wait();} |
1237 | template <class _Rep, class _Period> |
1238 | _LIBCPP_INLINE_VISIBILITY |
1239 | future_status |
1240 | wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const |
1241 | {return __state_->wait_for(__rel_time);} |
1242 | template <class _Clock, class _Duration> |
1243 | _LIBCPP_INLINE_VISIBILITY |
1244 | future_status |
1245 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const |
1246 | {return __state_->wait_until(__abs_time);} |
1247 | }; |
1248 | |
1249 | template <class _Rp> |
1250 | future<_Rp&>::future(__assoc_state<_Rp&>* __state) |
1251 | : __state_(__state) |
1252 | { |
1253 | __state_->__attach_future(); |
1254 | } |
1255 | |
1256 | template <class _Rp> |
1257 | future<_Rp&>::~future() |
1258 | { |
1259 | if (__state_) |
1260 | __state_->__release_shared(); |
1261 | } |
1262 | |
1263 | template <class _Rp> |
1264 | _Rp& |
1265 | future<_Rp&>::get() |
1266 | { |
1267 | unique_ptr<__shared_count, __release_shared_count> __(__state_); |
1268 | __assoc_state<_Rp&>* __s = __state_; |
1269 | __state_ = nullptr; |
1270 | return __s->copy(); |
1271 | } |
1272 | |
1273 | template <> |
1274 | class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE future<void> |
1275 | { |
1276 | __assoc_sub_state* __state_; |
1277 | |
1278 | explicit future(__assoc_sub_state* __state); |
1279 | |
1280 | template <class> friend class promise; |
1281 | template <class> friend class shared_future; |
1282 | |
1283 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1284 | template <class _R1, class _Fp> |
1285 | friend future<_R1> __make_deferred_assoc_state(_Fp&& __f); |
1286 | template <class _R1, class _Fp> |
1287 | friend future<_R1> __make_async_assoc_state(_Fp&& __f); |
1288 | #else |
1289 | template <class _R1, class _Fp> |
1290 | friend future<_R1> __make_deferred_assoc_state(_Fp __f); |
1291 | template <class _R1, class _Fp> |
1292 | friend future<_R1> __make_async_assoc_state(_Fp __f); |
1293 | #endif |
1294 | |
1295 | public: |
1296 | _LIBCPP_INLINE_VISIBILITY |
1297 | future() _NOEXCEPT : __state_(nullptr) {} |
1298 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1299 | _LIBCPP_INLINE_VISIBILITY |
1300 | future(future&& __rhs) _NOEXCEPT |
1301 | : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} |
1302 | future(const future&) = delete; |
1303 | future& operator=(const future&) = delete; |
1304 | _LIBCPP_INLINE_VISIBILITY |
1305 | future& operator=(future&& __rhs) _NOEXCEPT |
1306 | { |
1307 | future(std::move(__rhs)).swap(*this); |
1308 | return *this; |
1309 | } |
1310 | #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1311 | private: |
1312 | future(const future&); |
1313 | future& operator=(const future&); |
1314 | public: |
1315 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1316 | ~future(); |
1317 | _LIBCPP_INLINE_VISIBILITY |
1318 | shared_future<void> share() _NOEXCEPT; |
1319 | |
1320 | // retrieving the value |
1321 | void get(); |
1322 | |
1323 | _LIBCPP_INLINE_VISIBILITY |
1324 | void swap(future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} |
1325 | |
1326 | // functions to check state |
1327 | _LIBCPP_INLINE_VISIBILITY |
1328 | bool valid() const _NOEXCEPT {return __state_ != nullptr;} |
1329 | |
1330 | _LIBCPP_INLINE_VISIBILITY |
1331 | void wait() const {__state_->wait();} |
1332 | template <class _Rep, class _Period> |
1333 | _LIBCPP_INLINE_VISIBILITY |
1334 | future_status |
1335 | wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const |
1336 | {return __state_->wait_for(__rel_time);} |
1337 | template <class _Clock, class _Duration> |
1338 | _LIBCPP_INLINE_VISIBILITY |
1339 | future_status |
1340 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const |
1341 | {return __state_->wait_until(__abs_time);} |
1342 | }; |
1343 | |
1344 | template <class _Rp> |
1345 | inline _LIBCPP_INLINE_VISIBILITY |
1346 | void |
1347 | swap(future<_Rp>& __x, future<_Rp>& __y) _NOEXCEPT |
1348 | { |
1349 | __x.swap(__y); |
1350 | } |
1351 | |
1352 | // promise<R> |
1353 | |
1354 | template <class _Callable> class packaged_task; |
1355 | |
1356 | template <class _Rp> |
1357 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE promise |
1358 | { |
1359 | __assoc_state<_Rp>* __state_; |
1360 | |
1361 | _LIBCPP_INLINE_VISIBILITY |
1362 | explicit promise(nullptr_t) _NOEXCEPT : __state_(nullptr) {} |
1363 | |
1364 | template <class> friend class packaged_task; |
1365 | public: |
1366 | promise(); |
1367 | template <class _Alloc> |
1368 | promise(allocator_arg_t, const _Alloc& __a); |
1369 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1370 | _LIBCPP_INLINE_VISIBILITY |
1371 | promise(promise&& __rhs) _NOEXCEPT |
1372 | : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} |
1373 | promise(const promise& __rhs) = delete; |
1374 | #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1375 | private: |
1376 | promise(const promise& __rhs); |
1377 | public: |
1378 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1379 | ~promise(); |
1380 | |
1381 | // assignment |
1382 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1383 | _LIBCPP_INLINE_VISIBILITY |
1384 | promise& operator=(promise&& __rhs) _NOEXCEPT |
1385 | { |
1386 | promise(std::move(__rhs)).swap(*this); |
1387 | return *this; |
1388 | } |
1389 | promise& operator=(const promise& __rhs) = delete; |
1390 | #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1391 | private: |
1392 | promise& operator=(const promise& __rhs); |
1393 | public: |
1394 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1395 | _LIBCPP_INLINE_VISIBILITY |
1396 | void swap(promise& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} |
1397 | |
1398 | // retrieving the result |
1399 | future<_Rp> get_future(); |
1400 | |
1401 | // setting the result |
1402 | void set_value(const _Rp& __r); |
1403 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1404 | void set_value(_Rp&& __r); |
1405 | #endif |
1406 | void set_exception(exception_ptr __p); |
1407 | |
1408 | // setting the result with deferred notification |
1409 | void set_value_at_thread_exit(const _Rp& __r); |
1410 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1411 | void set_value_at_thread_exit(_Rp&& __r); |
1412 | #endif |
1413 | void set_exception_at_thread_exit(exception_ptr __p); |
1414 | }; |
1415 | |
1416 | template <class _Rp> |
1417 | promise<_Rp>::promise() |
1418 | : __state_(new __assoc_state<_Rp>) |
1419 | { |
1420 | } |
1421 | |
1422 | template <class _Rp> |
1423 | template <class _Alloc> |
1424 | promise<_Rp>::promise(allocator_arg_t, const _Alloc& __a0) |
1425 | { |
1426 | typedef __assoc_state_alloc<_Rp, _Alloc> _State; |
1427 | typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2; |
1428 | typedef __allocator_destructor<_A2> _D2; |
1429 | _A2 __a(__a0); |
1430 | unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1)); |
1431 | ::new(static_cast<void*>(_VSTD::addressof(*__hold.get()))) _State(__a0); |
1432 | __state_ = _VSTD::addressof(*__hold.release()); |
1433 | } |
1434 | |
1435 | template <class _Rp> |
1436 | promise<_Rp>::~promise() |
1437 | { |
1438 | if (__state_) |
1439 | { |
1440 | if (!__state_->__has_value() && __state_->use_count() > 1) |
1441 | __state_->set_exception(make_exception_ptr( |
1442 | future_error(make_error_code(future_errc::broken_promise)) |
1443 | )); |
1444 | __state_->__release_shared(); |
1445 | } |
1446 | } |
1447 | |
1448 | template <class _Rp> |
1449 | future<_Rp> |
1450 | promise<_Rp>::get_future() |
1451 | { |
1452 | if (__state_ == nullptr) |
1453 | __throw_future_error(future_errc::no_state); |
1454 | return future<_Rp>(__state_); |
1455 | } |
1456 | |
1457 | template <class _Rp> |
1458 | void |
1459 | promise<_Rp>::set_value(const _Rp& __r) |
1460 | { |
1461 | if (__state_ == nullptr) |
1462 | __throw_future_error(future_errc::no_state); |
1463 | __state_->set_value(__r); |
1464 | } |
1465 | |
1466 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1467 | |
1468 | template <class _Rp> |
1469 | void |
1470 | promise<_Rp>::set_value(_Rp&& __r) |
1471 | { |
1472 | if (__state_ == nullptr) |
1473 | __throw_future_error(future_errc::no_state); |
1474 | __state_->set_value(_VSTD::move(__r)); |
1475 | } |
1476 | |
1477 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1478 | |
1479 | template <class _Rp> |
1480 | void |
1481 | promise<_Rp>::set_exception(exception_ptr __p) |
1482 | { |
1483 | _LIBCPP_ASSERT( __p != nullptr, "promise::set_exception: received nullptr" ); |
1484 | if (__state_ == nullptr) |
1485 | __throw_future_error(future_errc::no_state); |
1486 | __state_->set_exception(__p); |
1487 | } |
1488 | |
1489 | template <class _Rp> |
1490 | void |
1491 | promise<_Rp>::set_value_at_thread_exit(const _Rp& __r) |
1492 | { |
1493 | if (__state_ == nullptr) |
1494 | __throw_future_error(future_errc::no_state); |
1495 | __state_->set_value_at_thread_exit(__r); |
1496 | } |
1497 | |
1498 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1499 | |
1500 | template <class _Rp> |
1501 | void |
1502 | promise<_Rp>::set_value_at_thread_exit(_Rp&& __r) |
1503 | { |
1504 | if (__state_ == nullptr) |
1505 | __throw_future_error(future_errc::no_state); |
1506 | __state_->set_value_at_thread_exit(_VSTD::move(__r)); |
1507 | } |
1508 | |
1509 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1510 | |
1511 | template <class _Rp> |
1512 | void |
1513 | promise<_Rp>::set_exception_at_thread_exit(exception_ptr __p) |
1514 | { |
1515 | _LIBCPP_ASSERT( __p != nullptr, "promise::set_exception_at_thread_exit: received nullptr" ); |
1516 | if (__state_ == nullptr) |
1517 | __throw_future_error(future_errc::no_state); |
1518 | __state_->set_exception_at_thread_exit(__p); |
1519 | } |
1520 | |
1521 | // promise<R&> |
1522 | |
1523 | template <class _Rp> |
1524 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE promise<_Rp&> |
1525 | { |
1526 | __assoc_state<_Rp&>* __state_; |
1527 | |
1528 | _LIBCPP_INLINE_VISIBILITY |
1529 | explicit promise(nullptr_t) _NOEXCEPT : __state_(nullptr) {} |
1530 | |
1531 | template <class> friend class packaged_task; |
1532 | |
1533 | public: |
1534 | promise(); |
1535 | template <class _Allocator> |
1536 | promise(allocator_arg_t, const _Allocator& __a); |
1537 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1538 | _LIBCPP_INLINE_VISIBILITY |
1539 | promise(promise&& __rhs) _NOEXCEPT |
1540 | : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} |
1541 | promise(const promise& __rhs) = delete; |
1542 | #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1543 | private: |
1544 | promise(const promise& __rhs); |
1545 | public: |
1546 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1547 | ~promise(); |
1548 | |
1549 | // assignment |
1550 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1551 | _LIBCPP_INLINE_VISIBILITY |
1552 | promise& operator=(promise&& __rhs) _NOEXCEPT |
1553 | { |
1554 | promise(std::move(__rhs)).swap(*this); |
1555 | return *this; |
1556 | } |
1557 | promise& operator=(const promise& __rhs) = delete; |
1558 | #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1559 | private: |
1560 | promise& operator=(const promise& __rhs); |
1561 | public: |
1562 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1563 | _LIBCPP_INLINE_VISIBILITY |
1564 | void swap(promise& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} |
1565 | |
1566 | // retrieving the result |
1567 | future<_Rp&> get_future(); |
1568 | |
1569 | // setting the result |
1570 | void set_value(_Rp& __r); |
1571 | void set_exception(exception_ptr __p); |
1572 | |
1573 | // setting the result with deferred notification |
1574 | void set_value_at_thread_exit(_Rp&); |
1575 | void set_exception_at_thread_exit(exception_ptr __p); |
1576 | }; |
1577 | |
1578 | template <class _Rp> |
1579 | promise<_Rp&>::promise() |
1580 | : __state_(new __assoc_state<_Rp&>) |
1581 | { |
1582 | } |
1583 | |
1584 | template <class _Rp> |
1585 | template <class _Alloc> |
1586 | promise<_Rp&>::promise(allocator_arg_t, const _Alloc& __a0) |
1587 | { |
1588 | typedef __assoc_state_alloc<_Rp&, _Alloc> _State; |
1589 | typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2; |
1590 | typedef __allocator_destructor<_A2> _D2; |
1591 | _A2 __a(__a0); |
1592 | unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1)); |
1593 | ::new(static_cast<void*>(_VSTD::addressof(*__hold.get()))) _State(__a0); |
1594 | __state_ = _VSTD::addressof(*__hold.release()); |
1595 | } |
1596 | |
1597 | template <class _Rp> |
1598 | promise<_Rp&>::~promise() |
1599 | { |
1600 | if (__state_) |
1601 | { |
1602 | if (!__state_->__has_value() && __state_->use_count() > 1) |
1603 | __state_->set_exception(make_exception_ptr( |
1604 | future_error(make_error_code(future_errc::broken_promise)) |
1605 | )); |
1606 | __state_->__release_shared(); |
1607 | } |
1608 | } |
1609 | |
1610 | template <class _Rp> |
1611 | future<_Rp&> |
1612 | promise<_Rp&>::get_future() |
1613 | { |
1614 | if (__state_ == nullptr) |
1615 | __throw_future_error(future_errc::no_state); |
1616 | return future<_Rp&>(__state_); |
1617 | } |
1618 | |
1619 | template <class _Rp> |
1620 | void |
1621 | promise<_Rp&>::set_value(_Rp& __r) |
1622 | { |
1623 | if (__state_ == nullptr) |
1624 | __throw_future_error(future_errc::no_state); |
1625 | __state_->set_value(__r); |
1626 | } |
1627 | |
1628 | template <class _Rp> |
1629 | void |
1630 | promise<_Rp&>::set_exception(exception_ptr __p) |
1631 | { |
1632 | _LIBCPP_ASSERT( __p != nullptr, "promise::set_exception: received nullptr" ); |
1633 | if (__state_ == nullptr) |
1634 | __throw_future_error(future_errc::no_state); |
1635 | __state_->set_exception(__p); |
1636 | } |
1637 | |
1638 | template <class _Rp> |
1639 | void |
1640 | promise<_Rp&>::set_value_at_thread_exit(_Rp& __r) |
1641 | { |
1642 | if (__state_ == nullptr) |
1643 | __throw_future_error(future_errc::no_state); |
1644 | __state_->set_value_at_thread_exit(__r); |
1645 | } |
1646 | |
1647 | template <class _Rp> |
1648 | void |
1649 | promise<_Rp&>::set_exception_at_thread_exit(exception_ptr __p) |
1650 | { |
1651 | _LIBCPP_ASSERT( __p != nullptr, "promise::set_exception_at_thread_exit: received nullptr" ); |
1652 | if (__state_ == nullptr) |
1653 | __throw_future_error(future_errc::no_state); |
1654 | __state_->set_exception_at_thread_exit(__p); |
1655 | } |
1656 | |
1657 | // promise<void> |
1658 | |
1659 | template <> |
1660 | class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE promise<void> |
1661 | { |
1662 | __assoc_sub_state* __state_; |
1663 | |
1664 | _LIBCPP_INLINE_VISIBILITY |
1665 | explicit promise(nullptr_t) _NOEXCEPT : __state_(nullptr) {} |
1666 | |
1667 | template <class> friend class packaged_task; |
1668 | |
1669 | public: |
1670 | promise(); |
1671 | template <class _Allocator> |
1672 | _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS |
1673 | promise(allocator_arg_t, const _Allocator& __a); |
1674 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1675 | _LIBCPP_INLINE_VISIBILITY |
1676 | promise(promise&& __rhs) _NOEXCEPT |
1677 | : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} |
1678 | promise(const promise& __rhs) = delete; |
1679 | #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1680 | private: |
1681 | promise(const promise& __rhs); |
1682 | public: |
1683 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1684 | ~promise(); |
1685 | |
1686 | // assignment |
1687 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1688 | _LIBCPP_INLINE_VISIBILITY |
1689 | promise& operator=(promise&& __rhs) _NOEXCEPT |
1690 | { |
1691 | promise(std::move(__rhs)).swap(*this); |
1692 | return *this; |
1693 | } |
1694 | promise& operator=(const promise& __rhs) = delete; |
1695 | #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1696 | private: |
1697 | promise& operator=(const promise& __rhs); |
1698 | public: |
1699 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
1700 | _LIBCPP_INLINE_VISIBILITY |
1701 | void swap(promise& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} |
1702 | |
1703 | // retrieving the result |
1704 | future<void> get_future(); |
1705 | |
1706 | // setting the result |
1707 | void set_value(); |
1708 | void set_exception(exception_ptr __p); |
1709 | |
1710 | // setting the result with deferred notification |
1711 | void set_value_at_thread_exit(); |
1712 | void set_exception_at_thread_exit(exception_ptr __p); |
1713 | }; |
1714 | |
1715 | template <class _Alloc> |
1716 | promise<void>::promise(allocator_arg_t, const _Alloc& __a0) |
1717 | { |
1718 | typedef __assoc_sub_state_alloc<_Alloc> _State; |
1719 | typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2; |
1720 | typedef __allocator_destructor<_A2> _D2; |
1721 | _A2 __a(__a0); |
1722 | unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1)); |
1723 | ::new(static_cast<void*>(_VSTD::addressof(*__hold.get()))) _State(__a0); |
1724 | __state_ = _VSTD::addressof(*__hold.release()); |
1725 | } |
1726 | |
1727 | template <class _Rp> |
1728 | inline _LIBCPP_INLINE_VISIBILITY |
1729 | void |
1730 | swap(promise<_Rp>& __x, promise<_Rp>& __y) _NOEXCEPT |
1731 | { |
1732 | __x.swap(__y); |
1733 | } |
1734 | |
1735 | template <class _Rp, class _Alloc> |
1736 | struct _LIBCPP_TEMPLATE_VIS uses_allocator<promise<_Rp>, _Alloc> |
1737 | : public true_type {}; |
1738 | |
1739 | #ifndef _LIBCPP_HAS_NO_VARIADICS |
1740 | |
1741 | // packaged_task |
1742 | |
1743 | template<class _Fp> class __packaged_task_base; |
1744 | |
1745 | template<class _Rp, class ..._ArgTypes> |
1746 | class _LIBCPP_AVAILABILITY_FUTURE __packaged_task_base<_Rp(_ArgTypes...)> |
1747 | { |
1748 | __packaged_task_base(const __packaged_task_base&); |
1749 | __packaged_task_base& operator=(const __packaged_task_base&); |
1750 | public: |
1751 | _LIBCPP_INLINE_VISIBILITY |
1752 | __packaged_task_base() {} |
1753 | _LIBCPP_INLINE_VISIBILITY |
1754 | virtual ~__packaged_task_base() {} |
1755 | virtual void __move_to(__packaged_task_base*) _NOEXCEPT = 0; |
1756 | virtual void destroy() = 0; |
1757 | virtual void destroy_deallocate() = 0; |
1758 | virtual _Rp operator()(_ArgTypes&& ...) = 0; |
1759 | }; |
1760 | |
1761 | template<class _FD, class _Alloc, class _FB> class __packaged_task_func; |
1762 | |
1763 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> |
1764 | class _LIBCPP_AVAILABILITY_FUTURE __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)> |
1765 | : public __packaged_task_base<_Rp(_ArgTypes...)> |
1766 | { |
1767 | __compressed_pair<_Fp, _Alloc> __f_; |
1768 | public: |
1769 | _LIBCPP_INLINE_VISIBILITY |
1770 | explicit __packaged_task_func(const _Fp& __f) : __f_(__f, __default_init_tag()) {} |
1771 | _LIBCPP_INLINE_VISIBILITY |
1772 | explicit __packaged_task_func(_Fp&& __f) : __f_(_VSTD::move(__f), __default_init_tag()) {} |
1773 | _LIBCPP_INLINE_VISIBILITY |
1774 | __packaged_task_func(const _Fp& __f, const _Alloc& __a) |
1775 | : __f_(__f, __a) {} |
1776 | _LIBCPP_INLINE_VISIBILITY |
1777 | __packaged_task_func(_Fp&& __f, const _Alloc& __a) |
1778 | : __f_(_VSTD::move(__f), __a) {} |
1779 | virtual void __move_to(__packaged_task_base<_Rp(_ArgTypes...)>*) _NOEXCEPT; |
1780 | virtual void destroy(); |
1781 | virtual void destroy_deallocate(); |
1782 | virtual _Rp operator()(_ArgTypes&& ... __args); |
1783 | }; |
1784 | |
1785 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> |
1786 | void |
1787 | __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__move_to( |
1788 | __packaged_task_base<_Rp(_ArgTypes...)>* __p) _NOEXCEPT |
1789 | { |
1790 | ::new (__p) __packaged_task_func(_VSTD::move(__f_.first()), _VSTD::move(__f_.second())); |
1791 | } |
1792 | |
1793 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> |
1794 | void |
1795 | __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy() |
1796 | { |
1797 | __f_.~__compressed_pair<_Fp, _Alloc>(); |
1798 | } |
1799 | |
1800 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> |
1801 | void |
1802 | __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate() |
1803 | { |
1804 | typedef typename __allocator_traits_rebind<_Alloc, __packaged_task_func>::type _Ap; |
1805 | typedef allocator_traits<_Ap> _ATraits; |
1806 | typedef pointer_traits<typename _ATraits::pointer> _PTraits; |
1807 | _Ap __a(__f_.second()); |
1808 | __f_.~__compressed_pair<_Fp, _Alloc>(); |
1809 | __a.deallocate(_PTraits::pointer_to(*this), 1); |
1810 | } |
1811 | |
1812 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> |
1813 | _Rp |
1814 | __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg) |
1815 | { |
1816 | return __invoke(__f_.first(), _VSTD::forward<_ArgTypes>(__arg)...); |
1817 | } |
1818 | |
1819 | template <class _Callable> class __packaged_task_function; |
1820 | |
1821 | template<class _Rp, class ..._ArgTypes> |
1822 | class _LIBCPP_AVAILABILITY_FUTURE __packaged_task_function<_Rp(_ArgTypes...)> |
1823 | { |
1824 | typedef __packaged_task_base<_Rp(_ArgTypes...)> __base; |
1825 | typename aligned_storage<3*sizeof(void*)>::type __buf_; |
1826 | __base* __f_; |
1827 | |
1828 | public: |
1829 | typedef _Rp result_type; |
1830 | |
1831 | // construct/copy/destroy: |
1832 | _LIBCPP_INLINE_VISIBILITY |
1833 | __packaged_task_function() _NOEXCEPT : __f_(nullptr) {} |
1834 | template<class _Fp> |
1835 | __packaged_task_function(_Fp&& __f); |
1836 | template<class _Fp, class _Alloc> |
1837 | __packaged_task_function(allocator_arg_t, const _Alloc& __a, _Fp&& __f); |
1838 | |
1839 | __packaged_task_function(__packaged_task_function&&) _NOEXCEPT; |
1840 | __packaged_task_function& operator=(__packaged_task_function&&) _NOEXCEPT; |
1841 | |
1842 | __packaged_task_function(const __packaged_task_function&) = delete; |
1843 | __packaged_task_function& operator=(const __packaged_task_function&) = delete; |
1844 | |
1845 | ~__packaged_task_function(); |
1846 | |
1847 | void swap(__packaged_task_function&) _NOEXCEPT; |
1848 | |
1849 | _LIBCPP_INLINE_VISIBILITY |
1850 | _Rp operator()(_ArgTypes...) const; |
1851 | }; |
1852 | |
1853 | template<class _Rp, class ..._ArgTypes> |
1854 | __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(__packaged_task_function&& __f) _NOEXCEPT |
1855 | { |
1856 | if (__f.__f_ == nullptr) |
1857 | __f_ = nullptr; |
1858 | else if (__f.__f_ == (__base*)&__f.__buf_) |
1859 | { |
1860 | __f_ = (__base*)&__buf_; |
1861 | __f.__f_->__move_to(__f_); |
1862 | } |
1863 | else |
1864 | { |
1865 | __f_ = __f.__f_; |
1866 | __f.__f_ = nullptr; |
1867 | } |
1868 | } |
1869 | |
1870 | template<class _Rp, class ..._ArgTypes> |
1871 | template <class _Fp> |
1872 | __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(_Fp&& __f) |
1873 | : __f_(nullptr) |
1874 | { |
1875 | typedef typename remove_reference<typename decay<_Fp>::type>::type _FR; |
1876 | typedef __packaged_task_func<_FR, allocator<_FR>, _Rp(_ArgTypes...)> _FF; |
1877 | if (sizeof(_FF) <= sizeof(__buf_)) |
1878 | { |
1879 | __f_ = (__base*)&__buf_; |
1880 | ::new (__f_) _FF(_VSTD::forward<_Fp>(__f)); |
1881 | } |
1882 | else |
1883 | { |
1884 | typedef allocator<_FF> _Ap; |
1885 | _Ap __a; |
1886 | typedef __allocator_destructor<_Ap> _Dp; |
1887 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); |
1888 | ::new (__hold.get()) _FF(_VSTD::forward<_Fp>(__f), allocator<_FR>(__a)); |
1889 | __f_ = __hold.release(); |
1890 | } |
1891 | } |
1892 | |
1893 | template<class _Rp, class ..._ArgTypes> |
1894 | template <class _Fp, class _Alloc> |
1895 | __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function( |
1896 | allocator_arg_t, const _Alloc& __a0, _Fp&& __f) |
1897 | : __f_(nullptr) |
1898 | { |
1899 | typedef typename remove_reference<typename decay<_Fp>::type>::type _FR; |
1900 | typedef __packaged_task_func<_FR, _Alloc, _Rp(_ArgTypes...)> _FF; |
1901 | if (sizeof(_FF) <= sizeof(__buf_)) |
1902 | { |
1903 | __f_ = (__base*)&__buf_; |
1904 | ::new (__f_) _FF(_VSTD::forward<_Fp>(__f)); |
1905 | } |
1906 | else |
1907 | { |
1908 | typedef typename __allocator_traits_rebind<_Alloc, _FF>::type _Ap; |
1909 | _Ap __a(__a0); |
1910 | typedef __allocator_destructor<_Ap> _Dp; |
1911 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); |
1912 | ::new (static_cast<void*>(_VSTD::addressof(*__hold.get()))) |
1913 | _FF(_VSTD::forward<_Fp>(__f), _Alloc(__a)); |
1914 | __f_ = _VSTD::addressof(*__hold.release()); |
1915 | } |
1916 | } |
1917 | |
1918 | template<class _Rp, class ..._ArgTypes> |
1919 | __packaged_task_function<_Rp(_ArgTypes...)>& |
1920 | __packaged_task_function<_Rp(_ArgTypes...)>::operator=(__packaged_task_function&& __f) _NOEXCEPT |
1921 | { |
1922 | if (__f_ == (__base*)&__buf_) |
1923 | __f_->destroy(); |
1924 | else if (__f_) |
1925 | __f_->destroy_deallocate(); |
1926 | __f_ = nullptr; |
1927 | if (__f.__f_ == nullptr) |
1928 | __f_ = nullptr; |
1929 | else if (__f.__f_ == (__base*)&__f.__buf_) |
1930 | { |
1931 | __f_ = (__base*)&__buf_; |
1932 | __f.__f_->__move_to(__f_); |
1933 | } |
1934 | else |
1935 | { |
1936 | __f_ = __f.__f_; |
1937 | __f.__f_ = nullptr; |
1938 | } |
1939 | return *this; |
1940 | } |
1941 | |
1942 | template<class _Rp, class ..._ArgTypes> |
1943 | __packaged_task_function<_Rp(_ArgTypes...)>::~__packaged_task_function() |
1944 | { |
1945 | if (__f_ == (__base*)&__buf_) |
1946 | __f_->destroy(); |
1947 | else if (__f_) |
1948 | __f_->destroy_deallocate(); |
1949 | } |
1950 | |
1951 | template<class _Rp, class ..._ArgTypes> |
1952 | void |
1953 | __packaged_task_function<_Rp(_ArgTypes...)>::swap(__packaged_task_function& __f) _NOEXCEPT |
1954 | { |
1955 | if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) |
1956 | { |
1957 | typename aligned_storage<sizeof(__buf_)>::type __tempbuf; |
1958 | __base* __t = (__base*)&__tempbuf; |
1959 | __f_->__move_to(__t); |
1960 | __f_->destroy(); |
1961 | __f_ = nullptr; |
1962 | __f.__f_->__move_to((__base*)&__buf_); |
1963 | __f.__f_->destroy(); |
1964 | __f.__f_ = nullptr; |
1965 | __f_ = (__base*)&__buf_; |
1966 | __t->__move_to((__base*)&__f.__buf_); |
1967 | __t->destroy(); |
1968 | __f.__f_ = (__base*)&__f.__buf_; |
1969 | } |
1970 | else if (__f_ == (__base*)&__buf_) |
1971 | { |
1972 | __f_->__move_to((__base*)&__f.__buf_); |
1973 | __f_->destroy(); |
1974 | __f_ = __f.__f_; |
1975 | __f.__f_ = (__base*)&__f.__buf_; |
1976 | } |
1977 | else if (__f.__f_ == (__base*)&__f.__buf_) |
1978 | { |
1979 | __f.__f_->__move_to((__base*)&__buf_); |
1980 | __f.__f_->destroy(); |
1981 | __f.__f_ = __f_; |
1982 | __f_ = (__base*)&__buf_; |
1983 | } |
1984 | else |
1985 | _VSTD::swap(__f_, __f.__f_); |
1986 | } |
1987 | |
1988 | template<class _Rp, class ..._ArgTypes> |
1989 | inline |
1990 | _Rp |
1991 | __packaged_task_function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const |
1992 | { |
1993 | return (*__f_)(_VSTD::forward<_ArgTypes>(__arg)...); |
1994 | } |
1995 | |
1996 | template<class _Rp, class ..._ArgTypes> |
1997 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE packaged_task<_Rp(_ArgTypes...)> |
1998 | { |
1999 | public: |
2000 | typedef _Rp result_type; // extension |
2001 | |
2002 | private: |
2003 | __packaged_task_function<result_type(_ArgTypes...)> __f_; |
2004 | promise<result_type> __p_; |
2005 | |
2006 | public: |
2007 | // construction and destruction |
2008 | _LIBCPP_INLINE_VISIBILITY |
2009 | packaged_task() _NOEXCEPT : __p_(nullptr) {} |
2010 | template <class _Fp, |
2011 | class = typename enable_if |
2012 | < |
2013 | !is_same< |
2014 | typename __uncvref<_Fp>::type, |
2015 | packaged_task |
2016 | >::value |
2017 | >::type |
2018 | > |
2019 | _LIBCPP_INLINE_VISIBILITY |
2020 | explicit packaged_task(_Fp&& __f) : __f_(_VSTD::forward<_Fp>(__f)) {} |
2021 | template <class _Fp, class _Allocator, |
2022 | class = typename enable_if |
2023 | < |
2024 | !is_same< |
2025 | typename __uncvref<_Fp>::type, |
2026 | packaged_task |
2027 | >::value |
2028 | >::type |
2029 | > |
2030 | _LIBCPP_INLINE_VISIBILITY |
2031 | packaged_task(allocator_arg_t, const _Allocator& __a, _Fp&& __f) |
2032 | : __f_(allocator_arg, __a, _VSTD::forward<_Fp>(__f)), |
2033 | __p_(allocator_arg, __a) {} |
2034 | // ~packaged_task() = default; |
2035 | |
2036 | // no copy |
2037 | packaged_task(const packaged_task&) = delete; |
2038 | packaged_task& operator=(const packaged_task&) = delete; |
2039 | |
2040 | // move support |
2041 | _LIBCPP_INLINE_VISIBILITY |
2042 | packaged_task(packaged_task&& __other) _NOEXCEPT |
2043 | : __f_(_VSTD::move(__other.__f_)), __p_(_VSTD::move(__other.__p_)) {} |
2044 | _LIBCPP_INLINE_VISIBILITY |
2045 | packaged_task& operator=(packaged_task&& __other) _NOEXCEPT |
2046 | { |
2047 | __f_ = _VSTD::move(__other.__f_); |
2048 | __p_ = _VSTD::move(__other.__p_); |
2049 | return *this; |
2050 | } |
2051 | _LIBCPP_INLINE_VISIBILITY |
2052 | void swap(packaged_task& __other) _NOEXCEPT |
2053 | { |
2054 | __f_.swap(__other.__f_); |
2055 | __p_.swap(__other.__p_); |
2056 | } |
2057 | |
2058 | _LIBCPP_INLINE_VISIBILITY |
2059 | bool valid() const _NOEXCEPT {return __p_.__state_ != nullptr;} |
2060 | |
2061 | // result retrieval |
2062 | _LIBCPP_INLINE_VISIBILITY |
2063 | future<result_type> get_future() {return __p_.get_future();} |
2064 | |
2065 | // execution |
2066 | void operator()(_ArgTypes... __args); |
2067 | void make_ready_at_thread_exit(_ArgTypes... __args); |
2068 | |
2069 | void reset(); |
2070 | }; |
2071 | |
2072 | template<class _Rp, class ..._ArgTypes> |
2073 | void |
2074 | packaged_task<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __args) |
2075 | { |
2076 | if (__p_.__state_ == nullptr) |
2077 | __throw_future_error(future_errc::no_state); |
2078 | if (__p_.__state_->__has_value()) |
2079 | __throw_future_error(future_errc::promise_already_satisfied); |
2080 | #ifndef _LIBCPP_NO_EXCEPTIONS |
2081 | try |
2082 | { |
2083 | #endif // _LIBCPP_NO_EXCEPTIONS |
2084 | __p_.set_value(__f_(_VSTD::forward<_ArgTypes>(__args)...)); |
2085 | #ifndef _LIBCPP_NO_EXCEPTIONS |
2086 | } |
2087 | catch (...) |
2088 | { |
2089 | __p_.set_exception(current_exception()); |
2090 | } |
2091 | #endif // _LIBCPP_NO_EXCEPTIONS |
2092 | } |
2093 | |
2094 | template<class _Rp, class ..._ArgTypes> |
2095 | void |
2096 | packaged_task<_Rp(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __args) |
2097 | { |
2098 | if (__p_.__state_ == nullptr) |
2099 | __throw_future_error(future_errc::no_state); |
2100 | if (__p_.__state_->__has_value()) |
2101 | __throw_future_error(future_errc::promise_already_satisfied); |
2102 | #ifndef _LIBCPP_NO_EXCEPTIONS |
2103 | try |
2104 | { |
2105 | #endif // _LIBCPP_NO_EXCEPTIONS |
2106 | __p_.set_value_at_thread_exit(__f_(_VSTD::forward<_ArgTypes>(__args)...)); |
2107 | #ifndef _LIBCPP_NO_EXCEPTIONS |
2108 | } |
2109 | catch (...) |
2110 | { |
2111 | __p_.set_exception_at_thread_exit(current_exception()); |
2112 | } |
2113 | #endif // _LIBCPP_NO_EXCEPTIONS |
2114 | } |
2115 | |
2116 | template<class _Rp, class ..._ArgTypes> |
2117 | void |
2118 | packaged_task<_Rp(_ArgTypes...)>::reset() |
2119 | { |
2120 | if (!valid()) |
2121 | __throw_future_error(future_errc::no_state); |
2122 | __p_ = promise<result_type>(); |
2123 | } |
2124 | |
2125 | template<class ..._ArgTypes> |
2126 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE packaged_task<void(_ArgTypes...)> |
2127 | { |
2128 | public: |
2129 | typedef void result_type; // extension |
2130 | |
2131 | private: |
2132 | __packaged_task_function<result_type(_ArgTypes...)> __f_; |
2133 | promise<result_type> __p_; |
2134 | |
2135 | public: |
2136 | // construction and destruction |
2137 | _LIBCPP_INLINE_VISIBILITY |
2138 | packaged_task() _NOEXCEPT : __p_(nullptr) {} |
2139 | template <class _Fp, |
2140 | class = typename enable_if |
2141 | < |
2142 | !is_same< |
2143 | typename __uncvref<_Fp>::type, |
2144 | packaged_task |
2145 | >::value |
2146 | >::type |
2147 | > |
2148 | _LIBCPP_INLINE_VISIBILITY |
2149 | explicit packaged_task(_Fp&& __f) : __f_(_VSTD::forward<_Fp>(__f)) {} |
2150 | template <class _Fp, class _Allocator, |
2151 | class = typename enable_if |
2152 | < |
2153 | !is_same< |
2154 | typename __uncvref<_Fp>::type, |
2155 | packaged_task |
2156 | >::value |
2157 | >::type |
2158 | > |
2159 | _LIBCPP_INLINE_VISIBILITY |
2160 | packaged_task(allocator_arg_t, const _Allocator& __a, _Fp&& __f) |
2161 | : __f_(allocator_arg, __a, _VSTD::forward<_Fp>(__f)), |
2162 | __p_(allocator_arg, __a) {} |
2163 | // ~packaged_task() = default; |
2164 | |
2165 | // no copy |
2166 | packaged_task(const packaged_task&) = delete; |
2167 | packaged_task& operator=(const packaged_task&) = delete; |
2168 | |
2169 | // move support |
2170 | _LIBCPP_INLINE_VISIBILITY |
2171 | packaged_task(packaged_task&& __other) _NOEXCEPT |
2172 | : __f_(_VSTD::move(__other.__f_)), __p_(_VSTD::move(__other.__p_)) {} |
2173 | _LIBCPP_INLINE_VISIBILITY |
2174 | packaged_task& operator=(packaged_task&& __other) _NOEXCEPT |
2175 | { |
2176 | __f_ = _VSTD::move(__other.__f_); |
2177 | __p_ = _VSTD::move(__other.__p_); |
2178 | return *this; |
2179 | } |
2180 | _LIBCPP_INLINE_VISIBILITY |
2181 | void swap(packaged_task& __other) _NOEXCEPT |
2182 | { |
2183 | __f_.swap(__other.__f_); |
2184 | __p_.swap(__other.__p_); |
2185 | } |
2186 | |
2187 | _LIBCPP_INLINE_VISIBILITY |
2188 | bool valid() const _NOEXCEPT {return __p_.__state_ != nullptr;} |
2189 | |
2190 | // result retrieval |
2191 | _LIBCPP_INLINE_VISIBILITY |
2192 | future<result_type> get_future() {return __p_.get_future();} |
2193 | |
2194 | // execution |
2195 | void operator()(_ArgTypes... __args); |
2196 | void make_ready_at_thread_exit(_ArgTypes... __args); |
2197 | |
2198 | void reset(); |
2199 | }; |
2200 | |
2201 | template<class ..._ArgTypes> |
2202 | void |
2203 | packaged_task<void(_ArgTypes...)>::operator()(_ArgTypes... __args) |
2204 | { |
2205 | if (__p_.__state_ == nullptr) |
2206 | __throw_future_error(future_errc::no_state); |
2207 | if (__p_.__state_->__has_value()) |
2208 | __throw_future_error(future_errc::promise_already_satisfied); |
2209 | #ifndef _LIBCPP_NO_EXCEPTIONS |
2210 | try |
2211 | { |
2212 | #endif // _LIBCPP_NO_EXCEPTIONS |
2213 | __f_(_VSTD::forward<_ArgTypes>(__args)...); |
2214 | __p_.set_value(); |
2215 | #ifndef _LIBCPP_NO_EXCEPTIONS |
2216 | } |
2217 | catch (...) |
2218 | { |
2219 | __p_.set_exception(current_exception()); |
2220 | } |
2221 | #endif // _LIBCPP_NO_EXCEPTIONS |
2222 | } |
2223 | |
2224 | template<class ..._ArgTypes> |
2225 | void |
2226 | packaged_task<void(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __args) |
2227 | { |
2228 | if (__p_.__state_ == nullptr) |
2229 | __throw_future_error(future_errc::no_state); |
2230 | if (__p_.__state_->__has_value()) |
2231 | __throw_future_error(future_errc::promise_already_satisfied); |
2232 | #ifndef _LIBCPP_NO_EXCEPTIONS |
2233 | try |
2234 | { |
2235 | #endif // _LIBCPP_NO_EXCEPTIONS |
2236 | __f_(_VSTD::forward<_ArgTypes>(__args)...); |
2237 | __p_.set_value_at_thread_exit(); |
2238 | #ifndef _LIBCPP_NO_EXCEPTIONS |
2239 | } |
2240 | catch (...) |
2241 | { |
2242 | __p_.set_exception_at_thread_exit(current_exception()); |
2243 | } |
2244 | #endif // _LIBCPP_NO_EXCEPTIONS |
2245 | } |
2246 | |
2247 | template<class ..._ArgTypes> |
2248 | void |
2249 | packaged_task<void(_ArgTypes...)>::reset() |
2250 | { |
2251 | if (!valid()) |
2252 | __throw_future_error(future_errc::no_state); |
2253 | __p_ = promise<result_type>(); |
2254 | } |
2255 | |
2256 | template <class _Callable> |
2257 | inline _LIBCPP_INLINE_VISIBILITY |
2258 | void |
2259 | swap(packaged_task<_Callable>& __x, packaged_task<_Callable>& __y) _NOEXCEPT |
2260 | { |
2261 | __x.swap(__y); |
2262 | } |
2263 | |
2264 | template <class _Callable, class _Alloc> |
2265 | struct _LIBCPP_TEMPLATE_VIS uses_allocator<packaged_task<_Callable>, _Alloc> |
2266 | : public true_type {}; |
2267 | |
2268 | template <class _Rp, class _Fp> |
2269 | _LIBCPP_INLINE_VISIBILITY future<_Rp> |
2270 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
2271 | __make_deferred_assoc_state(_Fp&& __f) |
2272 | #else |
2273 | __make_deferred_assoc_state(_Fp __f) |
2274 | #endif |
2275 | { |
2276 | unique_ptr<__deferred_assoc_state<_Rp, _Fp>, __release_shared_count> |
2277 | __h(new __deferred_assoc_state<_Rp, _Fp>(_VSTD::forward<_Fp>(__f))); |
2278 | return future<_Rp>(__h.get()); |
2279 | } |
2280 | |
2281 | template <class _Rp, class _Fp> |
2282 | _LIBCPP_INLINE_VISIBILITY future<_Rp> |
2283 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
2284 | __make_async_assoc_state(_Fp&& __f) |
2285 | #else |
2286 | __make_async_assoc_state(_Fp __f) |
2287 | #endif |
2288 | { |
2289 | unique_ptr<__async_assoc_state<_Rp, _Fp>, __release_shared_count> |
2290 | __h(new __async_assoc_state<_Rp, _Fp>(_VSTD::forward<_Fp>(__f))); |
2291 | _VSTD::thread(&__async_assoc_state<_Rp, _Fp>::__execute, __h.get()).detach(); |
2292 | return future<_Rp>(__h.get()); |
2293 | } |
2294 | |
2295 | template <class _Fp, class... _Args> |
2296 | class _LIBCPP_HIDDEN __async_func |
2297 | { |
2298 | tuple<_Fp, _Args...> __f_; |
2299 | |
2300 | public: |
2301 | typedef typename __invoke_of<_Fp, _Args...>::type _Rp; |
2302 | |
2303 | _LIBCPP_INLINE_VISIBILITY |
2304 | explicit __async_func(_Fp&& __f, _Args&&... __args) |
2305 | : __f_(_VSTD::move(__f), _VSTD::move(__args)...) {} |
2306 | |
2307 | _LIBCPP_INLINE_VISIBILITY |
2308 | __async_func(__async_func&& __f) : __f_(_VSTD::move(__f.__f_)) {} |
2309 | |
2310 | _Rp operator()() |
2311 | { |
2312 | typedef typename __make_tuple_indices<1+sizeof...(_Args), 1>::type _Index; |
2313 | return __execute(_Index()); |
2314 | } |
2315 | private: |
2316 | template <size_t ..._Indices> |
2317 | _Rp |
2318 | __execute(__tuple_indices<_Indices...>) |
2319 | { |
2320 | return __invoke(_VSTD::move(_VSTD::get<0>(__f_)), _VSTD::move(_VSTD::get<_Indices>(__f_))...); |
2321 | } |
2322 | }; |
2323 | |
2324 | inline _LIBCPP_INLINE_VISIBILITY bool __does_policy_contain(launch __policy, launch __value ) |
2325 | { return (int(__policy) & int(__value)) != 0; } |
2326 | |
2327 | template <class _Fp, class... _Args> |
2328 | _LIBCPP_NODISCARD_AFTER_CXX17 |
2329 | future<typename __invoke_of<typename decay<_Fp>::type, typename decay<_Args>::type...>::type> |
2330 | async(launch __policy, _Fp&& __f, _Args&&... __args) |
2331 | { |
2332 | typedef __async_func<typename decay<_Fp>::type, typename decay<_Args>::type...> _BF; |
2333 | typedef typename _BF::_Rp _Rp; |
2334 | |
2335 | #ifndef _LIBCPP_NO_EXCEPTIONS |
2336 | try |
2337 | { |
2338 | #endif |
2339 | if (__does_policy_contain(__policy, launch::async)) |
2340 | return _VSTD::__make_async_assoc_state<_Rp>(_BF(__decay_copy(_VSTD::forward<_Fp>(__f)), |
2341 | __decay_copy(_VSTD::forward<_Args>(__args))...)); |
2342 | #ifndef _LIBCPP_NO_EXCEPTIONS |
2343 | } |
2344 | catch ( ... ) { if (__policy == launch::async) throw ; } |
2345 | #endif |
2346 | |
2347 | if (__does_policy_contain(__policy, launch::deferred)) |
2348 | return _VSTD::__make_deferred_assoc_state<_Rp>(_BF(__decay_copy(_VSTD::forward<_Fp>(__f)), |
2349 | __decay_copy(_VSTD::forward<_Args>(__args))...)); |
2350 | return future<_Rp>{}; |
2351 | } |
2352 | |
2353 | template <class _Fp, class... _Args> |
2354 | _LIBCPP_NODISCARD_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY |
2355 | future<typename __invoke_of<typename decay<_Fp>::type, typename decay<_Args>::type...>::type> |
2356 | async(_Fp&& __f, _Args&&... __args) |
2357 | { |
2358 | return _VSTD::async(launch::any, _VSTD::forward<_Fp>(__f), |
2359 | _VSTD::forward<_Args>(__args)...); |
2360 | } |
2361 | |
2362 | #endif // _LIBCPP_HAS_NO_VARIADICS |
2363 | |
2364 | // shared_future |
2365 | |
2366 | template <class _Rp> |
2367 | class _LIBCPP_TEMPLATE_VIS shared_future |
2368 | { |
2369 | __assoc_state<_Rp>* __state_; |
2370 | |
2371 | public: |
2372 | _LIBCPP_INLINE_VISIBILITY |
2373 | shared_future() _NOEXCEPT : __state_(nullptr) {} |
2374 | _LIBCPP_INLINE_VISIBILITY |
2375 | shared_future(const shared_future& __rhs) _NOEXCEPT : __state_(__rhs.__state_) |
2376 | {if (__state_) __state_->__add_shared();} |
2377 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
2378 | _LIBCPP_INLINE_VISIBILITY |
2379 | shared_future(future<_Rp>&& __f) _NOEXCEPT : __state_(__f.__state_) |
2380 | {__f.__state_ = nullptr;} |
2381 | _LIBCPP_INLINE_VISIBILITY |
2382 | shared_future(shared_future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) |
2383 | {__rhs.__state_ = nullptr;} |
2384 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
2385 | ~shared_future(); |
2386 | shared_future& operator=(const shared_future& __rhs) _NOEXCEPT; |
2387 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
2388 | _LIBCPP_INLINE_VISIBILITY |
2389 | shared_future& operator=(shared_future&& __rhs) _NOEXCEPT |
2390 | { |
2391 | shared_future(std::move(__rhs)).swap(*this); |
2392 | return *this; |
2393 | } |
2394 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
2395 | |
2396 | // retrieving the value |
2397 | _LIBCPP_INLINE_VISIBILITY |
2398 | const _Rp& get() const {return __state_->copy();} |
2399 | |
2400 | _LIBCPP_INLINE_VISIBILITY |
2401 | void swap(shared_future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} |
2402 | |
2403 | // functions to check state |
2404 | _LIBCPP_INLINE_VISIBILITY |
2405 | bool valid() const _NOEXCEPT {return __state_ != nullptr;} |
2406 | |
2407 | _LIBCPP_INLINE_VISIBILITY |
2408 | void wait() const {__state_->wait();} |
2409 | template <class _Rep, class _Period> |
2410 | _LIBCPP_INLINE_VISIBILITY |
2411 | future_status |
2412 | wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const |
2413 | {return __state_->wait_for(__rel_time);} |
2414 | template <class _Clock, class _Duration> |
2415 | _LIBCPP_INLINE_VISIBILITY |
2416 | future_status |
2417 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const |
2418 | {return __state_->wait_until(__abs_time);} |
2419 | }; |
2420 | |
2421 | template <class _Rp> |
2422 | shared_future<_Rp>::~shared_future() |
2423 | { |
2424 | if (__state_) |
2425 | __state_->__release_shared(); |
2426 | } |
2427 | |
2428 | template <class _Rp> |
2429 | shared_future<_Rp>& |
2430 | shared_future<_Rp>::operator=(const shared_future& __rhs) _NOEXCEPT |
2431 | { |
2432 | if (__rhs.__state_) |
2433 | __rhs.__state_->__add_shared(); |
2434 | if (__state_) |
2435 | __state_->__release_shared(); |
2436 | __state_ = __rhs.__state_; |
2437 | return *this; |
2438 | } |
2439 | |
2440 | template <class _Rp> |
2441 | class _LIBCPP_TEMPLATE_VIS shared_future<_Rp&> |
2442 | { |
2443 | __assoc_state<_Rp&>* __state_; |
2444 | |
2445 | public: |
2446 | _LIBCPP_INLINE_VISIBILITY |
2447 | shared_future() _NOEXCEPT : __state_(nullptr) {} |
2448 | _LIBCPP_INLINE_VISIBILITY |
2449 | shared_future(const shared_future& __rhs) : __state_(__rhs.__state_) |
2450 | {if (__state_) __state_->__add_shared();} |
2451 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
2452 | _LIBCPP_INLINE_VISIBILITY |
2453 | shared_future(future<_Rp&>&& __f) _NOEXCEPT : __state_(__f.__state_) |
2454 | {__f.__state_ = nullptr;} |
2455 | _LIBCPP_INLINE_VISIBILITY |
2456 | shared_future(shared_future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) |
2457 | {__rhs.__state_ = nullptr;} |
2458 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
2459 | ~shared_future(); |
2460 | shared_future& operator=(const shared_future& __rhs); |
2461 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
2462 | _LIBCPP_INLINE_VISIBILITY |
2463 | shared_future& operator=(shared_future&& __rhs) _NOEXCEPT |
2464 | { |
2465 | shared_future(std::move(__rhs)).swap(*this); |
2466 | return *this; |
2467 | } |
2468 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
2469 | |
2470 | // retrieving the value |
2471 | _LIBCPP_INLINE_VISIBILITY |
2472 | _Rp& get() const {return __state_->copy();} |
2473 | |
2474 | _LIBCPP_INLINE_VISIBILITY |
2475 | void swap(shared_future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} |
2476 | |
2477 | // functions to check state |
2478 | _LIBCPP_INLINE_VISIBILITY |
2479 | bool valid() const _NOEXCEPT {return __state_ != nullptr;} |
2480 | |
2481 | _LIBCPP_INLINE_VISIBILITY |
2482 | void wait() const {__state_->wait();} |
2483 | template <class _Rep, class _Period> |
2484 | _LIBCPP_INLINE_VISIBILITY |
2485 | future_status |
2486 | wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const |
2487 | {return __state_->wait_for(__rel_time);} |
2488 | template <class _Clock, class _Duration> |
2489 | _LIBCPP_INLINE_VISIBILITY |
2490 | future_status |
2491 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const |
2492 | {return __state_->wait_until(__abs_time);} |
2493 | }; |
2494 | |
2495 | template <class _Rp> |
2496 | shared_future<_Rp&>::~shared_future() |
2497 | { |
2498 | if (__state_) |
2499 | __state_->__release_shared(); |
2500 | } |
2501 | |
2502 | template <class _Rp> |
2503 | shared_future<_Rp&>& |
2504 | shared_future<_Rp&>::operator=(const shared_future& __rhs) |
2505 | { |
2506 | if (__rhs.__state_) |
2507 | __rhs.__state_->__add_shared(); |
2508 | if (__state_) |
2509 | __state_->__release_shared(); |
2510 | __state_ = __rhs.__state_; |
2511 | return *this; |
2512 | } |
2513 | |
2514 | template <> |
2515 | class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE shared_future<void> |
2516 | { |
2517 | __assoc_sub_state* __state_; |
2518 | |
2519 | public: |
2520 | _LIBCPP_INLINE_VISIBILITY |
2521 | shared_future() _NOEXCEPT : __state_(nullptr) {} |
2522 | _LIBCPP_INLINE_VISIBILITY |
2523 | shared_future(const shared_future& __rhs) : __state_(__rhs.__state_) |
2524 | {if (__state_) __state_->__add_shared();} |
2525 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
2526 | _LIBCPP_INLINE_VISIBILITY |
2527 | shared_future(future<void>&& __f) _NOEXCEPT : __state_(__f.__state_) |
2528 | {__f.__state_ = nullptr;} |
2529 | _LIBCPP_INLINE_VISIBILITY |
2530 | shared_future(shared_future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) |
2531 | {__rhs.__state_ = nullptr;} |
2532 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
2533 | ~shared_future(); |
2534 | shared_future& operator=(const shared_future& __rhs); |
2535 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
2536 | _LIBCPP_INLINE_VISIBILITY |
2537 | shared_future& operator=(shared_future&& __rhs) _NOEXCEPT |
2538 | { |
2539 | shared_future(std::move(__rhs)).swap(*this); |
2540 | return *this; |
2541 | } |
2542 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
2543 | |
2544 | // retrieving the value |
2545 | _LIBCPP_INLINE_VISIBILITY |
2546 | void get() const {__state_->copy();} |
2547 | |
2548 | _LIBCPP_INLINE_VISIBILITY |
2549 | void swap(shared_future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} |
2550 | |
2551 | // functions to check state |
2552 | _LIBCPP_INLINE_VISIBILITY |
2553 | bool valid() const _NOEXCEPT {return __state_ != nullptr;} |
2554 | |
2555 | _LIBCPP_INLINE_VISIBILITY |
2556 | void wait() const {__state_->wait();} |
2557 | template <class _Rep, class _Period> |
2558 | _LIBCPP_INLINE_VISIBILITY |
2559 | future_status |
2560 | wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const |
2561 | {return __state_->wait_for(__rel_time);} |
2562 | template <class _Clock, class _Duration> |
2563 | _LIBCPP_INLINE_VISIBILITY |
2564 | future_status |
2565 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const |
2566 | {return __state_->wait_until(__abs_time);} |
2567 | }; |
2568 | |
2569 | template <class _Rp> |
2570 | inline _LIBCPP_INLINE_VISIBILITY |
2571 | void |
2572 | swap(shared_future<_Rp>& __x, shared_future<_Rp>& __y) _NOEXCEPT |
2573 | { |
2574 | __x.swap(__y); |
2575 | } |
2576 | |
2577 | template <class _Rp> |
2578 | inline |
2579 | shared_future<_Rp> |
2580 | future<_Rp>::share() _NOEXCEPT |
2581 | { |
2582 | return shared_future<_Rp>(_VSTD::move(*this)); |
2583 | } |
2584 | |
2585 | template <class _Rp> |
2586 | inline |
2587 | shared_future<_Rp&> |
2588 | future<_Rp&>::share() _NOEXCEPT |
2589 | { |
2590 | return shared_future<_Rp&>(_VSTD::move(*this)); |
2591 | } |
2592 | |
2593 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
2594 | |
2595 | inline |
2596 | shared_future<void> |
2597 | future<void>::share() _NOEXCEPT |
2598 | { |
2599 | return shared_future<void>(_VSTD::move(*this)); |
2600 | } |
2601 | |
2602 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
2603 | |
2604 | _LIBCPP_END_NAMESPACE_STD |
2605 | |
2606 | #endif // !_LIBCPP_HAS_NO_THREADS |
2607 | |
2608 | #endif // _LIBCPP_FUTURE |
2609 | |