1 | // -*- C++ -*- |
2 | //===----------------------------------------------------------------------===// |
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 : public logic_error { |
48 | public: |
49 | explicit future_error(future_errc e); // since C++17 |
50 | |
51 | const error_code& code() const noexcept; |
52 | const char* what() const noexcept; |
53 | |
54 | private: |
55 | error_code ec_; // exposition only |
56 | }; |
57 | |
58 | template <class R> |
59 | class promise |
60 | { |
61 | public: |
62 | promise(); |
63 | template <class Allocator> |
64 | promise(allocator_arg_t, const Allocator& a); |
65 | promise(promise&& rhs) noexcept; |
66 | promise(const promise& rhs) = delete; |
67 | ~promise(); |
68 | |
69 | // assignment |
70 | promise& operator=(promise&& rhs) noexcept; |
71 | promise& operator=(const promise& rhs) = delete; |
72 | void swap(promise& other) noexcept; |
73 | |
74 | // retrieving the result |
75 | future<R> get_future(); |
76 | |
77 | // setting the result |
78 | void set_value(const R& r); |
79 | void set_value(R&& r); |
80 | void set_exception(exception_ptr p); |
81 | |
82 | // setting the result with deferred notification |
83 | void set_value_at_thread_exit(const R& r); |
84 | void set_value_at_thread_exit(R&& r); |
85 | void set_exception_at_thread_exit(exception_ptr p); |
86 | }; |
87 | |
88 | template <class R> |
89 | class promise<R&> |
90 | { |
91 | public: |
92 | promise(); |
93 | template <class Allocator> |
94 | promise(allocator_arg_t, const Allocator& a); |
95 | promise(promise&& rhs) noexcept; |
96 | promise(const promise& rhs) = delete; |
97 | ~promise(); |
98 | |
99 | // assignment |
100 | promise& operator=(promise&& rhs) noexcept; |
101 | promise& operator=(const promise& rhs) = delete; |
102 | void swap(promise& other) noexcept; |
103 | |
104 | // retrieving the result |
105 | future<R&> get_future(); |
106 | |
107 | // setting the result |
108 | void set_value(R& r); |
109 | void set_exception(exception_ptr p); |
110 | |
111 | // setting the result with deferred notification |
112 | void set_value_at_thread_exit(R&); |
113 | void set_exception_at_thread_exit(exception_ptr p); |
114 | }; |
115 | |
116 | template <> |
117 | class promise<void> |
118 | { |
119 | public: |
120 | promise(); |
121 | template <class Allocator> |
122 | promise(allocator_arg_t, const Allocator& a); |
123 | promise(promise&& rhs) noexcept; |
124 | promise(const promise& rhs) = delete; |
125 | ~promise(); |
126 | |
127 | // assignment |
128 | promise& operator=(promise&& rhs) noexcept; |
129 | promise& operator=(const promise& rhs) = delete; |
130 | void swap(promise& other) noexcept; |
131 | |
132 | // retrieving the result |
133 | future<void> get_future(); |
134 | |
135 | // setting the result |
136 | void set_value(); |
137 | void set_exception(exception_ptr p); |
138 | |
139 | // setting the result with deferred notification |
140 | void set_value_at_thread_exit(); |
141 | void set_exception_at_thread_exit(exception_ptr p); |
142 | }; |
143 | |
144 | template <class R> void swap(promise<R>& x, promise<R>& y) noexcept; |
145 | |
146 | template <class R, class Alloc> |
147 | struct uses_allocator<promise<R>, Alloc> : public true_type {}; |
148 | |
149 | template <class R> |
150 | class future |
151 | { |
152 | public: |
153 | future() noexcept; |
154 | future(future&&) noexcept; |
155 | future(const future& rhs) = delete; |
156 | ~future(); |
157 | future& operator=(const future& rhs) = delete; |
158 | future& operator=(future&&) noexcept; |
159 | shared_future<R> share() noexcept; |
160 | |
161 | // retrieving the value |
162 | R get(); |
163 | |
164 | // functions to check state |
165 | bool valid() const noexcept; |
166 | |
167 | void wait() const; |
168 | template <class Rep, class Period> |
169 | future_status |
170 | wait_for(const chrono::duration<Rep, Period>& rel_time) const; |
171 | template <class Clock, class Duration> |
172 | future_status |
173 | wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; |
174 | }; |
175 | |
176 | template <class R> |
177 | class future<R&> |
178 | { |
179 | public: |
180 | future() noexcept; |
181 | future(future&&) noexcept; |
182 | future(const future& rhs) = delete; |
183 | ~future(); |
184 | future& operator=(const future& rhs) = delete; |
185 | future& operator=(future&&) noexcept; |
186 | shared_future<R&> share() noexcept; |
187 | |
188 | // retrieving the value |
189 | R& get(); |
190 | |
191 | // functions to check state |
192 | bool valid() const noexcept; |
193 | |
194 | void wait() const; |
195 | template <class Rep, class Period> |
196 | future_status |
197 | wait_for(const chrono::duration<Rep, Period>& rel_time) const; |
198 | template <class Clock, class Duration> |
199 | future_status |
200 | wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; |
201 | }; |
202 | |
203 | template <> |
204 | class future<void> |
205 | { |
206 | public: |
207 | future() noexcept; |
208 | future(future&&) noexcept; |
209 | future(const future& rhs) = delete; |
210 | ~future(); |
211 | future& operator=(const future& rhs) = delete; |
212 | future& operator=(future&&) noexcept; |
213 | shared_future<void> share() noexcept; |
214 | |
215 | // retrieving the value |
216 | void get(); |
217 | |
218 | // functions to check state |
219 | bool valid() const noexcept; |
220 | |
221 | void wait() const; |
222 | template <class Rep, class Period> |
223 | future_status |
224 | wait_for(const chrono::duration<Rep, Period>& rel_time) const; |
225 | template <class Clock, class Duration> |
226 | future_status |
227 | wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; |
228 | }; |
229 | |
230 | template <class R> |
231 | class shared_future |
232 | { |
233 | public: |
234 | shared_future() noexcept; |
235 | shared_future(const shared_future& rhs); |
236 | shared_future(future<R>&&) noexcept; |
237 | shared_future(shared_future&& rhs) noexcept; |
238 | ~shared_future(); |
239 | shared_future& operator=(const shared_future& rhs); |
240 | shared_future& operator=(shared_future&& rhs) noexcept; |
241 | |
242 | // retrieving the value |
243 | const R& get() const; |
244 | |
245 | // functions to check state |
246 | bool valid() const noexcept; |
247 | |
248 | void wait() const; |
249 | template <class Rep, class Period> |
250 | future_status |
251 | wait_for(const chrono::duration<Rep, Period>& rel_time) const; |
252 | template <class Clock, class Duration> |
253 | future_status |
254 | wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; |
255 | }; |
256 | |
257 | template <class R> |
258 | class shared_future<R&> |
259 | { |
260 | public: |
261 | shared_future() noexcept; |
262 | shared_future(const shared_future& rhs); |
263 | shared_future(future<R&>&&) noexcept; |
264 | shared_future(shared_future&& rhs) noexcept; |
265 | ~shared_future(); |
266 | shared_future& operator=(const shared_future& rhs); |
267 | shared_future& operator=(shared_future&& rhs) noexcept; |
268 | |
269 | // retrieving the value |
270 | R& get() const; |
271 | |
272 | // functions to check state |
273 | bool valid() const noexcept; |
274 | |
275 | void wait() const; |
276 | template <class Rep, class Period> |
277 | future_status |
278 | wait_for(const chrono::duration<Rep, Period>& rel_time) const; |
279 | template <class Clock, class Duration> |
280 | future_status |
281 | wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; |
282 | }; |
283 | |
284 | template <> |
285 | class shared_future<void> |
286 | { |
287 | public: |
288 | shared_future() noexcept; |
289 | shared_future(const shared_future& rhs); |
290 | shared_future(future<void>&&) noexcept; |
291 | shared_future(shared_future&& rhs) noexcept; |
292 | ~shared_future(); |
293 | shared_future& operator=(const shared_future& rhs); |
294 | shared_future& operator=(shared_future&& rhs) noexcept; |
295 | |
296 | // retrieving the value |
297 | void get() const; |
298 | |
299 | // functions to check state |
300 | bool valid() const noexcept; |
301 | |
302 | void wait() const; |
303 | template <class Rep, class Period> |
304 | future_status |
305 | wait_for(const chrono::duration<Rep, Period>& rel_time) const; |
306 | template <class Clock, class Duration> |
307 | future_status |
308 | wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; |
309 | }; |
310 | |
311 | template <class F, class... Args> |
312 | future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type> |
313 | async(F&& f, Args&&... args); |
314 | |
315 | template <class F, class... Args> |
316 | future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type> |
317 | async(launch policy, F&& f, Args&&... args); |
318 | |
319 | template <class> class packaged_task; // undefined |
320 | |
321 | template <class R, class... ArgTypes> |
322 | class packaged_task<R(ArgTypes...)> |
323 | { |
324 | public: |
325 | typedef R result_type; // extension |
326 | |
327 | // construction and destruction |
328 | packaged_task() noexcept; |
329 | template <class F> |
330 | explicit packaged_task(F&& f); |
331 | template <class F, class Allocator> |
332 | packaged_task(allocator_arg_t, const Allocator& a, F&& f); // removed in C++17 |
333 | ~packaged_task(); |
334 | |
335 | // no copy |
336 | packaged_task(const packaged_task&) = delete; |
337 | packaged_task& operator=(const packaged_task&) = delete; |
338 | |
339 | // move support |
340 | packaged_task(packaged_task&& other) noexcept; |
341 | packaged_task& operator=(packaged_task&& other) noexcept; |
342 | void swap(packaged_task& other) noexcept; |
343 | |
344 | bool valid() const noexcept; |
345 | |
346 | // result retrieval |
347 | future<R> get_future(); |
348 | |
349 | // execution |
350 | void operator()(ArgTypes... ); |
351 | void make_ready_at_thread_exit(ArgTypes...); |
352 | |
353 | void reset(); |
354 | }; |
355 | |
356 | template <class R> |
357 | void swap(packaged_task<R(ArgTypes...)&, packaged_task<R(ArgTypes...)>&) noexcept; |
358 | |
359 | template <class R, class Alloc> struct uses_allocator<packaged_task<R>, Alloc>; // removed in C++17 |
360 | |
361 | } // std |
362 | |
363 | */ |
364 | |
365 | #if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) |
366 | # include <__cxx03/future> |
367 | #else |
368 | # include <__config> |
369 | |
370 | # if _LIBCPP_HAS_THREADS |
371 | |
372 | # include <__assert> |
373 | # include <__chrono/duration.h> |
374 | # include <__chrono/steady_clock.h> |
375 | # include <__chrono/time_point.h> |
376 | # include <__condition_variable/condition_variable.h> |
377 | # include <__cstddef/nullptr_t.h> |
378 | # include <__exception/exception_ptr.h> |
379 | # include <__memory/addressof.h> |
380 | # include <__memory/allocator.h> |
381 | # include <__memory/allocator_arg_t.h> |
382 | # include <__memory/allocator_destructor.h> |
383 | # include <__memory/allocator_traits.h> |
384 | # include <__memory/compressed_pair.h> |
385 | # include <__memory/pointer_traits.h> |
386 | # include <__memory/shared_count.h> |
387 | # include <__memory/unique_ptr.h> |
388 | # include <__memory/uses_allocator.h> |
389 | # include <__mutex/lock_guard.h> |
390 | # include <__mutex/mutex.h> |
391 | # include <__mutex/unique_lock.h> |
392 | # include <__system_error/error_category.h> |
393 | # include <__system_error/error_code.h> |
394 | # include <__system_error/error_condition.h> |
395 | # include <__thread/thread.h> |
396 | # include <__type_traits/add_lvalue_reference.h> |
397 | # include <__type_traits/aligned_storage.h> |
398 | # include <__type_traits/conditional.h> |
399 | # include <__type_traits/decay.h> |
400 | # include <__type_traits/enable_if.h> |
401 | # include <__type_traits/invoke.h> |
402 | # include <__type_traits/is_same.h> |
403 | # include <__type_traits/remove_cvref.h> |
404 | # include <__type_traits/remove_reference.h> |
405 | # include <__type_traits/strip_signature.h> |
406 | # include <__type_traits/underlying_type.h> |
407 | # include <__utility/auto_cast.h> |
408 | # include <__utility/forward.h> |
409 | # include <__utility/move.h> |
410 | # include <__utility/swap.h> |
411 | # include <stdexcept> |
412 | # include <tuple> |
413 | # include <version> |
414 | |
415 | # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
416 | # pragma GCC system_header |
417 | # endif |
418 | |
419 | _LIBCPP_PUSH_MACROS |
420 | # include <__undef_macros> |
421 | |
422 | _LIBCPP_BEGIN_NAMESPACE_STD |
423 | |
424 | // enum class future_errc |
425 | _LIBCPP_DECLARE_STRONG_ENUM(future_errc){ |
426 | future_already_retrieved = 1, promise_already_satisfied, no_state, broken_promise}; |
427 | _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(future_errc) |
428 | |
429 | template <> |
430 | struct is_error_code_enum<future_errc> : public true_type {}; |
431 | |
432 | # ifdef _LIBCPP_CXX03_LANG |
433 | template <> |
434 | struct is_error_code_enum<future_errc::__lx> : public true_type {}; |
435 | # endif |
436 | |
437 | // enum class launch |
438 | _LIBCPP_DECLARE_STRONG_ENUM(launch){async = 1, deferred = 2, any = async | deferred}; |
439 | _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(launch) |
440 | |
441 | # ifndef _LIBCPP_CXX03_LANG |
442 | |
443 | using __launch_underlying_type _LIBCPP_NODEBUG = __underlying_type_t<launch>; |
444 | |
445 | inline _LIBCPP_HIDE_FROM_ABI constexpr launch operator&(launch __x, launch __y) { |
446 | return static_cast<launch>(static_cast<__launch_underlying_type>(__x) & static_cast<__launch_underlying_type>(__y)); |
447 | } |
448 | |
449 | inline _LIBCPP_HIDE_FROM_ABI constexpr launch operator|(launch __x, launch __y) { |
450 | return static_cast<launch>(static_cast<__launch_underlying_type>(__x) | static_cast<__launch_underlying_type>(__y)); |
451 | } |
452 | |
453 | inline _LIBCPP_HIDE_FROM_ABI constexpr launch operator^(launch __x, launch __y) { |
454 | return static_cast<launch>(static_cast<__launch_underlying_type>(__x) ^ static_cast<__launch_underlying_type>(__y)); |
455 | } |
456 | |
457 | inline _LIBCPP_HIDE_FROM_ABI constexpr launch operator~(launch __x) { |
458 | return static_cast<launch>(~static_cast<__launch_underlying_type>(__x) & 3); |
459 | } |
460 | |
461 | inline _LIBCPP_HIDE_FROM_ABI launch& operator&=(launch& __x, launch __y) { |
462 | __x = __x & __y; |
463 | return __x; |
464 | } |
465 | |
466 | inline _LIBCPP_HIDE_FROM_ABI launch& operator|=(launch& __x, launch __y) { |
467 | __x = __x | __y; |
468 | return __x; |
469 | } |
470 | |
471 | inline _LIBCPP_HIDE_FROM_ABI launch& operator^=(launch& __x, launch __y) { |
472 | __x = __x ^ __y; |
473 | return __x; |
474 | } |
475 | |
476 | # endif // !_LIBCPP_CXX03_LANG |
477 | |
478 | // enum class future_status |
479 | _LIBCPP_DECLARE_STRONG_ENUM(future_status){ready, timeout, deferred}; |
480 | _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(future_status) |
481 | |
482 | _LIBCPP_EXPORTED_FROM_ABI const error_category& future_category() _NOEXCEPT; |
483 | |
484 | inline _LIBCPP_HIDE_FROM_ABI error_code make_error_code(future_errc __e) _NOEXCEPT { |
485 | return error_code(static_cast<int>(__e), future_category()); |
486 | } |
487 | |
488 | inline _LIBCPP_HIDE_FROM_ABI error_condition make_error_condition(future_errc __e) _NOEXCEPT { |
489 | return error_condition(static_cast<int>(__e), future_category()); |
490 | } |
491 | |
492 | [[__noreturn__]] inline _LIBCPP_HIDE_FROM_ABI void __throw_future_error(future_errc __ev); |
493 | |
494 | class _LIBCPP_EXPORTED_FROM_ABI future_error : public logic_error { |
495 | error_code __ec_; |
496 | |
497 | future_error(error_code); |
498 | friend void __throw_future_error(future_errc); |
499 | template <class> |
500 | friend class promise; |
501 | |
502 | public: |
503 | # if _LIBCPP_STD_VER >= 17 |
504 | _LIBCPP_HIDE_FROM_ABI explicit future_error(future_errc __ec) : future_error(std::make_error_code(e: __ec)) {} |
505 | # endif |
506 | |
507 | _LIBCPP_HIDE_FROM_ABI const error_code& code() const _NOEXCEPT { return __ec_; } |
508 | |
509 | _LIBCPP_HIDE_FROM_ABI future_error(const future_error&) _NOEXCEPT = default; |
510 | ~future_error() _NOEXCEPT override; |
511 | }; |
512 | |
513 | // Declared above std::future_error |
514 | void __throw_future_error(future_errc __ev) { |
515 | # if _LIBCPP_HAS_EXCEPTIONS |
516 | throw future_error(make_error_code(e: __ev)); |
517 | # else |
518 | (void)__ev; |
519 | _LIBCPP_VERBOSE_ABORT("future_error was thrown in -fno-exceptions mode" ); |
520 | # endif |
521 | } |
522 | |
523 | class _LIBCPP_EXPORTED_FROM_ABI __assoc_sub_state : public __shared_count { |
524 | protected: |
525 | exception_ptr __exception_; |
526 | mutable mutex __mut_; |
527 | mutable condition_variable __cv_; |
528 | unsigned __state_; |
529 | |
530 | void __on_zero_shared() _NOEXCEPT override; |
531 | void __sub_wait(unique_lock<mutex>& __lk); |
532 | |
533 | public: |
534 | enum { __constructed = 1, __future_attached = 2, ready = 4, deferred = 8 }; |
535 | |
536 | _LIBCPP_HIDE_FROM_ABI __assoc_sub_state() : __state_(0) {} |
537 | |
538 | _LIBCPP_HIDE_FROM_ABI bool __has_value() const { return (__state_ & __constructed) || (__exception_ != nullptr); } |
539 | |
540 | _LIBCPP_HIDE_FROM_ABI void __attach_future() { |
541 | lock_guard<mutex> __lk(__mut_); |
542 | bool __has_future_attached = (__state_ & __future_attached) != 0; |
543 | if (__has_future_attached) |
544 | std::__throw_future_error(ev: future_errc::future_already_retrieved); |
545 | this->__add_shared(); |
546 | __state_ |= __future_attached; |
547 | } |
548 | |
549 | _LIBCPP_HIDE_FROM_ABI void __set_deferred() { __state_ |= deferred; } |
550 | |
551 | void __make_ready(); |
552 | _LIBCPP_HIDE_FROM_ABI bool __is_ready() const { return (__state_ & ready) != 0; } |
553 | |
554 | void set_value(); |
555 | void set_value_at_thread_exit(); |
556 | |
557 | void set_exception(exception_ptr __p); |
558 | void set_exception_at_thread_exit(exception_ptr __p); |
559 | |
560 | void copy(); |
561 | |
562 | void wait(); |
563 | template <class _Rep, class _Period> |
564 | future_status _LIBCPP_HIDE_FROM_ABI wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const; |
565 | template <class _Clock, class _Duration> |
566 | _LIBCPP_HIDE_FROM_ABI future_status wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const { |
567 | unique_lock<mutex> __lk(__mut_); |
568 | if (__state_ & deferred) |
569 | return future_status::deferred; |
570 | while (!(__state_ & ready) && _Clock::now() < __abs_time) |
571 | __cv_.wait_until(__lk, __abs_time); |
572 | if (__state_ & ready) |
573 | return future_status::ready; |
574 | return future_status::timeout; |
575 | } |
576 | |
577 | virtual void __execute(); |
578 | }; |
579 | |
580 | template <class _Rep, class _Period> |
581 | inline future_status __assoc_sub_state::wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const { |
582 | return wait_until(chrono::steady_clock::now() + __rel_time); |
583 | } |
584 | |
585 | template <class _Rp> |
586 | class _LIBCPP_HIDDEN __assoc_state : public __assoc_sub_state { |
587 | typedef __assoc_sub_state base; |
588 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH |
589 | typedef typename aligned_storage<sizeof(_Rp), _LIBCPP_ALIGNOF(_Rp)>::type _Up; |
590 | _LIBCPP_SUPPRESS_DEPRECATED_POP |
591 | |
592 | protected: |
593 | _Up __value_; |
594 | |
595 | _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override; |
596 | |
597 | public: |
598 | template <class _Arg> |
599 | _LIBCPP_HIDE_FROM_ABI void set_value(_Arg&& __arg); |
600 | |
601 | template <class _Arg> |
602 | _LIBCPP_HIDE_FROM_ABI void set_value_at_thread_exit(_Arg&& __arg); |
603 | |
604 | _LIBCPP_HIDE_FROM_ABI _Rp move(); |
605 | _LIBCPP_HIDE_FROM_ABI _Rp& copy(); |
606 | }; |
607 | |
608 | template <class _Rp> |
609 | void __assoc_state<_Rp>::__on_zero_shared() _NOEXCEPT { |
610 | if (this->__state_ & base::__constructed) |
611 | reinterpret_cast<_Rp*>(std::addressof(__value_))->~_Rp(); |
612 | delete this; |
613 | } |
614 | |
615 | template <class _Rp> |
616 | template <class _Arg> |
617 | void __assoc_state<_Rp>::set_value(_Arg&& __arg) { |
618 | unique_lock<mutex> __lk(this->__mut_); |
619 | if (this->__has_value()) |
620 | std::__throw_future_error(ev: future_errc::promise_already_satisfied); |
621 | ::new ((void*)std::addressof(__value_)) _Rp(std::forward<_Arg>(__arg)); |
622 | this->__state_ |= base::__constructed | base::ready; |
623 | __cv_.notify_all(); |
624 | } |
625 | |
626 | template <class _Rp> |
627 | template <class _Arg> |
628 | void __assoc_state<_Rp>::set_value_at_thread_exit(_Arg&& __arg) { |
629 | unique_lock<mutex> __lk(this->__mut_); |
630 | if (this->__has_value()) |
631 | std::__throw_future_error(ev: future_errc::promise_already_satisfied); |
632 | ::new ((void*)std::addressof(__value_)) _Rp(std::forward<_Arg>(__arg)); |
633 | this->__state_ |= base::__constructed; |
634 | __thread_local_data()->__make_ready_at_thread_exit(this); |
635 | } |
636 | |
637 | template <class _Rp> |
638 | _Rp __assoc_state<_Rp>::move() { |
639 | unique_lock<mutex> __lk(this->__mut_); |
640 | this->__sub_wait(__lk); |
641 | if (this->__exception_ != nullptr) |
642 | std::rethrow_exception(this->__exception_); |
643 | return std::move(*reinterpret_cast<_Rp*>(std::addressof(__value_))); |
644 | } |
645 | |
646 | template <class _Rp> |
647 | _Rp& __assoc_state<_Rp>::copy() { |
648 | unique_lock<mutex> __lk(this->__mut_); |
649 | this->__sub_wait(__lk); |
650 | if (this->__exception_ != nullptr) |
651 | std::rethrow_exception(this->__exception_); |
652 | return *reinterpret_cast<_Rp*>(std::addressof(__value_)); |
653 | } |
654 | |
655 | template <class _Rp> |
656 | class __assoc_state<_Rp&> : public __assoc_sub_state { |
657 | typedef __assoc_sub_state base; |
658 | typedef _Rp* _Up; |
659 | |
660 | protected: |
661 | _Up __value_; |
662 | |
663 | _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override; |
664 | |
665 | public: |
666 | _LIBCPP_HIDE_FROM_ABI void set_value(_Rp& __arg); |
667 | _LIBCPP_HIDE_FROM_ABI void set_value_at_thread_exit(_Rp& __arg); |
668 | |
669 | _LIBCPP_HIDE_FROM_ABI _Rp& copy(); |
670 | }; |
671 | |
672 | template <class _Rp> |
673 | void __assoc_state<_Rp&>::__on_zero_shared() _NOEXCEPT { |
674 | delete this; |
675 | } |
676 | |
677 | template <class _Rp> |
678 | void __assoc_state<_Rp&>::set_value(_Rp& __arg) { |
679 | unique_lock<mutex> __lk(this->__mut_); |
680 | if (this->__has_value()) |
681 | std::__throw_future_error(ev: future_errc::promise_already_satisfied); |
682 | __value_ = std::addressof(__arg); |
683 | this->__state_ |= base::__constructed | base::ready; |
684 | __cv_.notify_all(); |
685 | } |
686 | |
687 | template <class _Rp> |
688 | void __assoc_state<_Rp&>::set_value_at_thread_exit(_Rp& __arg) { |
689 | unique_lock<mutex> __lk(this->__mut_); |
690 | if (this->__has_value()) |
691 | std::__throw_future_error(ev: future_errc::promise_already_satisfied); |
692 | __value_ = std::addressof(__arg); |
693 | this->__state_ |= base::__constructed; |
694 | __thread_local_data()->__make_ready_at_thread_exit(this); |
695 | } |
696 | |
697 | template <class _Rp> |
698 | _Rp& __assoc_state<_Rp&>::copy() { |
699 | unique_lock<mutex> __lk(this->__mut_); |
700 | this->__sub_wait(__lk); |
701 | if (this->__exception_ != nullptr) |
702 | std::rethrow_exception(this->__exception_); |
703 | return *__value_; |
704 | } |
705 | |
706 | template <class _Rp, class _Alloc> |
707 | class __assoc_state_alloc : public __assoc_state<_Rp> { |
708 | typedef __assoc_state<_Rp> base; |
709 | _Alloc __alloc_; |
710 | |
711 | _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __on_zero_shared() _NOEXCEPT; |
712 | |
713 | public: |
714 | _LIBCPP_HIDE_FROM_ABI explicit __assoc_state_alloc(const _Alloc& __a) : __alloc_(__a) {} |
715 | }; |
716 | |
717 | template <class _Rp, class _Alloc> |
718 | void __assoc_state_alloc<_Rp, _Alloc>::__on_zero_shared() _NOEXCEPT { |
719 | if (this->__state_ & base::__constructed) |
720 | reinterpret_cast<_Rp*>(std::addressof(this->__value_))->~_Rp(); |
721 | typedef typename __allocator_traits_rebind<_Alloc, __assoc_state_alloc>::type _Al; |
722 | typedef allocator_traits<_Al> _ATraits; |
723 | typedef pointer_traits<typename _ATraits::pointer> _PTraits; |
724 | _Al __a(__alloc_); |
725 | this->~__assoc_state_alloc(); |
726 | __a.deallocate(_PTraits::pointer_to(*this), 1); |
727 | } |
728 | |
729 | template <class _Rp, class _Alloc> |
730 | class __assoc_state_alloc<_Rp&, _Alloc> : public __assoc_state<_Rp&> { |
731 | typedef __assoc_state<_Rp&> base; |
732 | _Alloc __alloc_; |
733 | |
734 | _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __on_zero_shared() _NOEXCEPT; |
735 | |
736 | public: |
737 | _LIBCPP_HIDE_FROM_ABI explicit __assoc_state_alloc(const _Alloc& __a) : __alloc_(__a) {} |
738 | }; |
739 | |
740 | template <class _Rp, class _Alloc> |
741 | void __assoc_state_alloc<_Rp&, _Alloc>::__on_zero_shared() _NOEXCEPT { |
742 | typedef typename __allocator_traits_rebind<_Alloc, __assoc_state_alloc>::type _Al; |
743 | typedef allocator_traits<_Al> _ATraits; |
744 | typedef pointer_traits<typename _ATraits::pointer> _PTraits; |
745 | _Al __a(__alloc_); |
746 | this->~__assoc_state_alloc(); |
747 | __a.deallocate(_PTraits::pointer_to(*this), 1); |
748 | } |
749 | |
750 | template <class _Alloc> |
751 | class __assoc_sub_state_alloc : public __assoc_sub_state { |
752 | typedef __assoc_sub_state base; |
753 | _Alloc __alloc_; |
754 | |
755 | _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override; |
756 | |
757 | public: |
758 | _LIBCPP_HIDE_FROM_ABI explicit __assoc_sub_state_alloc(const _Alloc& __a) : __alloc_(__a) {} |
759 | }; |
760 | |
761 | template <class _Alloc> |
762 | void __assoc_sub_state_alloc<_Alloc>::__on_zero_shared() _NOEXCEPT { |
763 | typedef typename __allocator_traits_rebind<_Alloc, __assoc_sub_state_alloc>::type _Al; |
764 | typedef allocator_traits<_Al> _ATraits; |
765 | typedef pointer_traits<typename _ATraits::pointer> _PTraits; |
766 | _Al __a(__alloc_); |
767 | this->~__assoc_sub_state_alloc(); |
768 | __a.deallocate(_PTraits::pointer_to(*this), 1); |
769 | } |
770 | |
771 | template <class _Rp, class _Fp> |
772 | class __deferred_assoc_state : public __assoc_state<_Rp> { |
773 | typedef __assoc_state<_Rp> base; |
774 | |
775 | _Fp __func_; |
776 | |
777 | public: |
778 | _LIBCPP_HIDE_FROM_ABI explicit __deferred_assoc_state(_Fp&& __f); |
779 | |
780 | _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __execute(); |
781 | }; |
782 | |
783 | template <class _Rp, class _Fp> |
784 | inline __deferred_assoc_state<_Rp, _Fp>::__deferred_assoc_state(_Fp&& __f) : __func_(std::forward<_Fp>(__f)) { |
785 | this->__set_deferred(); |
786 | } |
787 | |
788 | template <class _Rp, class _Fp> |
789 | void __deferred_assoc_state<_Rp, _Fp>::__execute() { |
790 | # if _LIBCPP_HAS_EXCEPTIONS |
791 | try { |
792 | # endif // _LIBCPP_HAS_EXCEPTIONS |
793 | this->set_value(__func_()); |
794 | # if _LIBCPP_HAS_EXCEPTIONS |
795 | } catch (...) { |
796 | this->set_exception(current_exception()); |
797 | } |
798 | # endif // _LIBCPP_HAS_EXCEPTIONS |
799 | } |
800 | |
801 | template <class _Fp> |
802 | class __deferred_assoc_state<void, _Fp> : public __assoc_sub_state { |
803 | typedef __assoc_sub_state base; |
804 | |
805 | _Fp __func_; |
806 | |
807 | public: |
808 | _LIBCPP_HIDE_FROM_ABI explicit __deferred_assoc_state(_Fp&& __f); |
809 | |
810 | _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __execute() override; |
811 | }; |
812 | |
813 | template <class _Fp> |
814 | inline __deferred_assoc_state<void, _Fp>::__deferred_assoc_state(_Fp&& __f) : __func_(std::forward<_Fp>(__f)) { |
815 | this->__set_deferred(); |
816 | } |
817 | |
818 | template <class _Fp> |
819 | void __deferred_assoc_state<void, _Fp>::__execute() { |
820 | # if _LIBCPP_HAS_EXCEPTIONS |
821 | try { |
822 | # endif // _LIBCPP_HAS_EXCEPTIONS |
823 | __func_(); |
824 | this->set_value(); |
825 | # if _LIBCPP_HAS_EXCEPTIONS |
826 | } catch (...) { |
827 | this->set_exception(current_exception()); |
828 | } |
829 | # endif // _LIBCPP_HAS_EXCEPTIONS |
830 | } |
831 | |
832 | template <class _Rp, class _Fp> |
833 | class __async_assoc_state : public __assoc_state<_Rp> { |
834 | typedef __assoc_state<_Rp> base; |
835 | |
836 | _Fp __func_; |
837 | |
838 | _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __on_zero_shared() _NOEXCEPT; |
839 | |
840 | public: |
841 | _LIBCPP_HIDE_FROM_ABI explicit __async_assoc_state(_Fp&& __f); |
842 | |
843 | _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __execute(); |
844 | }; |
845 | |
846 | template <class _Rp, class _Fp> |
847 | inline __async_assoc_state<_Rp, _Fp>::__async_assoc_state(_Fp&& __f) : __func_(std::forward<_Fp>(__f)) {} |
848 | |
849 | template <class _Rp, class _Fp> |
850 | void __async_assoc_state<_Rp, _Fp>::__execute() { |
851 | # if _LIBCPP_HAS_EXCEPTIONS |
852 | try { |
853 | # endif // _LIBCPP_HAS_EXCEPTIONS |
854 | this->set_value(__func_()); |
855 | # if _LIBCPP_HAS_EXCEPTIONS |
856 | } catch (...) { |
857 | this->set_exception(current_exception()); |
858 | } |
859 | # endif // _LIBCPP_HAS_EXCEPTIONS |
860 | } |
861 | |
862 | template <class _Rp, class _Fp> |
863 | void __async_assoc_state<_Rp, _Fp>::__on_zero_shared() _NOEXCEPT { |
864 | this->wait(); |
865 | base::__on_zero_shared(); |
866 | } |
867 | |
868 | template <class _Fp> |
869 | class __async_assoc_state<void, _Fp> : public __assoc_sub_state { |
870 | typedef __assoc_sub_state base; |
871 | |
872 | _Fp __func_; |
873 | |
874 | _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override; |
875 | |
876 | public: |
877 | _LIBCPP_HIDE_FROM_ABI explicit __async_assoc_state(_Fp&& __f); |
878 | |
879 | _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __execute() override; |
880 | }; |
881 | |
882 | template <class _Fp> |
883 | inline __async_assoc_state<void, _Fp>::__async_assoc_state(_Fp&& __f) : __func_(std::forward<_Fp>(__f)) {} |
884 | |
885 | template <class _Fp> |
886 | void __async_assoc_state<void, _Fp>::__execute() { |
887 | # if _LIBCPP_HAS_EXCEPTIONS |
888 | try { |
889 | # endif // _LIBCPP_HAS_EXCEPTIONS |
890 | __func_(); |
891 | this->set_value(); |
892 | # if _LIBCPP_HAS_EXCEPTIONS |
893 | } catch (...) { |
894 | this->set_exception(current_exception()); |
895 | } |
896 | # endif // _LIBCPP_HAS_EXCEPTIONS |
897 | } |
898 | |
899 | template <class _Fp> |
900 | void __async_assoc_state<void, _Fp>::__on_zero_shared() _NOEXCEPT { |
901 | this->wait(); |
902 | base::__on_zero_shared(); |
903 | } |
904 | |
905 | template <class _Rp> |
906 | class promise; |
907 | template <class _Rp> |
908 | class shared_future; |
909 | |
910 | // future |
911 | |
912 | template <class _Rp> |
913 | class future; |
914 | |
915 | template <class _Rp, class _Fp> |
916 | _LIBCPP_HIDE_FROM_ABI future<_Rp> __make_deferred_assoc_state(_Fp&& __f); |
917 | |
918 | template <class _Rp, class _Fp> |
919 | _LIBCPP_HIDE_FROM_ABI future<_Rp> __make_async_assoc_state(_Fp&& __f); |
920 | |
921 | template <class _Rp> |
922 | class future { |
923 | __assoc_state<_Rp>* __state_; |
924 | |
925 | explicit _LIBCPP_HIDE_FROM_ABI future(__assoc_state<_Rp>* __state); |
926 | |
927 | template <class> |
928 | friend class promise; |
929 | template <class> |
930 | friend class shared_future; |
931 | |
932 | template <class _R1, class _Fp> |
933 | friend future<_R1> __make_deferred_assoc_state(_Fp&& __f); |
934 | template <class _R1, class _Fp> |
935 | friend future<_R1> __make_async_assoc_state(_Fp&& __f); |
936 | |
937 | public: |
938 | _LIBCPP_HIDE_FROM_ABI future() _NOEXCEPT : __state_(nullptr) {} |
939 | _LIBCPP_HIDE_FROM_ABI future(future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) { __rhs.__state_ = nullptr; } |
940 | future(const future&) = delete; |
941 | future& operator=(const future&) = delete; |
942 | _LIBCPP_HIDE_FROM_ABI future& operator=(future&& __rhs) _NOEXCEPT { |
943 | future(std::move(__rhs)).swap(*this); |
944 | return *this; |
945 | } |
946 | |
947 | _LIBCPP_HIDE_FROM_ABI ~future(); |
948 | _LIBCPP_HIDE_FROM_ABI shared_future<_Rp> share() _NOEXCEPT; |
949 | |
950 | // retrieving the value |
951 | _LIBCPP_HIDE_FROM_ABI _Rp get(); |
952 | |
953 | _LIBCPP_HIDE_FROM_ABI void swap(future& __rhs) _NOEXCEPT { std::swap(__state_, __rhs.__state_); } |
954 | |
955 | // functions to check state |
956 | _LIBCPP_HIDE_FROM_ABI bool valid() const _NOEXCEPT { return __state_ != nullptr; } |
957 | |
958 | _LIBCPP_HIDE_FROM_ABI void wait() const { __state_->wait(); } |
959 | template <class _Rep, class _Period> |
960 | _LIBCPP_HIDE_FROM_ABI future_status wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const { |
961 | return __state_->wait_for(__rel_time); |
962 | } |
963 | template <class _Clock, class _Duration> |
964 | _LIBCPP_HIDE_FROM_ABI future_status wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const { |
965 | return __state_->wait_until(__abs_time); |
966 | } |
967 | }; |
968 | |
969 | template <class _Rp> |
970 | future<_Rp>::future(__assoc_state<_Rp>* __state) : __state_(__state) { |
971 | __state_->__attach_future(); |
972 | } |
973 | |
974 | struct __release_shared_count { |
975 | _LIBCPP_HIDE_FROM_ABI void operator()(__shared_count* __p) { __p->__release_shared(); } |
976 | }; |
977 | |
978 | template <class _Rp> |
979 | future<_Rp>::~future() { |
980 | if (__state_) |
981 | __state_->__release_shared(); |
982 | } |
983 | |
984 | template <class _Rp> |
985 | _Rp future<_Rp>::get() { |
986 | unique_ptr<__shared_count, __release_shared_count> __guard(__state_); |
987 | __assoc_state<_Rp>* __s = __state_; |
988 | __state_ = nullptr; |
989 | return __s->move(); |
990 | } |
991 | |
992 | template <class _Rp> |
993 | class future<_Rp&> { |
994 | __assoc_state<_Rp&>* __state_; |
995 | |
996 | explicit _LIBCPP_HIDE_FROM_ABI future(__assoc_state<_Rp&>* __state); |
997 | |
998 | template <class> |
999 | friend class promise; |
1000 | template <class> |
1001 | friend class shared_future; |
1002 | |
1003 | template <class _R1, class _Fp> |
1004 | friend future<_R1> __make_deferred_assoc_state(_Fp&& __f); |
1005 | template <class _R1, class _Fp> |
1006 | friend future<_R1> __make_async_assoc_state(_Fp&& __f); |
1007 | |
1008 | public: |
1009 | _LIBCPP_HIDE_FROM_ABI future() _NOEXCEPT : __state_(nullptr) {} |
1010 | _LIBCPP_HIDE_FROM_ABI future(future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) { __rhs.__state_ = nullptr; } |
1011 | future(const future&) = delete; |
1012 | future& operator=(const future&) = delete; |
1013 | _LIBCPP_HIDE_FROM_ABI future& operator=(future&& __rhs) _NOEXCEPT { |
1014 | future(std::move(__rhs)).swap(*this); |
1015 | return *this; |
1016 | } |
1017 | |
1018 | _LIBCPP_HIDE_FROM_ABI ~future(); |
1019 | _LIBCPP_HIDE_FROM_ABI shared_future<_Rp&> share() _NOEXCEPT; |
1020 | |
1021 | // retrieving the value |
1022 | _LIBCPP_HIDE_FROM_ABI _Rp& get(); |
1023 | |
1024 | _LIBCPP_HIDE_FROM_ABI void swap(future& __rhs) _NOEXCEPT { std::swap(__state_, __rhs.__state_); } |
1025 | |
1026 | // functions to check state |
1027 | _LIBCPP_HIDE_FROM_ABI bool valid() const _NOEXCEPT { return __state_ != nullptr; } |
1028 | |
1029 | _LIBCPP_HIDE_FROM_ABI void wait() const { __state_->wait(); } |
1030 | template <class _Rep, class _Period> |
1031 | _LIBCPP_HIDE_FROM_ABI future_status wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const { |
1032 | return __state_->wait_for(__rel_time); |
1033 | } |
1034 | template <class _Clock, class _Duration> |
1035 | _LIBCPP_HIDE_FROM_ABI future_status wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const { |
1036 | return __state_->wait_until(__abs_time); |
1037 | } |
1038 | }; |
1039 | |
1040 | template <class _Rp> |
1041 | future<_Rp&>::future(__assoc_state<_Rp&>* __state) : __state_(__state) { |
1042 | __state_->__attach_future(); |
1043 | } |
1044 | |
1045 | template <class _Rp> |
1046 | future<_Rp&>::~future() { |
1047 | if (__state_) |
1048 | __state_->__release_shared(); |
1049 | } |
1050 | |
1051 | template <class _Rp> |
1052 | _Rp& future<_Rp&>::get() { |
1053 | unique_ptr<__shared_count, __release_shared_count> __guard(__state_); |
1054 | __assoc_state<_Rp&>* __s = __state_; |
1055 | __state_ = nullptr; |
1056 | return __s->copy(); |
1057 | } |
1058 | |
1059 | template <> |
1060 | class _LIBCPP_EXPORTED_FROM_ABI future<void> { |
1061 | __assoc_sub_state* __state_; |
1062 | |
1063 | explicit future(__assoc_sub_state* __state); |
1064 | |
1065 | template <class> |
1066 | friend class promise; |
1067 | template <class> |
1068 | friend class shared_future; |
1069 | |
1070 | template <class _R1, class _Fp> |
1071 | friend future<_R1> __make_deferred_assoc_state(_Fp&& __f); |
1072 | template <class _R1, class _Fp> |
1073 | friend future<_R1> __make_async_assoc_state(_Fp&& __f); |
1074 | |
1075 | public: |
1076 | _LIBCPP_HIDE_FROM_ABI future() _NOEXCEPT : __state_(nullptr) {} |
1077 | _LIBCPP_HIDE_FROM_ABI future(future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) { __rhs.__state_ = nullptr; } |
1078 | future(const future&) = delete; |
1079 | future& operator=(const future&) = delete; |
1080 | _LIBCPP_HIDE_FROM_ABI future& operator=(future&& __rhs) _NOEXCEPT { |
1081 | future(std::move(__rhs)).swap(rhs&: *this); |
1082 | return *this; |
1083 | } |
1084 | |
1085 | ~future(); |
1086 | _LIBCPP_HIDE_FROM_ABI shared_future<void> share() _NOEXCEPT; |
1087 | |
1088 | // retrieving the value |
1089 | void get(); |
1090 | |
1091 | _LIBCPP_HIDE_FROM_ABI void swap(future& __rhs) _NOEXCEPT { std::swap(x&: __state_, y&: __rhs.__state_); } |
1092 | |
1093 | // functions to check state |
1094 | _LIBCPP_HIDE_FROM_ABI bool valid() const _NOEXCEPT { return __state_ != nullptr; } |
1095 | |
1096 | _LIBCPP_HIDE_FROM_ABI void wait() const { __state_->wait(); } |
1097 | template <class _Rep, class _Period> |
1098 | _LIBCPP_HIDE_FROM_ABI future_status wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const { |
1099 | return __state_->wait_for(__rel_time); |
1100 | } |
1101 | template <class _Clock, class _Duration> |
1102 | _LIBCPP_HIDE_FROM_ABI future_status wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const { |
1103 | return __state_->wait_until(__abs_time); |
1104 | } |
1105 | }; |
1106 | |
1107 | template <class _Rp> |
1108 | inline _LIBCPP_HIDE_FROM_ABI void swap(future<_Rp>& __x, future<_Rp>& __y) _NOEXCEPT { |
1109 | __x.swap(__y); |
1110 | } |
1111 | |
1112 | // promise<R> |
1113 | |
1114 | template <class _Callable> |
1115 | class packaged_task; |
1116 | |
1117 | template <class _Rp> |
1118 | class promise { |
1119 | __assoc_state<_Rp>* __state_; |
1120 | |
1121 | _LIBCPP_HIDE_FROM_ABI explicit promise(nullptr_t) _NOEXCEPT : __state_(nullptr) {} |
1122 | |
1123 | template <class> |
1124 | friend class packaged_task; |
1125 | |
1126 | public: |
1127 | _LIBCPP_HIDE_FROM_ABI promise(); |
1128 | template <class _Alloc> |
1129 | _LIBCPP_HIDE_FROM_ABI promise(allocator_arg_t, const _Alloc& __a); |
1130 | _LIBCPP_HIDE_FROM_ABI promise(promise&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) { __rhs.__state_ = nullptr; } |
1131 | promise(const promise& __rhs) = delete; |
1132 | _LIBCPP_HIDE_FROM_ABI ~promise(); |
1133 | |
1134 | // assignment |
1135 | _LIBCPP_HIDE_FROM_ABI promise& operator=(promise&& __rhs) _NOEXCEPT { |
1136 | promise(std::move(__rhs)).swap(*this); |
1137 | return *this; |
1138 | } |
1139 | promise& operator=(const promise& __rhs) = delete; |
1140 | |
1141 | _LIBCPP_HIDE_FROM_ABI void swap(promise& __rhs) _NOEXCEPT { std::swap(__state_, __rhs.__state_); } |
1142 | |
1143 | // retrieving the result |
1144 | _LIBCPP_HIDE_FROM_ABI future<_Rp> get_future(); |
1145 | |
1146 | // setting the result |
1147 | _LIBCPP_HIDE_FROM_ABI void set_value(const _Rp& __r); |
1148 | _LIBCPP_HIDE_FROM_ABI void set_value(_Rp&& __r); |
1149 | _LIBCPP_HIDE_FROM_ABI void set_exception(exception_ptr __p); |
1150 | |
1151 | // setting the result with deferred notification |
1152 | _LIBCPP_HIDE_FROM_ABI void set_value_at_thread_exit(const _Rp& __r); |
1153 | _LIBCPP_HIDE_FROM_ABI void set_value_at_thread_exit(_Rp&& __r); |
1154 | _LIBCPP_HIDE_FROM_ABI void set_exception_at_thread_exit(exception_ptr __p); |
1155 | }; |
1156 | |
1157 | template <class _Rp> |
1158 | promise<_Rp>::promise() : __state_(new __assoc_state<_Rp>) {} |
1159 | |
1160 | template <class _Rp> |
1161 | template <class _Alloc> |
1162 | promise<_Rp>::promise(allocator_arg_t, const _Alloc& __a0) { |
1163 | typedef __assoc_state_alloc<_Rp, _Alloc> _State; |
1164 | typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2; |
1165 | typedef __allocator_destructor<_A2> _D2; |
1166 | _A2 __a(__a0); |
1167 | unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1)); |
1168 | ::new ((void*)std::addressof(*__hold.get())) _State(__a0); |
1169 | __state_ = std::addressof(*__hold.release()); |
1170 | } |
1171 | |
1172 | template <class _Rp> |
1173 | promise<_Rp>::~promise() { |
1174 | if (__state_) { |
1175 | if (!__state_->__has_value() && __state_->use_count() > 1) |
1176 | __state_->set_exception(make_exception_ptr(e: future_error(make_error_code(e: future_errc::broken_promise)))); |
1177 | __state_->__release_shared(); |
1178 | } |
1179 | } |
1180 | |
1181 | template <class _Rp> |
1182 | future<_Rp> promise<_Rp>::get_future() { |
1183 | if (__state_ == nullptr) |
1184 | std::__throw_future_error(ev: future_errc::no_state); |
1185 | return future<_Rp>(__state_); |
1186 | } |
1187 | |
1188 | template <class _Rp> |
1189 | void promise<_Rp>::set_value(const _Rp& __r) { |
1190 | if (__state_ == nullptr) |
1191 | std::__throw_future_error(ev: future_errc::no_state); |
1192 | __state_->set_value(__r); |
1193 | } |
1194 | |
1195 | template <class _Rp> |
1196 | void promise<_Rp>::set_value(_Rp&& __r) { |
1197 | if (__state_ == nullptr) |
1198 | std::__throw_future_error(ev: future_errc::no_state); |
1199 | __state_->set_value(std::move(__r)); |
1200 | } |
1201 | |
1202 | template <class _Rp> |
1203 | void promise<_Rp>::set_exception(exception_ptr __p) { |
1204 | _LIBCPP_ASSERT_NON_NULL(__p != nullptr, "promise::set_exception: received nullptr" ); |
1205 | if (__state_ == nullptr) |
1206 | std::__throw_future_error(ev: future_errc::no_state); |
1207 | __state_->set_exception(__p); |
1208 | } |
1209 | |
1210 | template <class _Rp> |
1211 | void promise<_Rp>::set_value_at_thread_exit(const _Rp& __r) { |
1212 | if (__state_ == nullptr) |
1213 | std::__throw_future_error(ev: future_errc::no_state); |
1214 | __state_->set_value_at_thread_exit(__r); |
1215 | } |
1216 | |
1217 | template <class _Rp> |
1218 | void promise<_Rp>::set_value_at_thread_exit(_Rp&& __r) { |
1219 | if (__state_ == nullptr) |
1220 | std::__throw_future_error(ev: future_errc::no_state); |
1221 | __state_->set_value_at_thread_exit(std::move(__r)); |
1222 | } |
1223 | |
1224 | template <class _Rp> |
1225 | void promise<_Rp>::set_exception_at_thread_exit(exception_ptr __p) { |
1226 | _LIBCPP_ASSERT_NON_NULL(__p != nullptr, "promise::set_exception_at_thread_exit: received nullptr" ); |
1227 | if (__state_ == nullptr) |
1228 | std::__throw_future_error(ev: future_errc::no_state); |
1229 | __state_->set_exception_at_thread_exit(__p); |
1230 | } |
1231 | |
1232 | // promise<R&> |
1233 | |
1234 | template <class _Rp> |
1235 | class promise<_Rp&> { |
1236 | __assoc_state<_Rp&>* __state_; |
1237 | |
1238 | _LIBCPP_HIDE_FROM_ABI explicit promise(nullptr_t) _NOEXCEPT : __state_(nullptr) {} |
1239 | |
1240 | template <class> |
1241 | friend class packaged_task; |
1242 | |
1243 | public: |
1244 | _LIBCPP_HIDE_FROM_ABI promise(); |
1245 | template <class _Allocator> |
1246 | _LIBCPP_HIDE_FROM_ABI promise(allocator_arg_t, const _Allocator& __a); |
1247 | _LIBCPP_HIDE_FROM_ABI promise(promise&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) { __rhs.__state_ = nullptr; } |
1248 | promise(const promise& __rhs) = delete; |
1249 | _LIBCPP_HIDE_FROM_ABI ~promise(); |
1250 | |
1251 | // assignment |
1252 | _LIBCPP_HIDE_FROM_ABI promise& operator=(promise&& __rhs) _NOEXCEPT { |
1253 | promise(std::move(__rhs)).swap(*this); |
1254 | return *this; |
1255 | } |
1256 | promise& operator=(const promise& __rhs) = delete; |
1257 | |
1258 | _LIBCPP_HIDE_FROM_ABI void swap(promise& __rhs) _NOEXCEPT { std::swap(__state_, __rhs.__state_); } |
1259 | |
1260 | // retrieving the result |
1261 | _LIBCPP_HIDE_FROM_ABI future<_Rp&> get_future(); |
1262 | |
1263 | // setting the result |
1264 | _LIBCPP_HIDE_FROM_ABI void set_value(_Rp& __r); |
1265 | _LIBCPP_HIDE_FROM_ABI void set_exception(exception_ptr __p); |
1266 | |
1267 | // setting the result with deferred notification |
1268 | _LIBCPP_HIDE_FROM_ABI void set_value_at_thread_exit(_Rp&); |
1269 | _LIBCPP_HIDE_FROM_ABI void set_exception_at_thread_exit(exception_ptr __p); |
1270 | }; |
1271 | |
1272 | template <class _Rp> |
1273 | promise<_Rp&>::promise() : __state_(new __assoc_state<_Rp&>) {} |
1274 | |
1275 | template <class _Rp> |
1276 | template <class _Alloc> |
1277 | promise<_Rp&>::promise(allocator_arg_t, const _Alloc& __a0) { |
1278 | typedef __assoc_state_alloc<_Rp&, _Alloc> _State; |
1279 | typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2; |
1280 | typedef __allocator_destructor<_A2> _D2; |
1281 | _A2 __a(__a0); |
1282 | unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1)); |
1283 | ::new ((void*)std::addressof(*__hold.get())) _State(__a0); |
1284 | __state_ = std::addressof(*__hold.release()); |
1285 | } |
1286 | |
1287 | template <class _Rp> |
1288 | promise<_Rp&>::~promise() { |
1289 | if (__state_) { |
1290 | if (!__state_->__has_value() && __state_->use_count() > 1) |
1291 | __state_->set_exception(make_exception_ptr(e: future_error(make_error_code(e: future_errc::broken_promise)))); |
1292 | __state_->__release_shared(); |
1293 | } |
1294 | } |
1295 | |
1296 | template <class _Rp> |
1297 | future<_Rp&> promise<_Rp&>::get_future() { |
1298 | if (__state_ == nullptr) |
1299 | std::__throw_future_error(ev: future_errc::no_state); |
1300 | return future<_Rp&>(__state_); |
1301 | } |
1302 | |
1303 | template <class _Rp> |
1304 | void promise<_Rp&>::set_value(_Rp& __r) { |
1305 | if (__state_ == nullptr) |
1306 | std::__throw_future_error(ev: future_errc::no_state); |
1307 | __state_->set_value(__r); |
1308 | } |
1309 | |
1310 | template <class _Rp> |
1311 | void promise<_Rp&>::set_exception(exception_ptr __p) { |
1312 | _LIBCPP_ASSERT_NON_NULL(__p != nullptr, "promise::set_exception: received nullptr" ); |
1313 | if (__state_ == nullptr) |
1314 | std::__throw_future_error(ev: future_errc::no_state); |
1315 | __state_->set_exception(__p); |
1316 | } |
1317 | |
1318 | template <class _Rp> |
1319 | void promise<_Rp&>::set_value_at_thread_exit(_Rp& __r) { |
1320 | if (__state_ == nullptr) |
1321 | std::__throw_future_error(ev: future_errc::no_state); |
1322 | __state_->set_value_at_thread_exit(__r); |
1323 | } |
1324 | |
1325 | template <class _Rp> |
1326 | void promise<_Rp&>::set_exception_at_thread_exit(exception_ptr __p) { |
1327 | _LIBCPP_ASSERT_NON_NULL(__p != nullptr, "promise::set_exception_at_thread_exit: received nullptr" ); |
1328 | if (__state_ == nullptr) |
1329 | std::__throw_future_error(ev: future_errc::no_state); |
1330 | __state_->set_exception_at_thread_exit(__p); |
1331 | } |
1332 | |
1333 | // promise<void> |
1334 | |
1335 | template <> |
1336 | class _LIBCPP_EXPORTED_FROM_ABI promise<void> { |
1337 | __assoc_sub_state* __state_; |
1338 | |
1339 | _LIBCPP_HIDE_FROM_ABI explicit promise(nullptr_t) _NOEXCEPT : __state_(nullptr) {} |
1340 | |
1341 | template <class> |
1342 | friend class packaged_task; |
1343 | |
1344 | public: |
1345 | promise(); |
1346 | template <class _Alloc> |
1347 | _LIBCPP_HIDE_FROM_ABI promise(allocator_arg_t, const _Alloc& __a0) { |
1348 | typedef __assoc_sub_state_alloc<_Alloc> _State; |
1349 | typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2; |
1350 | typedef __allocator_destructor<_A2> _D2; |
1351 | _A2 __a(__a0); |
1352 | unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1)); |
1353 | ::new ((void*)std::addressof(*__hold.get())) _State(__a0); |
1354 | __state_ = std::addressof(*__hold.release()); |
1355 | } |
1356 | |
1357 | _LIBCPP_HIDE_FROM_ABI promise(promise&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) { __rhs.__state_ = nullptr; } |
1358 | promise(const promise& __rhs) = delete; |
1359 | ~promise(); |
1360 | |
1361 | // assignment |
1362 | _LIBCPP_HIDE_FROM_ABI promise& operator=(promise&& __rhs) _NOEXCEPT { |
1363 | promise(std::move(__rhs)).swap(rhs&: *this); |
1364 | return *this; |
1365 | } |
1366 | promise& operator=(const promise& __rhs) = delete; |
1367 | |
1368 | _LIBCPP_HIDE_FROM_ABI void swap(promise& __rhs) _NOEXCEPT { std::swap(x&: __state_, y&: __rhs.__state_); } |
1369 | |
1370 | // retrieving the result |
1371 | future<void> get_future(); |
1372 | |
1373 | // setting the result |
1374 | void set_value(); |
1375 | void set_exception(exception_ptr __p); |
1376 | |
1377 | // setting the result with deferred notification |
1378 | void set_value_at_thread_exit(); |
1379 | void set_exception_at_thread_exit(exception_ptr __p); |
1380 | }; |
1381 | |
1382 | template <class _Rp> |
1383 | inline _LIBCPP_HIDE_FROM_ABI void swap(promise<_Rp>& __x, promise<_Rp>& __y) _NOEXCEPT { |
1384 | __x.swap(__y); |
1385 | } |
1386 | |
1387 | template <class _Rp, class _Alloc> |
1388 | struct uses_allocator<promise<_Rp>, _Alloc> : public true_type {}; |
1389 | |
1390 | // packaged_task |
1391 | |
1392 | template <class _Fp> |
1393 | class __packaged_task_base; |
1394 | |
1395 | template <class _Rp, class... _ArgTypes> |
1396 | class __packaged_task_base<_Rp(_ArgTypes...)> { |
1397 | public: |
1398 | _LIBCPP_HIDE_FROM_ABI __packaged_task_base() {} |
1399 | __packaged_task_base(const __packaged_task_base&) = delete; |
1400 | __packaged_task_base& operator=(const __packaged_task_base&) = delete; |
1401 | _LIBCPP_HIDE_FROM_ABI_VIRTUAL |
1402 | virtual ~__packaged_task_base() {} |
1403 | virtual void __move_to(__packaged_task_base*) _NOEXCEPT = 0; |
1404 | virtual void destroy() = 0; |
1405 | virtual void destroy_deallocate() = 0; |
1406 | virtual _Rp operator()(_ArgTypes&&...) = 0; |
1407 | }; |
1408 | |
1409 | template <class _FD, class _Alloc, class _FB> |
1410 | class __packaged_task_func; |
1411 | |
1412 | template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes> |
1413 | class __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)> : public __packaged_task_base<_Rp(_ArgTypes...)> { |
1414 | _LIBCPP_COMPRESSED_PAIR(_Fp, __func_, _Alloc, __alloc_); |
1415 | |
1416 | public: |
1417 | _LIBCPP_HIDE_FROM_ABI explicit __packaged_task_func(const _Fp& __f) : __func_(__f) {} |
1418 | _LIBCPP_HIDE_FROM_ABI explicit __packaged_task_func(_Fp&& __f) : __func_(std::move(__f)) {} |
1419 | _LIBCPP_HIDE_FROM_ABI __packaged_task_func(const _Fp& __f, const _Alloc& __a) : __func_(__f), __alloc_(__a) {} |
1420 | _LIBCPP_HIDE_FROM_ABI __packaged_task_func(_Fp&& __f, const _Alloc& __a) : __func_(std::move(__f)), __alloc_(__a) {} |
1421 | _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __move_to(__packaged_task_base<_Rp(_ArgTypes...)>*) _NOEXCEPT; |
1422 | _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy(); |
1423 | _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy_deallocate(); |
1424 | _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual _Rp operator()(_ArgTypes&&... __args); |
1425 | }; |
1426 | |
1427 | template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes> |
1428 | void __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__move_to( |
1429 | __packaged_task_base<_Rp(_ArgTypes...)>* __p) _NOEXCEPT { |
1430 | ::new ((void*)__p) __packaged_task_func(std::move(__func_), std::move(__alloc_)); |
1431 | } |
1432 | |
1433 | template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes> |
1434 | void __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy() { |
1435 | __func_.~_Fp(); |
1436 | __alloc_.~_Alloc(); |
1437 | } |
1438 | |
1439 | template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes> |
1440 | void __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate() { |
1441 | typedef typename __allocator_traits_rebind<_Alloc, __packaged_task_func>::type _Ap; |
1442 | typedef allocator_traits<_Ap> _ATraits; |
1443 | typedef pointer_traits<typename _ATraits::pointer> _PTraits; |
1444 | _Ap __a(__alloc_); |
1445 | __func_.~_Fp(); |
1446 | __alloc_.~_Alloc(); |
1447 | __a.deallocate(_PTraits::pointer_to(*this), 1); |
1448 | } |
1449 | |
1450 | template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes> |
1451 | _Rp __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&&... __arg) { |
1452 | return std::__invoke(__func_, std::forward<_ArgTypes>(__arg)...); |
1453 | } |
1454 | |
1455 | template <class _Callable> |
1456 | class __packaged_task_function; |
1457 | |
1458 | template <class _Rp, class... _ArgTypes> |
1459 | class __packaged_task_function<_Rp(_ArgTypes...)> { |
1460 | typedef __packaged_task_base<_Rp(_ArgTypes...)> __base; |
1461 | |
1462 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI __base* __get_buf() { return (__base*)&__buf_; } |
1463 | |
1464 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH |
1465 | typename aligned_storage<3 * sizeof(void*)>::type __buf_; |
1466 | _LIBCPP_SUPPRESS_DEPRECATED_POP |
1467 | __base* __f_; |
1468 | |
1469 | public: |
1470 | typedef _Rp result_type; |
1471 | |
1472 | // construct/copy/destroy: |
1473 | _LIBCPP_HIDE_FROM_ABI __packaged_task_function() _NOEXCEPT : __f_(nullptr) {} |
1474 | template <class _Fp> |
1475 | _LIBCPP_HIDE_FROM_ABI __packaged_task_function(_Fp&& __f); |
1476 | template <class _Fp, class _Alloc> |
1477 | _LIBCPP_HIDE_FROM_ABI __packaged_task_function(allocator_arg_t, const _Alloc& __a, _Fp&& __f); |
1478 | |
1479 | _LIBCPP_HIDE_FROM_ABI __packaged_task_function(__packaged_task_function&&) _NOEXCEPT; |
1480 | _LIBCPP_HIDE_FROM_ABI __packaged_task_function& operator=(__packaged_task_function&&) _NOEXCEPT; |
1481 | |
1482 | __packaged_task_function(const __packaged_task_function&) = delete; |
1483 | __packaged_task_function& operator=(const __packaged_task_function&) = delete; |
1484 | |
1485 | _LIBCPP_HIDE_FROM_ABI ~__packaged_task_function(); |
1486 | |
1487 | _LIBCPP_HIDE_FROM_ABI void swap(__packaged_task_function&) _NOEXCEPT; |
1488 | |
1489 | _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes...) const; |
1490 | }; |
1491 | |
1492 | template <class _Rp, class... _ArgTypes> |
1493 | __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(__packaged_task_function&& __f) _NOEXCEPT { |
1494 | if (__f.__f_ == nullptr) |
1495 | __f_ = nullptr; |
1496 | else if (__f.__f_ == __f.__get_buf()) { |
1497 | __f.__f_->__move_to(__get_buf()); |
1498 | __f_ = (__base*)&__buf_; |
1499 | } else { |
1500 | __f_ = __f.__f_; |
1501 | __f.__f_ = nullptr; |
1502 | } |
1503 | } |
1504 | |
1505 | template <class _Rp, class... _ArgTypes> |
1506 | template <class _Fp> |
1507 | __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(_Fp&& __f) : __f_(nullptr) { |
1508 | typedef __libcpp_remove_reference_t<__decay_t<_Fp> > _FR; |
1509 | typedef __packaged_task_func<_FR, allocator<_FR>, _Rp(_ArgTypes...)> _FF; |
1510 | if (sizeof(_FF) <= sizeof(__buf_)) { |
1511 | ::new ((void*)&__buf_) _FF(std::forward<_Fp>(__f)); |
1512 | __f_ = (__base*)&__buf_; |
1513 | } else { |
1514 | typedef allocator<_FF> _Ap; |
1515 | _Ap __a; |
1516 | typedef __allocator_destructor<_Ap> _Dp; |
1517 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); |
1518 | ::new ((void*)__hold.get()) _FF(std::forward<_Fp>(__f), allocator<_FR>(__a)); |
1519 | __f_ = __hold.release(); |
1520 | } |
1521 | } |
1522 | |
1523 | template <class _Rp, class... _ArgTypes> |
1524 | template <class _Fp, class _Alloc> |
1525 | __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(allocator_arg_t, const _Alloc& __a0, _Fp&& __f) |
1526 | : __f_(nullptr) { |
1527 | typedef __libcpp_remove_reference_t<__decay_t<_Fp> > _FR; |
1528 | typedef __packaged_task_func<_FR, _Alloc, _Rp(_ArgTypes...)> _FF; |
1529 | if (sizeof(_FF) <= sizeof(__buf_)) { |
1530 | __f_ = (__base*)&__buf_; |
1531 | ::new ((void*)__f_) _FF(std::forward<_Fp>(__f)); |
1532 | } else { |
1533 | typedef typename __allocator_traits_rebind<_Alloc, _FF>::type _Ap; |
1534 | _Ap __a(__a0); |
1535 | typedef __allocator_destructor<_Ap> _Dp; |
1536 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); |
1537 | ::new ((void*)std::addressof(*__hold.get())) _FF(std::forward<_Fp>(__f), _Alloc(__a)); |
1538 | __f_ = std::addressof(*__hold.release()); |
1539 | } |
1540 | } |
1541 | |
1542 | template <class _Rp, class... _ArgTypes> |
1543 | __packaged_task_function<_Rp(_ArgTypes...)>& |
1544 | __packaged_task_function<_Rp(_ArgTypes...)>::operator=(__packaged_task_function&& __f) _NOEXCEPT { |
1545 | if (__f_ == __get_buf()) |
1546 | __f_->destroy(); |
1547 | else if (__f_) |
1548 | __f_->destroy_deallocate(); |
1549 | __f_ = nullptr; |
1550 | if (__f.__f_ == nullptr) |
1551 | __f_ = nullptr; |
1552 | else if (__f.__f_ == __f.__get_buf()) { |
1553 | __f.__f_->__move_to(__get_buf()); |
1554 | __f_ = __get_buf(); |
1555 | } else { |
1556 | __f_ = __f.__f_; |
1557 | __f.__f_ = nullptr; |
1558 | } |
1559 | return *this; |
1560 | } |
1561 | |
1562 | template <class _Rp, class... _ArgTypes> |
1563 | __packaged_task_function<_Rp(_ArgTypes...)>::~__packaged_task_function() { |
1564 | if (__f_ == __get_buf()) |
1565 | __f_->destroy(); |
1566 | else if (__f_) |
1567 | __f_->destroy_deallocate(); |
1568 | } |
1569 | |
1570 | template <class _Rp, class... _ArgTypes> |
1571 | _LIBCPP_NO_CFI void __packaged_task_function<_Rp(_ArgTypes...)>::swap(__packaged_task_function& __f) _NOEXCEPT { |
1572 | if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) { |
1573 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH |
1574 | typename aligned_storage<sizeof(__buf_)>::type __tempbuf; |
1575 | _LIBCPP_SUPPRESS_DEPRECATED_POP |
1576 | __base* __t = (__base*)&__tempbuf; |
1577 | __f_->__move_to(__t); |
1578 | __f_->destroy(); |
1579 | __f_ = nullptr; |
1580 | __f.__f_->__move_to((__base*)&__buf_); |
1581 | __f.__f_->destroy(); |
1582 | __f.__f_ = nullptr; |
1583 | __f_ = (__base*)&__buf_; |
1584 | __t->__move_to((__base*)&__f.__buf_); |
1585 | __t->destroy(); |
1586 | __f.__f_ = (__base*)&__f.__buf_; |
1587 | } else if (__f_ == (__base*)&__buf_) { |
1588 | __f_->__move_to((__base*)&__f.__buf_); |
1589 | __f_->destroy(); |
1590 | __f_ = __f.__f_; |
1591 | __f.__f_ = (__base*)&__f.__buf_; |
1592 | } else if (__f.__f_ == (__base*)&__f.__buf_) { |
1593 | __f.__f_->__move_to((__base*)&__buf_); |
1594 | __f.__f_->destroy(); |
1595 | __f.__f_ = __f_; |
1596 | __f_ = (__base*)&__buf_; |
1597 | } else |
1598 | std::swap(__f_, __f.__f_); |
1599 | } |
1600 | |
1601 | template <class _Rp, class... _ArgTypes> |
1602 | inline _Rp __packaged_task_function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const { |
1603 | return (*__f_)(std::forward<_ArgTypes>(__arg)...); |
1604 | } |
1605 | |
1606 | template <class _Rp, class... _ArgTypes> |
1607 | class packaged_task<_Rp(_ArgTypes...)> { |
1608 | public: |
1609 | using result_type _LIBCPP_DEPRECATED = _Rp; // extension |
1610 | |
1611 | private: |
1612 | __packaged_task_function<_Rp(_ArgTypes...)> __f_; |
1613 | promise<_Rp> __p_; |
1614 | |
1615 | public: |
1616 | // construction and destruction |
1617 | _LIBCPP_HIDE_FROM_ABI packaged_task() _NOEXCEPT : __p_(nullptr) {} |
1618 | |
1619 | template <class _Fp, __enable_if_t<!is_same<__remove_cvref_t<_Fp>, packaged_task>::value, int> = 0> |
1620 | _LIBCPP_HIDE_FROM_ABI explicit packaged_task(_Fp&& __f) : __f_(std::forward<_Fp>(__f)) {} |
1621 | |
1622 | # if _LIBCPP_STD_VER <= 14 |
1623 | template <class _Fp, class _Allocator, __enable_if_t<!is_same<__remove_cvref_t<_Fp>, packaged_task>::value, int> = 0> |
1624 | _LIBCPP_HIDE_FROM_ABI packaged_task(allocator_arg_t, const _Allocator& __a, _Fp&& __f) |
1625 | : __f_(allocator_arg_t(), __a, std::forward<_Fp>(__f)), __p_(allocator_arg_t(), __a) {} |
1626 | # endif |
1627 | // ~packaged_task() = default; |
1628 | |
1629 | // no copy |
1630 | packaged_task(const packaged_task&) = delete; |
1631 | packaged_task& operator=(const packaged_task&) = delete; |
1632 | |
1633 | // move support |
1634 | _LIBCPP_HIDE_FROM_ABI packaged_task(packaged_task&& __other) _NOEXCEPT |
1635 | : __f_(std::move(__other.__f_)), |
1636 | __p_(std::move(__other.__p_)) {} |
1637 | _LIBCPP_HIDE_FROM_ABI packaged_task& operator=(packaged_task&& __other) _NOEXCEPT { |
1638 | __f_ = std::move(__other.__f_); |
1639 | __p_ = std::move(__other.__p_); |
1640 | return *this; |
1641 | } |
1642 | _LIBCPP_HIDE_FROM_ABI void swap(packaged_task& __other) _NOEXCEPT { |
1643 | __f_.swap(__other.__f_); |
1644 | __p_.swap(__other.__p_); |
1645 | } |
1646 | |
1647 | _LIBCPP_HIDE_FROM_ABI bool valid() const _NOEXCEPT { return __p_.__state_ != nullptr; } |
1648 | |
1649 | // result retrieval |
1650 | _LIBCPP_HIDE_FROM_ABI future<_Rp> get_future() { return __p_.get_future(); } |
1651 | |
1652 | // execution |
1653 | _LIBCPP_HIDE_FROM_ABI void operator()(_ArgTypes... __args); |
1654 | _LIBCPP_HIDE_FROM_ABI void make_ready_at_thread_exit(_ArgTypes... __args); |
1655 | |
1656 | _LIBCPP_HIDE_FROM_ABI void reset(); |
1657 | }; |
1658 | |
1659 | template <class _Rp, class... _ArgTypes> |
1660 | void packaged_task<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __args) { |
1661 | if (__p_.__state_ == nullptr) |
1662 | std::__throw_future_error(ev: future_errc::no_state); |
1663 | if (__p_.__state_->__has_value()) |
1664 | std::__throw_future_error(ev: future_errc::promise_already_satisfied); |
1665 | # if _LIBCPP_HAS_EXCEPTIONS |
1666 | try { |
1667 | # endif // _LIBCPP_HAS_EXCEPTIONS |
1668 | __p_.set_value(__f_(std::forward<_ArgTypes>(__args)...)); |
1669 | # if _LIBCPP_HAS_EXCEPTIONS |
1670 | } catch (...) { |
1671 | __p_.set_exception(current_exception()); |
1672 | } |
1673 | # endif // _LIBCPP_HAS_EXCEPTIONS |
1674 | } |
1675 | |
1676 | template <class _Rp, class... _ArgTypes> |
1677 | void packaged_task<_Rp(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __args) { |
1678 | if (__p_.__state_ == nullptr) |
1679 | std::__throw_future_error(ev: future_errc::no_state); |
1680 | if (__p_.__state_->__has_value()) |
1681 | std::__throw_future_error(ev: future_errc::promise_already_satisfied); |
1682 | # if _LIBCPP_HAS_EXCEPTIONS |
1683 | try { |
1684 | # endif // _LIBCPP_HAS_EXCEPTIONS |
1685 | __p_.set_value_at_thread_exit(__f_(std::forward<_ArgTypes>(__args)...)); |
1686 | # if _LIBCPP_HAS_EXCEPTIONS |
1687 | } catch (...) { |
1688 | __p_.set_exception_at_thread_exit(current_exception()); |
1689 | } |
1690 | # endif // _LIBCPP_HAS_EXCEPTIONS |
1691 | } |
1692 | |
1693 | template <class _Rp, class... _ArgTypes> |
1694 | void packaged_task<_Rp(_ArgTypes...)>::reset() { |
1695 | if (!valid()) |
1696 | std::__throw_future_error(ev: future_errc::no_state); |
1697 | __p_ = promise<_Rp>(); |
1698 | } |
1699 | |
1700 | template <class... _ArgTypes> |
1701 | class packaged_task<void(_ArgTypes...)> { |
1702 | public: |
1703 | using result_type _LIBCPP_DEPRECATED = void; // extension |
1704 | |
1705 | private: |
1706 | __packaged_task_function<void(_ArgTypes...)> __f_; |
1707 | promise<void> __p_; |
1708 | |
1709 | public: |
1710 | // construction and destruction |
1711 | _LIBCPP_HIDE_FROM_ABI packaged_task() _NOEXCEPT : __p_(nullptr) {} |
1712 | template <class _Fp, __enable_if_t<!is_same<__remove_cvref_t<_Fp>, packaged_task>::value, int> = 0> |
1713 | _LIBCPP_HIDE_FROM_ABI explicit packaged_task(_Fp&& __f) : __f_(std::forward<_Fp>(__f)) {} |
1714 | # if _LIBCPP_STD_VER <= 14 |
1715 | template <class _Fp, class _Allocator, __enable_if_t<!is_same<__remove_cvref_t<_Fp>, packaged_task>::value, int> = 0> |
1716 | _LIBCPP_HIDE_FROM_ABI packaged_task(allocator_arg_t, const _Allocator& __a, _Fp&& __f) |
1717 | : __f_(allocator_arg_t(), __a, std::forward<_Fp>(__f)), __p_(allocator_arg_t(), __a) {} |
1718 | # endif |
1719 | // ~packaged_task() = default; |
1720 | |
1721 | // no copy |
1722 | packaged_task(const packaged_task&) = delete; |
1723 | packaged_task& operator=(const packaged_task&) = delete; |
1724 | |
1725 | // move support |
1726 | _LIBCPP_HIDE_FROM_ABI packaged_task(packaged_task&& __other) _NOEXCEPT |
1727 | : __f_(std::move(__other.__f_)), |
1728 | __p_(std::move(__other.__p_)) {} |
1729 | _LIBCPP_HIDE_FROM_ABI packaged_task& operator=(packaged_task&& __other) _NOEXCEPT { |
1730 | __f_ = std::move(__other.__f_); |
1731 | __p_ = std::move(__other.__p_); |
1732 | return *this; |
1733 | } |
1734 | _LIBCPP_HIDE_FROM_ABI void swap(packaged_task& __other) _NOEXCEPT { |
1735 | __f_.swap(__other.__f_); |
1736 | __p_.swap(rhs&: __other.__p_); |
1737 | } |
1738 | |
1739 | _LIBCPP_HIDE_FROM_ABI bool valid() const _NOEXCEPT { return __p_.__state_ != nullptr; } |
1740 | |
1741 | // result retrieval |
1742 | _LIBCPP_HIDE_FROM_ABI future<void> get_future() { return __p_.get_future(); } |
1743 | |
1744 | // execution |
1745 | _LIBCPP_HIDE_FROM_ABI void operator()(_ArgTypes... __args); |
1746 | _LIBCPP_HIDE_FROM_ABI void make_ready_at_thread_exit(_ArgTypes... __args); |
1747 | |
1748 | _LIBCPP_HIDE_FROM_ABI void reset(); |
1749 | }; |
1750 | |
1751 | # if _LIBCPP_STD_VER >= 17 |
1752 | |
1753 | template <class _Rp, class... _Args> |
1754 | packaged_task(_Rp (*)(_Args...)) -> packaged_task<_Rp(_Args...)>; |
1755 | |
1756 | template <class _Fp, class _Stripped = typename __strip_signature<decltype(&_Fp::operator())>::type> |
1757 | packaged_task(_Fp) -> packaged_task<_Stripped>; |
1758 | |
1759 | # endif |
1760 | |
1761 | template <class... _ArgTypes> |
1762 | void packaged_task<void(_ArgTypes...)>::operator()(_ArgTypes... __args) { |
1763 | if (__p_.__state_ == nullptr) |
1764 | std::__throw_future_error(ev: future_errc::no_state); |
1765 | if (__p_.__state_->__has_value()) |
1766 | std::__throw_future_error(ev: future_errc::promise_already_satisfied); |
1767 | # if _LIBCPP_HAS_EXCEPTIONS |
1768 | try { |
1769 | # endif // _LIBCPP_HAS_EXCEPTIONS |
1770 | __f_(std::forward<_ArgTypes>(__args)...); |
1771 | __p_.set_value(); |
1772 | # if _LIBCPP_HAS_EXCEPTIONS |
1773 | } catch (...) { |
1774 | __p_.set_exception(current_exception()); |
1775 | } |
1776 | # endif // _LIBCPP_HAS_EXCEPTIONS |
1777 | } |
1778 | |
1779 | template <class... _ArgTypes> |
1780 | void packaged_task<void(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __args) { |
1781 | if (__p_.__state_ == nullptr) |
1782 | std::__throw_future_error(ev: future_errc::no_state); |
1783 | if (__p_.__state_->__has_value()) |
1784 | std::__throw_future_error(ev: future_errc::promise_already_satisfied); |
1785 | # if _LIBCPP_HAS_EXCEPTIONS |
1786 | try { |
1787 | # endif // _LIBCPP_HAS_EXCEPTIONS |
1788 | __f_(std::forward<_ArgTypes>(__args)...); |
1789 | __p_.set_value_at_thread_exit(); |
1790 | # if _LIBCPP_HAS_EXCEPTIONS |
1791 | } catch (...) { |
1792 | __p_.set_exception_at_thread_exit(current_exception()); |
1793 | } |
1794 | # endif // _LIBCPP_HAS_EXCEPTIONS |
1795 | } |
1796 | |
1797 | template <class... _ArgTypes> |
1798 | void packaged_task<void(_ArgTypes...)>::reset() { |
1799 | if (!valid()) |
1800 | std::__throw_future_error(ev: future_errc::no_state); |
1801 | __p_ = promise<void>(); |
1802 | } |
1803 | |
1804 | template <class _Rp, class... _ArgTypes> |
1805 | inline _LIBCPP_HIDE_FROM_ABI void |
1806 | swap(packaged_task<_Rp(_ArgTypes...)>& __x, packaged_task<_Rp(_ArgTypes...)>& __y) _NOEXCEPT { |
1807 | __x.swap(__y); |
1808 | } |
1809 | |
1810 | # if _LIBCPP_STD_VER <= 14 |
1811 | template <class _Callable, class _Alloc> |
1812 | struct uses_allocator<packaged_task<_Callable>, _Alloc> : public true_type {}; |
1813 | # endif |
1814 | |
1815 | template <class _Rp, class _Fp> |
1816 | _LIBCPP_HIDE_FROM_ABI future<_Rp> __make_deferred_assoc_state(_Fp&& __f) { |
1817 | unique_ptr<__deferred_assoc_state<_Rp, _Fp>, __release_shared_count> __h( |
1818 | new __deferred_assoc_state<_Rp, _Fp>(std::forward<_Fp>(__f))); |
1819 | return future<_Rp>(__h.get()); |
1820 | } |
1821 | |
1822 | template <class _Rp, class _Fp> |
1823 | _LIBCPP_HIDE_FROM_ABI future<_Rp> __make_async_assoc_state(_Fp&& __f) { |
1824 | unique_ptr<__async_assoc_state<_Rp, _Fp>, __release_shared_count> __h( |
1825 | new __async_assoc_state<_Rp, _Fp>(std::forward<_Fp>(__f))); |
1826 | # if _LIBCPP_HAS_EXCEPTIONS |
1827 | try { |
1828 | # endif |
1829 | std::thread(&__async_assoc_state<_Rp, _Fp>::__execute, __h.get()).detach(); |
1830 | # if _LIBCPP_HAS_EXCEPTIONS |
1831 | } catch (...) { |
1832 | __h->__make_ready(); |
1833 | throw; |
1834 | } |
1835 | # endif |
1836 | return future<_Rp>(__h.get()); |
1837 | } |
1838 | |
1839 | # ifndef _LIBCPP_CXX03_LANG |
1840 | |
1841 | template <class _Fp, class... _Args> |
1842 | class _LIBCPP_HIDDEN __async_func { |
1843 | tuple<_Fp, _Args...> __f_; |
1844 | |
1845 | public: |
1846 | using _Rp _LIBCPP_NODEBUG = __invoke_result_t<_Fp, _Args...>; |
1847 | |
1848 | _LIBCPP_HIDE_FROM_ABI explicit __async_func(_Fp&& __f, _Args&&... __args) |
1849 | : __f_(std::move(__f), std::move(__args)...) {} |
1850 | |
1851 | _LIBCPP_HIDE_FROM_ABI __async_func(__async_func&& __f) : __f_(std::move(__f.__f_)) {} |
1852 | |
1853 | _LIBCPP_HIDE_FROM_ABI _Rp operator()() { |
1854 | typedef typename __make_tuple_indices<1 + sizeof...(_Args), 1>::type _Index; |
1855 | return __execute(_Index()); |
1856 | } |
1857 | |
1858 | private: |
1859 | template <size_t... _Indices> |
1860 | _LIBCPP_HIDE_FROM_ABI _Rp __execute(__tuple_indices<_Indices...>) { |
1861 | return std::__invoke(std::move(std::get<0>(__f_)), std::move(std::get<_Indices>(__f_))...); |
1862 | } |
1863 | }; |
1864 | |
1865 | inline _LIBCPP_HIDE_FROM_ABI bool __does_policy_contain(launch __policy, launch __value) { |
1866 | return (int(__policy) & int(__value)) != 0; |
1867 | } |
1868 | |
1869 | template <class _Fp, class... _Args> |
1870 | [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI future<__invoke_result_t<__decay_t<_Fp>, __decay_t<_Args>...> > |
1871 | async(launch __policy, _Fp&& __f, _Args&&... __args) { |
1872 | typedef __async_func<__decay_t<_Fp>, __decay_t<_Args>...> _BF; |
1873 | typedef typename _BF::_Rp _Rp; |
1874 | |
1875 | # if _LIBCPP_HAS_EXCEPTIONS |
1876 | try { |
1877 | # endif |
1878 | if (__does_policy_contain(__policy, value: launch::async)) |
1879 | return std::__make_async_assoc_state<_Rp>( |
1880 | _BF(_LIBCPP_AUTO_CAST(std::forward<_Fp>(__f)), _LIBCPP_AUTO_CAST(std::forward<_Args>(__args))...)); |
1881 | # if _LIBCPP_HAS_EXCEPTIONS |
1882 | } catch (...) { |
1883 | if (__policy == launch::async) |
1884 | throw; |
1885 | } |
1886 | # endif |
1887 | |
1888 | if (__does_policy_contain(__policy, value: launch::deferred)) |
1889 | return std::__make_deferred_assoc_state<_Rp>( |
1890 | _BF(_LIBCPP_AUTO_CAST(std::forward<_Fp>(__f)), _LIBCPP_AUTO_CAST(std::forward<_Args>(__args))...)); |
1891 | return future<_Rp>{}; |
1892 | } |
1893 | |
1894 | template <class _Fp, class... _Args> |
1895 | [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI future<__invoke_result_t<__decay_t<_Fp>, __decay_t<_Args>...> > |
1896 | async(_Fp&& __f, _Args&&... __args) { |
1897 | return std::async(launch::any, std::forward<_Fp>(__f), std::forward<_Args>(__args)...); |
1898 | } |
1899 | |
1900 | # endif // C++03 |
1901 | |
1902 | // shared_future |
1903 | |
1904 | template <class _Rp> |
1905 | class shared_future { |
1906 | __assoc_state<_Rp>* __state_; |
1907 | |
1908 | public: |
1909 | _LIBCPP_HIDE_FROM_ABI shared_future() _NOEXCEPT : __state_(nullptr) {} |
1910 | _LIBCPP_HIDE_FROM_ABI shared_future(const shared_future& __rhs) _NOEXCEPT : __state_(__rhs.__state_) { |
1911 | if (__state_) |
1912 | __state_->__add_shared(); |
1913 | } |
1914 | _LIBCPP_HIDE_FROM_ABI shared_future(future<_Rp>&& __f) _NOEXCEPT : __state_(__f.__state_) { __f.__state_ = nullptr; } |
1915 | _LIBCPP_HIDE_FROM_ABI shared_future(shared_future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) { |
1916 | __rhs.__state_ = nullptr; |
1917 | } |
1918 | _LIBCPP_HIDE_FROM_ABI ~shared_future(); |
1919 | _LIBCPP_HIDE_FROM_ABI shared_future& operator=(const shared_future& __rhs) _NOEXCEPT; |
1920 | _LIBCPP_HIDE_FROM_ABI shared_future& operator=(shared_future&& __rhs) _NOEXCEPT { |
1921 | shared_future(std::move(__rhs)).swap(*this); |
1922 | return *this; |
1923 | } |
1924 | |
1925 | // retrieving the value |
1926 | _LIBCPP_HIDE_FROM_ABI const _Rp& get() const { return __state_->copy(); } |
1927 | |
1928 | _LIBCPP_HIDE_FROM_ABI void swap(shared_future& __rhs) _NOEXCEPT { std::swap(__state_, __rhs.__state_); } |
1929 | |
1930 | // functions to check state |
1931 | _LIBCPP_HIDE_FROM_ABI bool valid() const _NOEXCEPT { return __state_ != nullptr; } |
1932 | |
1933 | _LIBCPP_HIDE_FROM_ABI void wait() const { __state_->wait(); } |
1934 | template <class _Rep, class _Period> |
1935 | _LIBCPP_HIDE_FROM_ABI future_status wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const { |
1936 | return __state_->wait_for(__rel_time); |
1937 | } |
1938 | template <class _Clock, class _Duration> |
1939 | _LIBCPP_HIDE_FROM_ABI future_status wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const { |
1940 | return __state_->wait_until(__abs_time); |
1941 | } |
1942 | }; |
1943 | |
1944 | template <class _Rp> |
1945 | shared_future<_Rp>::~shared_future() { |
1946 | if (__state_) |
1947 | __state_->__release_shared(); |
1948 | } |
1949 | |
1950 | template <class _Rp> |
1951 | shared_future<_Rp>& shared_future<_Rp>::operator=(const shared_future& __rhs) _NOEXCEPT { |
1952 | if (__rhs.__state_) |
1953 | __rhs.__state_->__add_shared(); |
1954 | if (__state_) |
1955 | __state_->__release_shared(); |
1956 | __state_ = __rhs.__state_; |
1957 | return *this; |
1958 | } |
1959 | |
1960 | template <class _Rp> |
1961 | class shared_future<_Rp&> { |
1962 | __assoc_state<_Rp&>* __state_; |
1963 | |
1964 | public: |
1965 | _LIBCPP_HIDE_FROM_ABI shared_future() _NOEXCEPT : __state_(nullptr) {} |
1966 | _LIBCPP_HIDE_FROM_ABI shared_future(const shared_future& __rhs) : __state_(__rhs.__state_) { |
1967 | if (__state_) |
1968 | __state_->__add_shared(); |
1969 | } |
1970 | _LIBCPP_HIDE_FROM_ABI shared_future(future<_Rp&>&& __f) _NOEXCEPT : __state_(__f.__state_) { __f.__state_ = nullptr; } |
1971 | _LIBCPP_HIDE_FROM_ABI shared_future(shared_future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) { |
1972 | __rhs.__state_ = nullptr; |
1973 | } |
1974 | _LIBCPP_HIDE_FROM_ABI ~shared_future(); |
1975 | _LIBCPP_HIDE_FROM_ABI shared_future& operator=(const shared_future& __rhs); |
1976 | _LIBCPP_HIDE_FROM_ABI shared_future& operator=(shared_future&& __rhs) _NOEXCEPT { |
1977 | shared_future(std::move(__rhs)).swap(*this); |
1978 | return *this; |
1979 | } |
1980 | |
1981 | // retrieving the value |
1982 | _LIBCPP_HIDE_FROM_ABI _Rp& get() const { return __state_->copy(); } |
1983 | |
1984 | _LIBCPP_HIDE_FROM_ABI void swap(shared_future& __rhs) _NOEXCEPT { std::swap(__state_, __rhs.__state_); } |
1985 | |
1986 | // functions to check state |
1987 | _LIBCPP_HIDE_FROM_ABI bool valid() const _NOEXCEPT { return __state_ != nullptr; } |
1988 | |
1989 | _LIBCPP_HIDE_FROM_ABI void wait() const { __state_->wait(); } |
1990 | template <class _Rep, class _Period> |
1991 | _LIBCPP_HIDE_FROM_ABI future_status wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const { |
1992 | return __state_->wait_for(__rel_time); |
1993 | } |
1994 | template <class _Clock, class _Duration> |
1995 | _LIBCPP_HIDE_FROM_ABI future_status wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const { |
1996 | return __state_->wait_until(__abs_time); |
1997 | } |
1998 | }; |
1999 | |
2000 | template <class _Rp> |
2001 | shared_future<_Rp&>::~shared_future() { |
2002 | if (__state_) |
2003 | __state_->__release_shared(); |
2004 | } |
2005 | |
2006 | template <class _Rp> |
2007 | shared_future<_Rp&>& shared_future<_Rp&>::operator=(const shared_future& __rhs) { |
2008 | if (__rhs.__state_) |
2009 | __rhs.__state_->__add_shared(); |
2010 | if (__state_) |
2011 | __state_->__release_shared(); |
2012 | __state_ = __rhs.__state_; |
2013 | return *this; |
2014 | } |
2015 | |
2016 | template <> |
2017 | class _LIBCPP_EXPORTED_FROM_ABI shared_future<void> { |
2018 | __assoc_sub_state* __state_; |
2019 | |
2020 | public: |
2021 | _LIBCPP_HIDE_FROM_ABI shared_future() _NOEXCEPT : __state_(nullptr) {} |
2022 | _LIBCPP_HIDE_FROM_ABI shared_future(const shared_future& __rhs) : __state_(__rhs.__state_) { |
2023 | if (__state_) |
2024 | __state_->__add_shared(); |
2025 | } |
2026 | _LIBCPP_HIDE_FROM_ABI shared_future(future<void>&& __f) _NOEXCEPT : __state_(__f.__state_) { __f.__state_ = nullptr; } |
2027 | _LIBCPP_HIDE_FROM_ABI shared_future(shared_future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) { |
2028 | __rhs.__state_ = nullptr; |
2029 | } |
2030 | ~shared_future(); |
2031 | shared_future& operator=(const shared_future& __rhs); |
2032 | _LIBCPP_HIDE_FROM_ABI shared_future& operator=(shared_future&& __rhs) _NOEXCEPT { |
2033 | shared_future(std::move(__rhs)).swap(rhs&: *this); |
2034 | return *this; |
2035 | } |
2036 | |
2037 | // retrieving the value |
2038 | _LIBCPP_HIDE_FROM_ABI void get() const { __state_->copy(); } |
2039 | |
2040 | _LIBCPP_HIDE_FROM_ABI void swap(shared_future& __rhs) _NOEXCEPT { std::swap(x&: __state_, y&: __rhs.__state_); } |
2041 | |
2042 | // functions to check state |
2043 | _LIBCPP_HIDE_FROM_ABI bool valid() const _NOEXCEPT { return __state_ != nullptr; } |
2044 | |
2045 | _LIBCPP_HIDE_FROM_ABI void wait() const { __state_->wait(); } |
2046 | template <class _Rep, class _Period> |
2047 | _LIBCPP_HIDE_FROM_ABI future_status wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const { |
2048 | return __state_->wait_for(__rel_time); |
2049 | } |
2050 | template <class _Clock, class _Duration> |
2051 | _LIBCPP_HIDE_FROM_ABI future_status wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const { |
2052 | return __state_->wait_until(__abs_time); |
2053 | } |
2054 | }; |
2055 | |
2056 | template <class _Rp> |
2057 | inline _LIBCPP_HIDE_FROM_ABI void swap(shared_future<_Rp>& __x, shared_future<_Rp>& __y) _NOEXCEPT { |
2058 | __x.swap(__y); |
2059 | } |
2060 | |
2061 | template <class _Rp> |
2062 | inline shared_future<_Rp> future<_Rp>::share() _NOEXCEPT { |
2063 | return shared_future<_Rp>(std::move(*this)); |
2064 | } |
2065 | |
2066 | template <class _Rp> |
2067 | inline shared_future<_Rp&> future<_Rp&>::share() _NOEXCEPT { |
2068 | return shared_future<_Rp&>(std::move(*this)); |
2069 | } |
2070 | |
2071 | inline shared_future<void> future<void>::share() _NOEXCEPT { return shared_future<void>(std::move(*this)); } |
2072 | |
2073 | _LIBCPP_END_NAMESPACE_STD |
2074 | |
2075 | _LIBCPP_POP_MACROS |
2076 | |
2077 | # endif // _LIBCPP_HAS_THREADS |
2078 | |
2079 | # if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 17 |
2080 | # include <chrono> |
2081 | # endif |
2082 | |
2083 | # if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 |
2084 | # include <atomic> |
2085 | # include <cstdlib> |
2086 | # include <exception> |
2087 | # include <iosfwd> |
2088 | # include <system_error> |
2089 | # include <thread> |
2090 | # endif |
2091 | #endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) |
2092 | |
2093 | #endif // _LIBCPP_FUTURE |
2094 | |