File: | build/source/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp |
Warning: | line 191, column 11 Potential leak of memory pointed to by field '_M_head_impl' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===---- ExecutorProcessControl.cpp -- Executor process control APIs -----===// | |||
2 | // | |||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |||
4 | // See https://llvm.org/LICENSE.txt for license information. | |||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |||
6 | // | |||
7 | //===----------------------------------------------------------------------===// | |||
8 | ||||
9 | #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" | |||
10 | ||||
11 | #include "llvm/ExecutionEngine/Orc/Core.h" | |||
12 | #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h" | |||
13 | #include "llvm/Support/FormatVariadic.h" | |||
14 | #include "llvm/Support/Process.h" | |||
15 | #include "llvm/TargetParser/Host.h" | |||
16 | ||||
17 | #define DEBUG_TYPE"orc" "orc" | |||
18 | ||||
19 | namespace llvm { | |||
20 | namespace orc { | |||
21 | ||||
22 | ExecutorProcessControl::MemoryAccess::~MemoryAccess() = default; | |||
23 | ||||
24 | ExecutorProcessControl::~ExecutorProcessControl() = default; | |||
25 | ||||
26 | SelfExecutorProcessControl::SelfExecutorProcessControl( | |||
27 | std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D, | |||
28 | Triple TargetTriple, unsigned PageSize, | |||
29 | std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) | |||
30 | : ExecutorProcessControl(std::move(SSP), std::move(D)) { | |||
31 | ||||
32 | OwnedMemMgr = std::move(MemMgr); | |||
33 | if (!OwnedMemMgr) | |||
34 | OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>( | |||
35 | sys::Process::getPageSizeEstimate()); | |||
36 | ||||
37 | this->TargetTriple = std::move(TargetTriple); | |||
38 | this->PageSize = PageSize; | |||
39 | this->MemMgr = OwnedMemMgr.get(); | |||
40 | this->MemAccess = this; | |||
41 | this->JDI = {ExecutorAddr::fromPtr(jitDispatchViaWrapperFunctionManager), | |||
42 | ExecutorAddr::fromPtr(this)}; | |||
43 | if (this->TargetTriple.isOSBinFormatMachO()) | |||
44 | GlobalManglingPrefix = '_'; | |||
45 | } | |||
46 | ||||
47 | Expected<std::unique_ptr<SelfExecutorProcessControl>> | |||
48 | SelfExecutorProcessControl::Create( | |||
49 | std::shared_ptr<SymbolStringPool> SSP, | |||
50 | std::unique_ptr<TaskDispatcher> D, | |||
51 | std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) { | |||
52 | ||||
53 | if (!SSP) | |||
54 | SSP = std::make_shared<SymbolStringPool>(); | |||
55 | ||||
56 | if (!D) { | |||
57 | #if LLVM_ENABLE_THREADS1 | |||
58 | D = std::make_unique<DynamicThreadPoolTaskDispatcher>(); | |||
59 | #else | |||
60 | D = std::make_unique<InPlaceTaskDispatcher>(); | |||
61 | #endif | |||
62 | } | |||
63 | ||||
64 | auto PageSize = sys::Process::getPageSize(); | |||
65 | if (!PageSize) | |||
66 | return PageSize.takeError(); | |||
67 | ||||
68 | Triple TT(sys::getProcessTriple()); | |||
69 | ||||
70 | return std::make_unique<SelfExecutorProcessControl>( | |||
71 | std::move(SSP), std::move(D), std::move(TT), *PageSize, | |||
72 | std::move(MemMgr)); | |||
73 | } | |||
74 | ||||
75 | Expected<tpctypes::DylibHandle> | |||
76 | SelfExecutorProcessControl::loadDylib(const char *DylibPath) { | |||
77 | std::string ErrMsg; | |||
78 | auto Dylib = sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg); | |||
79 | if (!Dylib.isValid()) | |||
80 | return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); | |||
81 | return ExecutorAddr::fromPtr(Dylib.getOSSpecificHandle()); | |||
82 | } | |||
83 | ||||
84 | Expected<std::vector<tpctypes::LookupResult>> | |||
85 | SelfExecutorProcessControl::lookupSymbols(ArrayRef<LookupRequest> Request) { | |||
86 | std::vector<tpctypes::LookupResult> R; | |||
87 | ||||
88 | for (auto &Elem : Request) { | |||
89 | sys::DynamicLibrary Dylib(Elem.Handle.toPtr<void *>()); | |||
90 | R.push_back(std::vector<ExecutorAddr>()); | |||
91 | for (auto &KV : Elem.Symbols) { | |||
92 | auto &Sym = KV.first; | |||
93 | std::string Tmp((*Sym).data() + !!GlobalManglingPrefix, | |||
94 | (*Sym).size() - !!GlobalManglingPrefix); | |||
95 | void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str()); | |||
96 | if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) { | |||
97 | // FIXME: Collect all failing symbols before erroring out. | |||
98 | SymbolNameVector MissingSymbols; | |||
99 | MissingSymbols.push_back(Sym); | |||
100 | return make_error<SymbolsNotFound>(SSP, std::move(MissingSymbols)); | |||
101 | } | |||
102 | R.back().push_back(ExecutorAddr::fromPtr(Addr)); | |||
103 | } | |||
104 | } | |||
105 | ||||
106 | return R; | |||
107 | } | |||
108 | ||||
109 | Expected<int32_t> | |||
110 | SelfExecutorProcessControl::runAsMain(ExecutorAddr MainFnAddr, | |||
111 | ArrayRef<std::string> Args) { | |||
112 | using MainTy = int (*)(int, char *[]); | |||
113 | return orc::runAsMain(MainFnAddr.toPtr<MainTy>(), Args); | |||
114 | } | |||
115 | ||||
116 | Expected<int32_t> | |||
117 | SelfExecutorProcessControl::runAsVoidFunction(ExecutorAddr VoidFnAddr) { | |||
118 | using VoidTy = int (*)(); | |||
119 | return orc::runAsVoidFunction(VoidFnAddr.toPtr<VoidTy>()); | |||
120 | } | |||
121 | ||||
122 | Expected<int32_t> | |||
123 | SelfExecutorProcessControl::runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) { | |||
124 | using IntTy = int (*)(int); | |||
125 | return orc::runAsIntFunction(IntFnAddr.toPtr<IntTy>(), Arg); | |||
126 | } | |||
127 | ||||
128 | void SelfExecutorProcessControl::callWrapperAsync(ExecutorAddr WrapperFnAddr, | |||
129 | IncomingWFRHandler SendResult, | |||
130 | ArrayRef<char> ArgBuffer) { | |||
131 | using WrapperFnTy = | |||
132 | shared::CWrapperFunctionResult (*)(const char *Data, size_t Size); | |||
133 | auto *WrapperFn = WrapperFnAddr.toPtr<WrapperFnTy>(); | |||
134 | SendResult(WrapperFn(ArgBuffer.data(), ArgBuffer.size())); | |||
135 | } | |||
136 | ||||
137 | Error SelfExecutorProcessControl::disconnect() { | |||
138 | D->shutdown(); | |||
139 | return Error::success(); | |||
140 | } | |||
141 | ||||
142 | void SelfExecutorProcessControl::writeUInt8sAsync( | |||
143 | ArrayRef<tpctypes::UInt8Write> Ws, WriteResultFn OnWriteComplete) { | |||
144 | for (auto &W : Ws) | |||
145 | *W.Addr.toPtr<uint8_t *>() = W.Value; | |||
146 | OnWriteComplete(Error::success()); | |||
147 | } | |||
148 | ||||
149 | void SelfExecutorProcessControl::writeUInt16sAsync( | |||
150 | ArrayRef<tpctypes::UInt16Write> Ws, WriteResultFn OnWriteComplete) { | |||
151 | for (auto &W : Ws) | |||
152 | *W.Addr.toPtr<uint16_t *>() = W.Value; | |||
153 | OnWriteComplete(Error::success()); | |||
154 | } | |||
155 | ||||
156 | void SelfExecutorProcessControl::writeUInt32sAsync( | |||
157 | ArrayRef<tpctypes::UInt32Write> Ws, WriteResultFn OnWriteComplete) { | |||
158 | for (auto &W : Ws) | |||
159 | *W.Addr.toPtr<uint32_t *>() = W.Value; | |||
160 | OnWriteComplete(Error::success()); | |||
161 | } | |||
162 | ||||
163 | void SelfExecutorProcessControl::writeUInt64sAsync( | |||
164 | ArrayRef<tpctypes::UInt64Write> Ws, WriteResultFn OnWriteComplete) { | |||
165 | for (auto &W : Ws) | |||
166 | *W.Addr.toPtr<uint64_t *>() = W.Value; | |||
167 | OnWriteComplete(Error::success()); | |||
168 | } | |||
169 | ||||
170 | void SelfExecutorProcessControl::writeBuffersAsync( | |||
171 | ArrayRef<tpctypes::BufferWrite> Ws, WriteResultFn OnWriteComplete) { | |||
172 | for (auto &W : Ws) | |||
173 | memcpy(W.Addr.toPtr<char *>(), W.Buffer.data(), W.Buffer.size()); | |||
174 | OnWriteComplete(Error::success()); | |||
175 | } | |||
176 | ||||
177 | shared::CWrapperFunctionResult | |||
178 | SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager( | |||
179 | void *Ctx, const void *FnTag, const char *Data, size_t Size) { | |||
180 | ||||
181 | LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { { dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Size << " byte payload.\n" ; }; } } while (false) | |||
| ||||
182 | dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Sizedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { { dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Size << " byte payload.\n" ; }; } } while (false) | |||
183 | << " byte payload.\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { { dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Size << " byte payload.\n" ; }; } } while (false) | |||
184 | })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { { dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Size << " byte payload.\n" ; }; } } while (false); | |||
185 | ||||
186 | std::promise<shared::WrapperFunctionResult> ResultP; | |||
187 | auto ResultF = ResultP.get_future(); | |||
188 | static_cast<SelfExecutorProcessControl *>(Ctx) | |||
189 | ->getExecutionSession() | |||
190 | .runJITDispatchHandler( | |||
191 | [ResultP = std::move(ResultP)]( | |||
| ||||
192 | shared::WrapperFunctionResult Result) mutable { | |||
193 | ResultP.set_value(std::move(Result)); | |||
194 | }, | |||
195 | ExecutorAddr::fromPtr(FnTag), {Data, Size}); | |||
196 | ||||
197 | return ResultF.get().release(); | |||
198 | } | |||
199 | ||||
200 | } // end namespace orc | |||
201 | } // end namespace llvm |
1 | // <future> -*- C++ -*- |
2 | |
3 | // Copyright (C) 2009-2020 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the |
7 | // terms of the GNU General Public License as published by the |
8 | // Free Software Foundation; either version 3, or (at your option) |
9 | // any later version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /** @file include/future |
26 | * This is a Standard C++ Library header. |
27 | */ |
28 | |
29 | #ifndef _GLIBCXX_FUTURE1 |
30 | #define _GLIBCXX_FUTURE1 1 |
31 | |
32 | #pragma GCC system_header |
33 | |
34 | #if __cplusplus201703L < 201103L |
35 | # include <bits/c++0x_warning.h> |
36 | #else |
37 | |
38 | #include <mutex> |
39 | #include <thread> |
40 | #include <condition_variable> |
41 | #include <system_error> |
42 | #include <atomic> |
43 | #include <bits/atomic_futex.h> |
44 | #include <bits/functexcept.h> |
45 | #include <bits/invoke.h> |
46 | #include <bits/unique_ptr.h> |
47 | #include <bits/shared_ptr.h> |
48 | #include <bits/std_function.h> |
49 | #include <bits/uses_allocator.h> |
50 | #include <bits/allocated_ptr.h> |
51 | #include <ext/aligned_buffer.h> |
52 | |
53 | namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default"))) |
54 | { |
55 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
56 | |
57 | /** |
58 | * @defgroup futures Futures |
59 | * @ingroup concurrency |
60 | * |
61 | * Classes for futures support. |
62 | * @{ |
63 | */ |
64 | |
65 | /// Error code for futures |
66 | enum class future_errc |
67 | { |
68 | future_already_retrieved = 1, |
69 | promise_already_satisfied, |
70 | no_state, |
71 | broken_promise |
72 | }; |
73 | |
74 | /// Specialization. |
75 | template<> |
76 | struct is_error_code_enum<future_errc> : public true_type { }; |
77 | |
78 | /// Points to a statically-allocated object derived from error_category. |
79 | const error_category& |
80 | future_category() noexcept; |
81 | |
82 | /// Overload for make_error_code. |
83 | inline error_code |
84 | make_error_code(future_errc __errc) noexcept |
85 | { return error_code(static_cast<int>(__errc), future_category()); } |
86 | |
87 | /// Overload for make_error_condition. |
88 | inline error_condition |
89 | make_error_condition(future_errc __errc) noexcept |
90 | { return error_condition(static_cast<int>(__errc), future_category()); } |
91 | |
92 | /** |
93 | * @brief Exception type thrown by futures. |
94 | * @ingroup exceptions |
95 | */ |
96 | class future_error : public logic_error |
97 | { |
98 | public: |
99 | explicit |
100 | future_error(future_errc __errc) |
101 | : future_error(std::make_error_code(__errc)) |
102 | { } |
103 | |
104 | virtual ~future_error() noexcept; |
105 | |
106 | virtual const char* |
107 | what() const noexcept; |
108 | |
109 | const error_code& |
110 | code() const noexcept { return _M_code; } |
111 | |
112 | private: |
113 | explicit |
114 | future_error(error_code __ec) |
115 | : logic_error("std::future_error: " + __ec.message()), _M_code(__ec) |
116 | { } |
117 | |
118 | friend void __throw_future_error(int); |
119 | |
120 | error_code _M_code; |
121 | }; |
122 | |
123 | // Forward declarations. |
124 | template<typename _Res> |
125 | class future; |
126 | |
127 | template<typename _Res> |
128 | class shared_future; |
129 | |
130 | template<typename _Signature> |
131 | class packaged_task; |
132 | |
133 | template<typename _Res> |
134 | class promise; |
135 | |
136 | /// Launch code for futures |
137 | enum class launch |
138 | { |
139 | async = 1, |
140 | deferred = 2 |
141 | }; |
142 | |
143 | constexpr launch operator&(launch __x, launch __y) |
144 | { |
145 | return static_cast<launch>( |
146 | static_cast<int>(__x) & static_cast<int>(__y)); |
147 | } |
148 | |
149 | constexpr launch operator|(launch __x, launch __y) |
150 | { |
151 | return static_cast<launch>( |
152 | static_cast<int>(__x) | static_cast<int>(__y)); |
153 | } |
154 | |
155 | constexpr launch operator^(launch __x, launch __y) |
156 | { |
157 | return static_cast<launch>( |
158 | static_cast<int>(__x) ^ static_cast<int>(__y)); |
159 | } |
160 | |
161 | constexpr launch operator~(launch __x) |
162 | { return static_cast<launch>(~static_cast<int>(__x)); } |
163 | |
164 | inline launch& operator&=(launch& __x, launch __y) |
165 | { return __x = __x & __y; } |
166 | |
167 | inline launch& operator|=(launch& __x, launch __y) |
168 | { return __x = __x | __y; } |
169 | |
170 | inline launch& operator^=(launch& __x, launch __y) |
171 | { return __x = __x ^ __y; } |
172 | |
173 | /// Status code for futures |
174 | enum class future_status |
175 | { |
176 | ready, |
177 | timeout, |
178 | deferred |
179 | }; |
180 | |
181 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
182 | // 2021. Further incorrect usages of result_of |
183 | template<typename _Fn, typename... _Args> |
184 | using __async_result_of = typename __invoke_result< |
185 | typename decay<_Fn>::type, typename decay<_Args>::type...>::type; |
186 | |
187 | template<typename _Fn, typename... _Args> |
188 | future<__async_result_of<_Fn, _Args...>> |
189 | async(launch __policy, _Fn&& __fn, _Args&&... __args); |
190 | |
191 | template<typename _Fn, typename... _Args> |
192 | future<__async_result_of<_Fn, _Args...>> |
193 | async(_Fn&& __fn, _Args&&... __args); |
194 | |
195 | #if defined(_GLIBCXX_HAS_GTHREADS1) |
196 | |
197 | /// Base class and enclosing scope. |
198 | struct __future_base |
199 | { |
200 | /// Base class for results. |
201 | struct _Result_base |
202 | { |
203 | exception_ptr _M_error; |
204 | |
205 | _Result_base(const _Result_base&) = delete; |
206 | _Result_base& operator=(const _Result_base&) = delete; |
207 | |
208 | // _M_destroy() allows derived classes to control deallocation |
209 | virtual void _M_destroy() = 0; |
210 | |
211 | struct _Deleter |
212 | { |
213 | void operator()(_Result_base* __fr) const { __fr->_M_destroy(); } |
214 | }; |
215 | |
216 | protected: |
217 | _Result_base(); |
218 | virtual ~_Result_base(); |
219 | }; |
220 | |
221 | /// A unique_ptr for result objects. |
222 | template<typename _Res> |
223 | using _Ptr = unique_ptr<_Res, _Result_base::_Deleter>; |
224 | |
225 | /// A result object that has storage for an object of type _Res. |
226 | template<typename _Res> |
227 | struct _Result : _Result_base |
228 | { |
229 | private: |
230 | __gnu_cxx::__aligned_buffer<_Res> _M_storage; |
231 | bool _M_initialized; |
232 | |
233 | public: |
234 | typedef _Res result_type; |
235 | |
236 | _Result() noexcept : _M_initialized() { } |
237 | |
238 | ~_Result() |
239 | { |
240 | if (_M_initialized) |
241 | _M_value().~_Res(); |
242 | } |
243 | |
244 | // Return lvalue, future will add const or rvalue-reference |
245 | _Res& |
246 | _M_value() noexcept { return *_M_storage._M_ptr(); } |
247 | |
248 | void |
249 | _M_set(const _Res& __res) |
250 | { |
251 | ::new (_M_storage._M_addr()) _Res(__res); |
252 | _M_initialized = true; |
253 | } |
254 | |
255 | void |
256 | _M_set(_Res&& __res) |
257 | { |
258 | ::new (_M_storage._M_addr()) _Res(std::move(__res)); |
259 | _M_initialized = true; |
260 | } |
261 | |
262 | private: |
263 | void _M_destroy() { delete this; } |
264 | }; |
265 | |
266 | /// A result object that uses an allocator. |
267 | template<typename _Res, typename _Alloc> |
268 | struct _Result_alloc final : _Result<_Res>, _Alloc |
269 | { |
270 | using __allocator_type = __alloc_rebind<_Alloc, _Result_alloc>; |
271 | |
272 | explicit |
273 | _Result_alloc(const _Alloc& __a) : _Result<_Res>(), _Alloc(__a) |
274 | { } |
275 | |
276 | private: |
277 | void _M_destroy() |
278 | { |
279 | __allocator_type __a(*this); |
280 | __allocated_ptr<__allocator_type> __guard_ptr{ __a, this }; |
281 | this->~_Result_alloc(); |
282 | } |
283 | }; |
284 | |
285 | // Create a result object that uses an allocator. |
286 | template<typename _Res, typename _Allocator> |
287 | static _Ptr<_Result_alloc<_Res, _Allocator>> |
288 | _S_allocate_result(const _Allocator& __a) |
289 | { |
290 | using __result_type = _Result_alloc<_Res, _Allocator>; |
291 | typename __result_type::__allocator_type __a2(__a); |
292 | auto __guard = std::__allocate_guarded(__a2); |
293 | __result_type* __p = ::new((void*)__guard.get()) __result_type{__a}; |
294 | __guard = nullptr; |
295 | return _Ptr<__result_type>(__p); |
296 | } |
297 | |
298 | // Keep it simple for std::allocator. |
299 | template<typename _Res, typename _Tp> |
300 | static _Ptr<_Result<_Res>> |
301 | _S_allocate_result(const std::allocator<_Tp>& __a) |
302 | { |
303 | return _Ptr<_Result<_Res>>(new _Result<_Res>); |
304 | } |
305 | |
306 | // Base class for various types of shared state created by an |
307 | // asynchronous provider (such as a std::promise) and shared with one |
308 | // or more associated futures. |
309 | class _State_baseV2 |
310 | { |
311 | typedef _Ptr<_Result_base> _Ptr_type; |
312 | |
313 | enum _Status : unsigned { |
314 | __not_ready, |
315 | __ready |
316 | }; |
317 | |
318 | _Ptr_type _M_result; |
319 | __atomic_futex_unsigned<> _M_status; |
320 | atomic_flag _M_retrieved = ATOMIC_FLAG_INIT{ 0 }; |
321 | once_flag _M_once; |
322 | |
323 | public: |
324 | _State_baseV2() noexcept : _M_result(), _M_status(_Status::__not_ready) |
325 | { } |
326 | _State_baseV2(const _State_baseV2&) = delete; |
327 | _State_baseV2& operator=(const _State_baseV2&) = delete; |
328 | virtual ~_State_baseV2() = default; |
329 | |
330 | _Result_base& |
331 | wait() |
332 | { |
333 | // Run any deferred function or join any asynchronous thread: |
334 | _M_complete_async(); |
335 | // Acquire MO makes sure this synchronizes with the thread that made |
336 | // the future ready. |
337 | _M_status._M_load_when_equal(_Status::__ready, memory_order_acquire); |
338 | return *_M_result; |
339 | } |
340 | |
341 | template<typename _Rep, typename _Period> |
342 | future_status |
343 | wait_for(const chrono::duration<_Rep, _Period>& __rel) |
344 | { |
345 | // First, check if the future has been made ready. Use acquire MO |
346 | // to synchronize with the thread that made it ready. |
347 | if (_M_status._M_load(memory_order_acquire) == _Status::__ready) |
348 | return future_status::ready; |
349 | |
350 | if (_M_is_deferred_future()) |
351 | return future_status::deferred; |
352 | |
353 | // Don't wait unless the relative time is greater than zero. |
354 | if (__rel > __rel.zero() |
355 | && _M_status._M_load_when_equal_for(_Status::__ready, |
356 | memory_order_acquire, |
357 | __rel)) |
358 | { |
359 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
360 | // 2100. timed waiting functions must also join |
361 | // This call is a no-op by default except on an async future, |
362 | // in which case the async thread is joined. It's also not a |
363 | // no-op for a deferred future, but such a future will never |
364 | // reach this point because it returns future_status::deferred |
365 | // instead of waiting for the future to become ready (see |
366 | // above). Async futures synchronize in this call, so we need |
367 | // no further synchronization here. |
368 | _M_complete_async(); |
369 | |
370 | return future_status::ready; |
371 | } |
372 | return future_status::timeout; |
373 | } |
374 | |
375 | template<typename _Clock, typename _Duration> |
376 | future_status |
377 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs) |
378 | { |
379 | #if __cplusplus201703L > 201703L |
380 | static_assert(chrono::is_clock_v<_Clock>); |
381 | #endif |
382 | // First, check if the future has been made ready. Use acquire MO |
383 | // to synchronize with the thread that made it ready. |
384 | if (_M_status._M_load(memory_order_acquire) == _Status::__ready) |
385 | return future_status::ready; |
386 | |
387 | if (_M_is_deferred_future()) |
388 | return future_status::deferred; |
389 | |
390 | if (_M_status._M_load_when_equal_until(_Status::__ready, |
391 | memory_order_acquire, |
392 | __abs)) |
393 | { |
394 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
395 | // 2100. timed waiting functions must also join |
396 | // See wait_for(...) above. |
397 | _M_complete_async(); |
398 | |
399 | return future_status::ready; |
400 | } |
401 | return future_status::timeout; |
402 | } |
403 | |
404 | // Provide a result to the shared state and make it ready. |
405 | // Calls at most once: _M_result = __res(); |
406 | void |
407 | _M_set_result(function<_Ptr_type()> __res, bool __ignore_failure = false) |
408 | { |
409 | bool __did_set = false; |
410 | // all calls to this function are serialized, |
411 | // side-effects of invoking __res only happen once |
412 | call_once(_M_once, &_State_baseV2::_M_do_set, this, |
413 | std::__addressof(__res), std::__addressof(__did_set)); |
414 | if (__did_set) |
415 | // Use release MO to synchronize with observers of the ready state. |
416 | _M_status._M_store_notify_all(_Status::__ready, |
417 | memory_order_release); |
418 | else if (!__ignore_failure) |
419 | __throw_future_error(int(future_errc::promise_already_satisfied)); |
420 | } |
421 | |
422 | // Provide a result to the shared state but delay making it ready |
423 | // until the calling thread exits. |
424 | // Calls at most once: _M_result = __res(); |
425 | void |
426 | _M_set_delayed_result(function<_Ptr_type()> __res, |
427 | weak_ptr<_State_baseV2> __self) |
428 | { |
429 | bool __did_set = false; |
430 | unique_ptr<_Make_ready> __mr{new _Make_ready}; |
431 | // all calls to this function are serialized, |
432 | // side-effects of invoking __res only happen once |
433 | call_once(_M_once, &_State_baseV2::_M_do_set, this, |
434 | std::__addressof(__res), std::__addressof(__did_set)); |
435 | if (!__did_set) |
436 | __throw_future_error(int(future_errc::promise_already_satisfied)); |
437 | __mr->_M_shared_state = std::move(__self); |
438 | __mr->_M_set(); |
439 | __mr.release(); |
440 | } |
441 | |
442 | // Abandon this shared state. |
443 | void |
444 | _M_break_promise(_Ptr_type __res) |
445 | { |
446 | if (static_cast<bool>(__res)) |
447 | { |
448 | __res->_M_error = |
449 | make_exception_ptr(future_error(future_errc::broken_promise)); |
450 | // This function is only called when the last asynchronous result |
451 | // provider is abandoning this shared state, so noone can be |
452 | // trying to make the shared state ready at the same time, and |
453 | // we can access _M_result directly instead of through call_once. |
454 | _M_result.swap(__res); |
455 | // Use release MO to synchronize with observers of the ready state. |
456 | _M_status._M_store_notify_all(_Status::__ready, |
457 | memory_order_release); |
458 | } |
459 | } |
460 | |
461 | // Called when this object is first passed to a future. |
462 | void |
463 | _M_set_retrieved_flag() |
464 | { |
465 | if (_M_retrieved.test_and_set()) |
466 | __throw_future_error(int(future_errc::future_already_retrieved)); |
467 | } |
468 | |
469 | template<typename _Res, typename _Arg> |
470 | struct _Setter; |
471 | |
472 | // set lvalues |
473 | template<typename _Res, typename _Arg> |
474 | struct _Setter<_Res, _Arg&> |
475 | { |
476 | // check this is only used by promise<R>::set_value(const R&) |
477 | // or promise<R&>::set_value(R&) |
478 | static_assert(is_same<_Res, _Arg&>::value // promise<R&> |
479 | || is_same<const _Res, _Arg>::value, // promise<R> |
480 | "Invalid specialisation"); |
481 | |
482 | // Used by std::promise to copy construct the result. |
483 | typename promise<_Res>::_Ptr_type operator()() const |
484 | { |
485 | _M_promise->_M_storage->_M_set(*_M_arg); |
486 | return std::move(_M_promise->_M_storage); |
487 | } |
488 | promise<_Res>* _M_promise; |
489 | _Arg* _M_arg; |
490 | }; |
491 | |
492 | // set rvalues |
493 | template<typename _Res> |
494 | struct _Setter<_Res, _Res&&> |
495 | { |
496 | // Used by std::promise to move construct the result. |
497 | typename promise<_Res>::_Ptr_type operator()() const |
498 | { |
499 | _M_promise->_M_storage->_M_set(std::move(*_M_arg)); |
500 | return std::move(_M_promise->_M_storage); |
501 | } |
502 | promise<_Res>* _M_promise; |
503 | _Res* _M_arg; |
504 | }; |
505 | |
506 | // set void |
507 | template<typename _Res> |
508 | struct _Setter<_Res, void> |
509 | { |
510 | static_assert(is_void<_Res>::value, "Only used for promise<void>"); |
511 | |
512 | typename promise<_Res>::_Ptr_type operator()() const |
513 | { return std::move(_M_promise->_M_storage); } |
514 | |
515 | promise<_Res>* _M_promise; |
516 | }; |
517 | |
518 | struct __exception_ptr_tag { }; |
519 | |
520 | // set exceptions |
521 | template<typename _Res> |
522 | struct _Setter<_Res, __exception_ptr_tag> |
523 | { |
524 | // Used by std::promise to store an exception as the result. |
525 | typename promise<_Res>::_Ptr_type operator()() const |
526 | { |
527 | _M_promise->_M_storage->_M_error = *_M_ex; |
528 | return std::move(_M_promise->_M_storage); |
529 | } |
530 | |
531 | promise<_Res>* _M_promise; |
532 | exception_ptr* _M_ex; |
533 | }; |
534 | |
535 | template<typename _Res, typename _Arg> |
536 | static _Setter<_Res, _Arg&&> |
537 | __setter(promise<_Res>* __prom, _Arg&& __arg) |
538 | { |
539 | _S_check(__prom->_M_future); |
540 | return _Setter<_Res, _Arg&&>{ __prom, std::__addressof(__arg) }; |
541 | } |
542 | |
543 | template<typename _Res> |
544 | static _Setter<_Res, __exception_ptr_tag> |
545 | __setter(exception_ptr& __ex, promise<_Res>* __prom) |
546 | { |
547 | _S_check(__prom->_M_future); |
548 | return _Setter<_Res, __exception_ptr_tag>{ __prom, &__ex }; |
549 | } |
550 | |
551 | template<typename _Res> |
552 | static _Setter<_Res, void> |
553 | __setter(promise<_Res>* __prom) |
554 | { |
555 | _S_check(__prom->_M_future); |
556 | return _Setter<_Res, void>{ __prom }; |
557 | } |
558 | |
559 | template<typename _Tp> |
560 | static void |
561 | _S_check(const shared_ptr<_Tp>& __p) |
562 | { |
563 | if (!static_cast<bool>(__p)) |
564 | __throw_future_error((int)future_errc::no_state); |
565 | } |
566 | |
567 | private: |
568 | // The function invoked with std::call_once(_M_once, ...). |
569 | void |
570 | _M_do_set(function<_Ptr_type()>* __f, bool* __did_set) |
571 | { |
572 | _Ptr_type __res = (*__f)(); |
573 | // Notify the caller that we did try to set; if we do not throw an |
574 | // exception, the caller will be aware that it did set (e.g., see |
575 | // _M_set_result). |
576 | *__did_set = true; |
577 | _M_result.swap(__res); // nothrow |
578 | } |
579 | |
580 | // Wait for completion of async function. |
581 | virtual void _M_complete_async() { } |
582 | |
583 | // Return true if state corresponds to a deferred function. |
584 | virtual bool _M_is_deferred_future() const { return false; } |
585 | |
586 | struct _Make_ready final : __at_thread_exit_elt |
587 | { |
588 | weak_ptr<_State_baseV2> _M_shared_state; |
589 | static void _S_run(void*); |
590 | void _M_set(); |
591 | }; |
592 | }; |
593 | |
594 | #ifdef _GLIBCXX_ASYNC_ABI_COMPAT |
595 | class _State_base; |
596 | class _Async_state_common; |
597 | #else |
598 | using _State_base = _State_baseV2; |
599 | class _Async_state_commonV2; |
600 | #endif |
601 | |
602 | template<typename _BoundFn, |
603 | typename _Res = decltype(std::declval<_BoundFn&>()())> |
604 | class _Deferred_state; |
605 | |
606 | template<typename _BoundFn, |
607 | typename _Res = decltype(std::declval<_BoundFn&>()())> |
608 | class _Async_state_impl; |
609 | |
610 | template<typename _Signature> |
611 | class _Task_state_base; |
612 | |
613 | template<typename _Fn, typename _Alloc, typename _Signature> |
614 | class _Task_state; |
615 | |
616 | template<typename _BoundFn> |
617 | static std::shared_ptr<_State_base> |
618 | _S_make_deferred_state(_BoundFn&& __fn); |
619 | |
620 | template<typename _BoundFn> |
621 | static std::shared_ptr<_State_base> |
622 | _S_make_async_state(_BoundFn&& __fn); |
623 | |
624 | template<typename _Res_ptr, typename _Fn, |
625 | typename _Res = typename _Res_ptr::element_type::result_type> |
626 | struct _Task_setter; |
627 | |
628 | template<typename _Res_ptr, typename _BoundFn> |
629 | static _Task_setter<_Res_ptr, _BoundFn> |
630 | _S_task_setter(_Res_ptr& __ptr, _BoundFn& __call) |
631 | { |
632 | return { std::__addressof(__ptr), std::__addressof(__call) }; |
633 | } |
634 | }; |
635 | |
636 | /// Partial specialization for reference types. |
637 | template<typename _Res> |
638 | struct __future_base::_Result<_Res&> : __future_base::_Result_base |
639 | { |
640 | typedef _Res& result_type; |
641 | |
642 | _Result() noexcept : _M_value_ptr() { } |
643 | |
644 | void |
645 | _M_set(_Res& __res) noexcept |
646 | { _M_value_ptr = std::addressof(__res); } |
647 | |
648 | _Res& _M_get() noexcept { return *_M_value_ptr; } |
649 | |
650 | private: |
651 | _Res* _M_value_ptr; |
652 | |
653 | void _M_destroy() { delete this; } |
654 | }; |
655 | |
656 | /// Explicit specialization for void. |
657 | template<> |
658 | struct __future_base::_Result<void> : __future_base::_Result_base |
659 | { |
660 | typedef void result_type; |
661 | |
662 | private: |
663 | void _M_destroy() { delete this; } |
664 | }; |
665 | |
666 | #ifndef _GLIBCXX_ASYNC_ABI_COMPAT |
667 | |
668 | // Allow _Setter objects to be stored locally in std::function |
669 | template<typename _Res, typename _Arg> |
670 | struct __is_location_invariant |
671 | <__future_base::_State_base::_Setter<_Res, _Arg>> |
672 | : true_type { }; |
673 | |
674 | // Allow _Task_setter objects to be stored locally in std::function |
675 | template<typename _Res_ptr, typename _Fn, typename _Res> |
676 | struct __is_location_invariant |
677 | <__future_base::_Task_setter<_Res_ptr, _Fn, _Res>> |
678 | : true_type { }; |
679 | |
680 | /// Common implementation for future and shared_future. |
681 | template<typename _Res> |
682 | class __basic_future : public __future_base |
683 | { |
684 | protected: |
685 | typedef shared_ptr<_State_base> __state_type; |
686 | typedef __future_base::_Result<_Res>& __result_type; |
687 | |
688 | private: |
689 | __state_type _M_state; |
690 | |
691 | public: |
692 | // Disable copying. |
693 | __basic_future(const __basic_future&) = delete; |
694 | __basic_future& operator=(const __basic_future&) = delete; |
695 | |
696 | bool |
697 | valid() const noexcept { return static_cast<bool>(_M_state); } |
698 | |
699 | void |
700 | wait() const |
701 | { |
702 | _State_base::_S_check(_M_state); |
703 | _M_state->wait(); |
704 | } |
705 | |
706 | template<typename _Rep, typename _Period> |
707 | future_status |
708 | wait_for(const chrono::duration<_Rep, _Period>& __rel) const |
709 | { |
710 | _State_base::_S_check(_M_state); |
711 | return _M_state->wait_for(__rel); |
712 | } |
713 | |
714 | template<typename _Clock, typename _Duration> |
715 | future_status |
716 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs) const |
717 | { |
718 | _State_base::_S_check(_M_state); |
719 | return _M_state->wait_until(__abs); |
720 | } |
721 | |
722 | protected: |
723 | /// Wait for the state to be ready and rethrow any stored exception |
724 | __result_type |
725 | _M_get_result() const |
726 | { |
727 | _State_base::_S_check(_M_state); |
728 | _Result_base& __res = _M_state->wait(); |
729 | if (!(__res._M_error == 0)) |
730 | rethrow_exception(__res._M_error); |
731 | return static_cast<__result_type>(__res); |
732 | } |
733 | |
734 | void _M_swap(__basic_future& __that) noexcept |
735 | { |
736 | _M_state.swap(__that._M_state); |
737 | } |
738 | |
739 | // Construction of a future by promise::get_future() |
740 | explicit |
741 | __basic_future(const __state_type& __state) : _M_state(__state) |
742 | { |
743 | _State_base::_S_check(_M_state); |
744 | _M_state->_M_set_retrieved_flag(); |
745 | } |
746 | |
747 | // Copy construction from a shared_future |
748 | explicit |
749 | __basic_future(const shared_future<_Res>&) noexcept; |
750 | |
751 | // Move construction from a shared_future |
752 | explicit |
753 | __basic_future(shared_future<_Res>&&) noexcept; |
754 | |
755 | // Move construction from a future |
756 | explicit |
757 | __basic_future(future<_Res>&&) noexcept; |
758 | |
759 | constexpr __basic_future() noexcept : _M_state() { } |
760 | |
761 | struct _Reset |
762 | { |
763 | explicit _Reset(__basic_future& __fut) noexcept : _M_fut(__fut) { } |
764 | ~_Reset() { _M_fut._M_state.reset(); } |
765 | __basic_future& _M_fut; |
766 | }; |
767 | }; |
768 | |
769 | |
770 | /// Primary template for future. |
771 | template<typename _Res> |
772 | class future : public __basic_future<_Res> |
773 | { |
774 | friend class promise<_Res>; |
775 | template<typename> friend class packaged_task; |
776 | template<typename _Fn, typename... _Args> |
777 | friend future<__async_result_of<_Fn, _Args...>> |
778 | async(launch, _Fn&&, _Args&&...); |
779 | |
780 | typedef __basic_future<_Res> _Base_type; |
781 | typedef typename _Base_type::__state_type __state_type; |
782 | |
783 | explicit |
784 | future(const __state_type& __state) : _Base_type(__state) { } |
785 | |
786 | public: |
787 | constexpr future() noexcept : _Base_type() { } |
788 | |
789 | /// Move constructor |
790 | future(future&& __uf) noexcept : _Base_type(std::move(__uf)) { } |
791 | |
792 | // Disable copying |
793 | future(const future&) = delete; |
794 | future& operator=(const future&) = delete; |
795 | |
796 | future& operator=(future&& __fut) noexcept |
797 | { |
798 | future(std::move(__fut))._M_swap(*this); |
799 | return *this; |
800 | } |
801 | |
802 | /// Retrieving the value |
803 | _Res |
804 | get() |
805 | { |
806 | typename _Base_type::_Reset __reset(*this); |
807 | return std::move(this->_M_get_result()._M_value()); |
808 | } |
809 | |
810 | shared_future<_Res> share() noexcept; |
811 | }; |
812 | |
813 | /// Partial specialization for future<R&> |
814 | template<typename _Res> |
815 | class future<_Res&> : public __basic_future<_Res&> |
816 | { |
817 | friend class promise<_Res&>; |
818 | template<typename> friend class packaged_task; |
819 | template<typename _Fn, typename... _Args> |
820 | friend future<__async_result_of<_Fn, _Args...>> |
821 | async(launch, _Fn&&, _Args&&...); |
822 | |
823 | typedef __basic_future<_Res&> _Base_type; |
824 | typedef typename _Base_type::__state_type __state_type; |
825 | |
826 | explicit |
827 | future(const __state_type& __state) : _Base_type(__state) { } |
828 | |
829 | public: |
830 | constexpr future() noexcept : _Base_type() { } |
831 | |
832 | /// Move constructor |
833 | future(future&& __uf) noexcept : _Base_type(std::move(__uf)) { } |
834 | |
835 | // Disable copying |
836 | future(const future&) = delete; |
837 | future& operator=(const future&) = delete; |
838 | |
839 | future& operator=(future&& __fut) noexcept |
840 | { |
841 | future(std::move(__fut))._M_swap(*this); |
842 | return *this; |
843 | } |
844 | |
845 | /// Retrieving the value |
846 | _Res& |
847 | get() |
848 | { |
849 | typename _Base_type::_Reset __reset(*this); |
850 | return this->_M_get_result()._M_get(); |
851 | } |
852 | |
853 | shared_future<_Res&> share() noexcept; |
854 | }; |
855 | |
856 | /// Explicit specialization for future<void> |
857 | template<> |
858 | class future<void> : public __basic_future<void> |
859 | { |
860 | friend class promise<void>; |
861 | template<typename> friend class packaged_task; |
862 | template<typename _Fn, typename... _Args> |
863 | friend future<__async_result_of<_Fn, _Args...>> |
864 | async(launch, _Fn&&, _Args&&...); |
865 | |
866 | typedef __basic_future<void> _Base_type; |
867 | typedef typename _Base_type::__state_type __state_type; |
868 | |
869 | explicit |
870 | future(const __state_type& __state) : _Base_type(__state) { } |
871 | |
872 | public: |
873 | constexpr future() noexcept : _Base_type() { } |
874 | |
875 | /// Move constructor |
876 | future(future&& __uf) noexcept : _Base_type(std::move(__uf)) { } |
877 | |
878 | // Disable copying |
879 | future(const future&) = delete; |
880 | future& operator=(const future&) = delete; |
881 | |
882 | future& operator=(future&& __fut) noexcept |
883 | { |
884 | future(std::move(__fut))._M_swap(*this); |
885 | return *this; |
886 | } |
887 | |
888 | /// Retrieving the value |
889 | void |
890 | get() |
891 | { |
892 | typename _Base_type::_Reset __reset(*this); |
893 | this->_M_get_result(); |
894 | } |
895 | |
896 | shared_future<void> share() noexcept; |
897 | }; |
898 | |
899 | |
900 | /// Primary template for shared_future. |
901 | template<typename _Res> |
902 | class shared_future : public __basic_future<_Res> |
903 | { |
904 | typedef __basic_future<_Res> _Base_type; |
905 | |
906 | public: |
907 | constexpr shared_future() noexcept : _Base_type() { } |
908 | |
909 | /// Copy constructor |
910 | shared_future(const shared_future& __sf) noexcept : _Base_type(__sf) { } |
911 | |
912 | /// Construct from a future rvalue |
913 | shared_future(future<_Res>&& __uf) noexcept |
914 | : _Base_type(std::move(__uf)) |
915 | { } |
916 | |
917 | /// Construct from a shared_future rvalue |
918 | shared_future(shared_future&& __sf) noexcept |
919 | : _Base_type(std::move(__sf)) |
920 | { } |
921 | |
922 | shared_future& operator=(const shared_future& __sf) noexcept |
923 | { |
924 | shared_future(__sf)._M_swap(*this); |
925 | return *this; |
926 | } |
927 | |
928 | shared_future& operator=(shared_future&& __sf) noexcept |
929 | { |
930 | shared_future(std::move(__sf))._M_swap(*this); |
931 | return *this; |
932 | } |
933 | |
934 | /// Retrieving the value |
935 | const _Res& |
936 | get() const { return this->_M_get_result()._M_value(); } |
937 | }; |
938 | |
939 | /// Partial specialization for shared_future<R&> |
940 | template<typename _Res> |
941 | class shared_future<_Res&> : public __basic_future<_Res&> |
942 | { |
943 | typedef __basic_future<_Res&> _Base_type; |
944 | |
945 | public: |
946 | constexpr shared_future() noexcept : _Base_type() { } |
947 | |
948 | /// Copy constructor |
949 | shared_future(const shared_future& __sf) : _Base_type(__sf) { } |
950 | |
951 | /// Construct from a future rvalue |
952 | shared_future(future<_Res&>&& __uf) noexcept |
953 | : _Base_type(std::move(__uf)) |
954 | { } |
955 | |
956 | /// Construct from a shared_future rvalue |
957 | shared_future(shared_future&& __sf) noexcept |
958 | : _Base_type(std::move(__sf)) |
959 | { } |
960 | |
961 | shared_future& operator=(const shared_future& __sf) |
962 | { |
963 | shared_future(__sf)._M_swap(*this); |
964 | return *this; |
965 | } |
966 | |
967 | shared_future& operator=(shared_future&& __sf) noexcept |
968 | { |
969 | shared_future(std::move(__sf))._M_swap(*this); |
970 | return *this; |
971 | } |
972 | |
973 | /// Retrieving the value |
974 | _Res& |
975 | get() const { return this->_M_get_result()._M_get(); } |
976 | }; |
977 | |
978 | /// Explicit specialization for shared_future<void> |
979 | template<> |
980 | class shared_future<void> : public __basic_future<void> |
981 | { |
982 | typedef __basic_future<void> _Base_type; |
983 | |
984 | public: |
985 | constexpr shared_future() noexcept : _Base_type() { } |
986 | |
987 | /// Copy constructor |
988 | shared_future(const shared_future& __sf) : _Base_type(__sf) { } |
989 | |
990 | /// Construct from a future rvalue |
991 | shared_future(future<void>&& __uf) noexcept |
992 | : _Base_type(std::move(__uf)) |
993 | { } |
994 | |
995 | /// Construct from a shared_future rvalue |
996 | shared_future(shared_future&& __sf) noexcept |
997 | : _Base_type(std::move(__sf)) |
998 | { } |
999 | |
1000 | shared_future& operator=(const shared_future& __sf) |
1001 | { |
1002 | shared_future(__sf)._M_swap(*this); |
1003 | return *this; |
1004 | } |
1005 | |
1006 | shared_future& operator=(shared_future&& __sf) noexcept |
1007 | { |
1008 | shared_future(std::move(__sf))._M_swap(*this); |
1009 | return *this; |
1010 | } |
1011 | |
1012 | // Retrieving the value |
1013 | void |
1014 | get() const { this->_M_get_result(); } |
1015 | }; |
1016 | |
1017 | // Now we can define the protected __basic_future constructors. |
1018 | template<typename _Res> |
1019 | inline __basic_future<_Res>:: |
1020 | __basic_future(const shared_future<_Res>& __sf) noexcept |
1021 | : _M_state(__sf._M_state) |
1022 | { } |
1023 | |
1024 | template<typename _Res> |
1025 | inline __basic_future<_Res>:: |
1026 | __basic_future(shared_future<_Res>&& __sf) noexcept |
1027 | : _M_state(std::move(__sf._M_state)) |
1028 | { } |
1029 | |
1030 | template<typename _Res> |
1031 | inline __basic_future<_Res>:: |
1032 | __basic_future(future<_Res>&& __uf) noexcept |
1033 | : _M_state(std::move(__uf._M_state)) |
1034 | { } |
1035 | |
1036 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1037 | // 2556. Wide contract for future::share() |
1038 | template<typename _Res> |
1039 | inline shared_future<_Res> |
1040 | future<_Res>::share() noexcept |
1041 | { return shared_future<_Res>(std::move(*this)); } |
1042 | |
1043 | template<typename _Res> |
1044 | inline shared_future<_Res&> |
1045 | future<_Res&>::share() noexcept |
1046 | { return shared_future<_Res&>(std::move(*this)); } |
1047 | |
1048 | inline shared_future<void> |
1049 | future<void>::share() noexcept |
1050 | { return shared_future<void>(std::move(*this)); } |
1051 | |
1052 | /// Primary template for promise |
1053 | template<typename _Res> |
1054 | class promise |
1055 | { |
1056 | typedef __future_base::_State_base _State; |
1057 | typedef __future_base::_Result<_Res> _Res_type; |
1058 | typedef __future_base::_Ptr<_Res_type> _Ptr_type; |
1059 | template<typename, typename> friend class _State::_Setter; |
1060 | friend _State; |
1061 | |
1062 | shared_ptr<_State> _M_future; |
1063 | _Ptr_type _M_storage; |
1064 | |
1065 | public: |
1066 | promise() |
1067 | : _M_future(std::make_shared<_State>()), |
1068 | _M_storage(new _Res_type()) |
1069 | { } |
1070 | |
1071 | promise(promise&& __rhs) noexcept |
1072 | : _M_future(std::move(__rhs._M_future)), |
1073 | _M_storage(std::move(__rhs._M_storage)) |
1074 | { } |
1075 | |
1076 | template<typename _Allocator> |
1077 | promise(allocator_arg_t, const _Allocator& __a) |
1078 | : _M_future(std::allocate_shared<_State>(__a)), |
1079 | _M_storage(__future_base::_S_allocate_result<_Res>(__a)) |
1080 | { } |
1081 | |
1082 | template<typename _Allocator> |
1083 | promise(allocator_arg_t, const _Allocator&, promise&& __rhs) |
1084 | : _M_future(std::move(__rhs._M_future)), |
1085 | _M_storage(std::move(__rhs._M_storage)) |
1086 | { } |
1087 | |
1088 | promise(const promise&) = delete; |
1089 | |
1090 | ~promise() |
1091 | { |
1092 | if (static_cast<bool>(_M_future) && !_M_future.unique()) |
1093 | _M_future->_M_break_promise(std::move(_M_storage)); |
1094 | } |
1095 | |
1096 | // Assignment |
1097 | promise& |
1098 | operator=(promise&& __rhs) noexcept |
1099 | { |
1100 | promise(std::move(__rhs)).swap(*this); |
1101 | return *this; |
1102 | } |
1103 | |
1104 | promise& operator=(const promise&) = delete; |
1105 | |
1106 | void |
1107 | swap(promise& __rhs) noexcept |
1108 | { |
1109 | _M_future.swap(__rhs._M_future); |
1110 | _M_storage.swap(__rhs._M_storage); |
1111 | } |
1112 | |
1113 | // Retrieving the result |
1114 | future<_Res> |
1115 | get_future() |
1116 | { return future<_Res>(_M_future); } |
1117 | |
1118 | // Setting the result |
1119 | void |
1120 | set_value(const _Res& __r) |
1121 | { _M_future->_M_set_result(_State::__setter(this, __r)); } |
1122 | |
1123 | void |
1124 | set_value(_Res&& __r) |
1125 | { _M_future->_M_set_result(_State::__setter(this, std::move(__r))); } |
1126 | |
1127 | void |
1128 | set_exception(exception_ptr __p) |
1129 | { _M_future->_M_set_result(_State::__setter(__p, this)); } |
1130 | |
1131 | void |
1132 | set_value_at_thread_exit(const _Res& __r) |
1133 | { |
1134 | _M_future->_M_set_delayed_result(_State::__setter(this, __r), |
1135 | _M_future); |
1136 | } |
1137 | |
1138 | void |
1139 | set_value_at_thread_exit(_Res&& __r) |
1140 | { |
1141 | _M_future->_M_set_delayed_result( |
1142 | _State::__setter(this, std::move(__r)), _M_future); |
1143 | } |
1144 | |
1145 | void |
1146 | set_exception_at_thread_exit(exception_ptr __p) |
1147 | { |
1148 | _M_future->_M_set_delayed_result(_State::__setter(__p, this), |
1149 | _M_future); |
1150 | } |
1151 | }; |
1152 | |
1153 | template<typename _Res> |
1154 | inline void |
1155 | swap(promise<_Res>& __x, promise<_Res>& __y) noexcept |
1156 | { __x.swap(__y); } |
1157 | |
1158 | template<typename _Res, typename _Alloc> |
1159 | struct uses_allocator<promise<_Res>, _Alloc> |
1160 | : public true_type { }; |
1161 | |
1162 | |
1163 | /// Partial specialization for promise<R&> |
1164 | template<typename _Res> |
1165 | class promise<_Res&> |
1166 | { |
1167 | typedef __future_base::_State_base _State; |
1168 | typedef __future_base::_Result<_Res&> _Res_type; |
1169 | typedef __future_base::_Ptr<_Res_type> _Ptr_type; |
1170 | template<typename, typename> friend class _State::_Setter; |
1171 | friend _State; |
1172 | |
1173 | shared_ptr<_State> _M_future; |
1174 | _Ptr_type _M_storage; |
1175 | |
1176 | public: |
1177 | promise() |
1178 | : _M_future(std::make_shared<_State>()), |
1179 | _M_storage(new _Res_type()) |
1180 | { } |
1181 | |
1182 | promise(promise&& __rhs) noexcept |
1183 | : _M_future(std::move(__rhs._M_future)), |
1184 | _M_storage(std::move(__rhs._M_storage)) |
1185 | { } |
1186 | |
1187 | template<typename _Allocator> |
1188 | promise(allocator_arg_t, const _Allocator& __a) |
1189 | : _M_future(std::allocate_shared<_State>(__a)), |
1190 | _M_storage(__future_base::_S_allocate_result<_Res&>(__a)) |
1191 | { } |
1192 | |
1193 | template<typename _Allocator> |
1194 | promise(allocator_arg_t, const _Allocator&, promise&& __rhs) |
1195 | : _M_future(std::move(__rhs._M_future)), |
1196 | _M_storage(std::move(__rhs._M_storage)) |
1197 | { } |
1198 | |
1199 | promise(const promise&) = delete; |
1200 | |
1201 | ~promise() |
1202 | { |
1203 | if (static_cast<bool>(_M_future) && !_M_future.unique()) |
1204 | _M_future->_M_break_promise(std::move(_M_storage)); |
1205 | } |
1206 | |
1207 | // Assignment |
1208 | promise& |
1209 | operator=(promise&& __rhs) noexcept |
1210 | { |
1211 | promise(std::move(__rhs)).swap(*this); |
1212 | return *this; |
1213 | } |
1214 | |
1215 | promise& operator=(const promise&) = delete; |
1216 | |
1217 | void |
1218 | swap(promise& __rhs) noexcept |
1219 | { |
1220 | _M_future.swap(__rhs._M_future); |
1221 | _M_storage.swap(__rhs._M_storage); |
1222 | } |
1223 | |
1224 | // Retrieving the result |
1225 | future<_Res&> |
1226 | get_future() |
1227 | { return future<_Res&>(_M_future); } |
1228 | |
1229 | // Setting the result |
1230 | void |
1231 | set_value(_Res& __r) |
1232 | { _M_future->_M_set_result(_State::__setter(this, __r)); } |
1233 | |
1234 | void |
1235 | set_exception(exception_ptr __p) |
1236 | { _M_future->_M_set_result(_State::__setter(__p, this)); } |
1237 | |
1238 | void |
1239 | set_value_at_thread_exit(_Res& __r) |
1240 | { |
1241 | _M_future->_M_set_delayed_result(_State::__setter(this, __r), |
1242 | _M_future); |
1243 | } |
1244 | |
1245 | void |
1246 | set_exception_at_thread_exit(exception_ptr __p) |
1247 | { |
1248 | _M_future->_M_set_delayed_result(_State::__setter(__p, this), |
1249 | _M_future); |
1250 | } |
1251 | }; |
1252 | |
1253 | /// Explicit specialization for promise<void> |
1254 | template<> |
1255 | class promise<void> |
1256 | { |
1257 | typedef __future_base::_State_base _State; |
1258 | typedef __future_base::_Result<void> _Res_type; |
1259 | typedef __future_base::_Ptr<_Res_type> _Ptr_type; |
1260 | template<typename, typename> friend class _State::_Setter; |
1261 | friend _State; |
1262 | |
1263 | shared_ptr<_State> _M_future; |
1264 | _Ptr_type _M_storage; |
1265 | |
1266 | public: |
1267 | promise() |
1268 | : _M_future(std::make_shared<_State>()), |
1269 | _M_storage(new _Res_type()) |
1270 | { } |
1271 | |
1272 | promise(promise&& __rhs) noexcept |
1273 | : _M_future(std::move(__rhs._M_future)), |
1274 | _M_storage(std::move(__rhs._M_storage)) |
1275 | { } |
1276 | |
1277 | template<typename _Allocator> |
1278 | promise(allocator_arg_t, const _Allocator& __a) |
1279 | : _M_future(std::allocate_shared<_State>(__a)), |
1280 | _M_storage(__future_base::_S_allocate_result<void>(__a)) |
1281 | { } |
1282 | |
1283 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1284 | // 2095. missing constructors needed for uses-allocator construction |
1285 | template<typename _Allocator> |
1286 | promise(allocator_arg_t, const _Allocator&, promise&& __rhs) |
1287 | : _M_future(std::move(__rhs._M_future)), |
1288 | _M_storage(std::move(__rhs._M_storage)) |
1289 | { } |
1290 | |
1291 | promise(const promise&) = delete; |
1292 | |
1293 | ~promise() |
1294 | { |
1295 | if (static_cast<bool>(_M_future) && !_M_future.unique()) |
1296 | _M_future->_M_break_promise(std::move(_M_storage)); |
1297 | } |
1298 | |
1299 | // Assignment |
1300 | promise& |
1301 | operator=(promise&& __rhs) noexcept |
1302 | { |
1303 | promise(std::move(__rhs)).swap(*this); |
1304 | return *this; |
1305 | } |
1306 | |
1307 | promise& operator=(const promise&) = delete; |
1308 | |
1309 | void |
1310 | swap(promise& __rhs) noexcept |
1311 | { |
1312 | _M_future.swap(__rhs._M_future); |
1313 | _M_storage.swap(__rhs._M_storage); |
1314 | } |
1315 | |
1316 | // Retrieving the result |
1317 | future<void> |
1318 | get_future() |
1319 | { return future<void>(_M_future); } |
1320 | |
1321 | // Setting the result |
1322 | void |
1323 | set_value() |
1324 | { _M_future->_M_set_result(_State::__setter(this)); } |
1325 | |
1326 | void |
1327 | set_exception(exception_ptr __p) |
1328 | { _M_future->_M_set_result(_State::__setter(__p, this)); } |
1329 | |
1330 | void |
1331 | set_value_at_thread_exit() |
1332 | { _M_future->_M_set_delayed_result(_State::__setter(this), _M_future); } |
1333 | |
1334 | void |
1335 | set_exception_at_thread_exit(exception_ptr __p) |
1336 | { |
1337 | _M_future->_M_set_delayed_result(_State::__setter(__p, this), |
1338 | _M_future); |
1339 | } |
1340 | }; |
1341 | |
1342 | template<typename _Ptr_type, typename _Fn, typename _Res> |
1343 | struct __future_base::_Task_setter |
1344 | { |
1345 | // Invoke the function and provide the result to the caller. |
1346 | _Ptr_type operator()() const |
1347 | { |
1348 | __tryif (true) |
1349 | { |
1350 | (*_M_result)->_M_set((*_M_fn)()); |
1351 | } |
1352 | __catch(const __cxxabiv1::__forced_unwind&)if (false) |
1353 | { |
1354 | __throw_exception_again; // will cause broken_promise |
1355 | } |
1356 | __catch(...)if (false) |
1357 | { |
1358 | (*_M_result)->_M_error = current_exception(); |
1359 | } |
1360 | return std::move(*_M_result); |
1361 | } |
1362 | _Ptr_type* _M_result; |
1363 | _Fn* _M_fn; |
1364 | }; |
1365 | |
1366 | template<typename _Ptr_type, typename _Fn> |
1367 | struct __future_base::_Task_setter<_Ptr_type, _Fn, void> |
1368 | { |
1369 | _Ptr_type operator()() const |
1370 | { |
1371 | __tryif (true) |
1372 | { |
1373 | (*_M_fn)(); |
1374 | } |
1375 | __catch(const __cxxabiv1::__forced_unwind&)if (false) |
1376 | { |
1377 | __throw_exception_again; // will cause broken_promise |
1378 | } |
1379 | __catch(...)if (false) |
1380 | { |
1381 | (*_M_result)->_M_error = current_exception(); |
1382 | } |
1383 | return std::move(*_M_result); |
1384 | } |
1385 | _Ptr_type* _M_result; |
1386 | _Fn* _M_fn; |
1387 | }; |
1388 | |
1389 | // Holds storage for a packaged_task's result. |
1390 | template<typename _Res, typename... _Args> |
1391 | struct __future_base::_Task_state_base<_Res(_Args...)> |
1392 | : __future_base::_State_base |
1393 | { |
1394 | typedef _Res _Res_type; |
1395 | |
1396 | template<typename _Alloc> |
1397 | _Task_state_base(const _Alloc& __a) |
1398 | : _M_result(_S_allocate_result<_Res>(__a)) |
1399 | { } |
1400 | |
1401 | // Invoke the stored task and make the state ready. |
1402 | virtual void |
1403 | _M_run(_Args&&... __args) = 0; |
1404 | |
1405 | // Invoke the stored task and make the state ready at thread exit. |
1406 | virtual void |
1407 | _M_run_delayed(_Args&&... __args, weak_ptr<_State_base>) = 0; |
1408 | |
1409 | virtual shared_ptr<_Task_state_base> |
1410 | _M_reset() = 0; |
1411 | |
1412 | typedef __future_base::_Ptr<_Result<_Res>> _Ptr_type; |
1413 | _Ptr_type _M_result; |
1414 | }; |
1415 | |
1416 | // Holds a packaged_task's stored task. |
1417 | template<typename _Fn, typename _Alloc, typename _Res, typename... _Args> |
1418 | struct __future_base::_Task_state<_Fn, _Alloc, _Res(_Args...)> final |
1419 | : __future_base::_Task_state_base<_Res(_Args...)> |
1420 | { |
1421 | template<typename _Fn2> |
1422 | _Task_state(_Fn2&& __fn, const _Alloc& __a) |
1423 | : _Task_state_base<_Res(_Args...)>(__a), |
1424 | _M_impl(std::forward<_Fn2>(__fn), __a) |
1425 | { } |
1426 | |
1427 | private: |
1428 | virtual void |
1429 | _M_run(_Args&&... __args) |
1430 | { |
1431 | auto __boundfn = [&] () -> _Res { |
1432 | return std::__invoke_r<_Res>(_M_impl._M_fn, |
1433 | std::forward<_Args>(__args)...); |
1434 | }; |
1435 | this->_M_set_result(_S_task_setter(this->_M_result, __boundfn)); |
1436 | } |
1437 | |
1438 | virtual void |
1439 | _M_run_delayed(_Args&&... __args, weak_ptr<_State_base> __self) |
1440 | { |
1441 | auto __boundfn = [&] () -> _Res { |
1442 | return std::__invoke_r<_Res>(_M_impl._M_fn, |
1443 | std::forward<_Args>(__args)...); |
1444 | }; |
1445 | this->_M_set_delayed_result(_S_task_setter(this->_M_result, __boundfn), |
1446 | std::move(__self)); |
1447 | } |
1448 | |
1449 | virtual shared_ptr<_Task_state_base<_Res(_Args...)>> |
1450 | _M_reset(); |
1451 | |
1452 | struct _Impl : _Alloc |
1453 | { |
1454 | template<typename _Fn2> |
1455 | _Impl(_Fn2&& __fn, const _Alloc& __a) |
1456 | : _Alloc(__a), _M_fn(std::forward<_Fn2>(__fn)) { } |
1457 | _Fn _M_fn; |
1458 | } _M_impl; |
1459 | }; |
1460 | |
1461 | template<typename _Signature, typename _Fn, |
1462 | typename _Alloc = std::allocator<int>> |
1463 | static shared_ptr<__future_base::_Task_state_base<_Signature>> |
1464 | __create_task_state(_Fn&& __fn, const _Alloc& __a = _Alloc()) |
1465 | { |
1466 | typedef typename decay<_Fn>::type _Fn2; |
1467 | typedef __future_base::_Task_state<_Fn2, _Alloc, _Signature> _State; |
1468 | return std::allocate_shared<_State>(__a, std::forward<_Fn>(__fn), __a); |
1469 | } |
1470 | |
1471 | template<typename _Fn, typename _Alloc, typename _Res, typename... _Args> |
1472 | shared_ptr<__future_base::_Task_state_base<_Res(_Args...)>> |
1473 | __future_base::_Task_state<_Fn, _Alloc, _Res(_Args...)>::_M_reset() |
1474 | { |
1475 | return __create_task_state<_Res(_Args...)>(std::move(_M_impl._M_fn), |
1476 | static_cast<_Alloc&>(_M_impl)); |
1477 | } |
1478 | |
1479 | /// packaged_task |
1480 | template<typename _Res, typename... _ArgTypes> |
1481 | class packaged_task<_Res(_ArgTypes...)> |
1482 | { |
1483 | typedef __future_base::_Task_state_base<_Res(_ArgTypes...)> _State_type; |
1484 | shared_ptr<_State_type> _M_state; |
1485 | |
1486 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1487 | // 3039. Unnecessary decay in thread and packaged_task |
1488 | template<typename _Fn, typename _Fn2 = __remove_cvref_t<_Fn>> |
1489 | using __not_same |
1490 | = typename enable_if<!is_same<packaged_task, _Fn2>::value>::type; |
1491 | |
1492 | public: |
1493 | // Construction and destruction |
1494 | packaged_task() noexcept { } |
1495 | |
1496 | template<typename _Fn, typename = __not_same<_Fn>> |
1497 | explicit |
1498 | packaged_task(_Fn&& __fn) |
1499 | : _M_state( |
1500 | __create_task_state<_Res(_ArgTypes...)>(std::forward<_Fn>(__fn))) |
1501 | { } |
1502 | |
1503 | #if __cplusplus201703L < 201703L |
1504 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1505 | // 2097. packaged_task constructors should be constrained |
1506 | // 2407. [this constructor should not be] explicit |
1507 | // 2921. packaged_task and type-erased allocators |
1508 | template<typename _Fn, typename _Alloc, typename = __not_same<_Fn>> |
1509 | packaged_task(allocator_arg_t, const _Alloc& __a, _Fn&& __fn) |
1510 | : _M_state(__create_task_state<_Res(_ArgTypes...)>( |
1511 | std::forward<_Fn>(__fn), __a)) |
1512 | { } |
1513 | |
1514 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1515 | // 2095. missing constructors needed for uses-allocator construction |
1516 | template<typename _Allocator> |
1517 | packaged_task(allocator_arg_t, const _Allocator& __a) noexcept |
1518 | { } |
1519 | |
1520 | template<typename _Allocator> |
1521 | packaged_task(allocator_arg_t, const _Allocator&, |
1522 | const packaged_task&) = delete; |
1523 | |
1524 | template<typename _Allocator> |
1525 | packaged_task(allocator_arg_t, const _Allocator&, |
1526 | packaged_task&& __other) noexcept |
1527 | { this->swap(__other); } |
1528 | #endif |
1529 | |
1530 | ~packaged_task() |
1531 | { |
1532 | if (static_cast<bool>(_M_state) && !_M_state.unique()) |
1533 | _M_state->_M_break_promise(std::move(_M_state->_M_result)); |
1534 | } |
1535 | |
1536 | // No copy |
1537 | packaged_task(const packaged_task&) = delete; |
1538 | packaged_task& operator=(const packaged_task&) = delete; |
1539 | |
1540 | // Move support |
1541 | packaged_task(packaged_task&& __other) noexcept |
1542 | { this->swap(__other); } |
1543 | |
1544 | packaged_task& operator=(packaged_task&& __other) noexcept |
1545 | { |
1546 | packaged_task(std::move(__other)).swap(*this); |
1547 | return *this; |
1548 | } |
1549 | |
1550 | void |
1551 | swap(packaged_task& __other) noexcept |
1552 | { _M_state.swap(__other._M_state); } |
1553 | |
1554 | bool |
1555 | valid() const noexcept |
1556 | { return static_cast<bool>(_M_state); } |
1557 | |
1558 | // Result retrieval |
1559 | future<_Res> |
1560 | get_future() |
1561 | { return future<_Res>(_M_state); } |
1562 | |
1563 | // Execution |
1564 | void |
1565 | operator()(_ArgTypes... __args) |
1566 | { |
1567 | __future_base::_State_base::_S_check(_M_state); |
1568 | _M_state->_M_run(std::forward<_ArgTypes>(__args)...); |
1569 | } |
1570 | |
1571 | void |
1572 | make_ready_at_thread_exit(_ArgTypes... __args) |
1573 | { |
1574 | __future_base::_State_base::_S_check(_M_state); |
1575 | _M_state->_M_run_delayed(std::forward<_ArgTypes>(__args)..., _M_state); |
1576 | } |
1577 | |
1578 | void |
1579 | reset() |
1580 | { |
1581 | __future_base::_State_base::_S_check(_M_state); |
1582 | packaged_task __tmp; |
1583 | __tmp._M_state = _M_state; |
1584 | _M_state = _M_state->_M_reset(); |
1585 | } |
1586 | }; |
1587 | |
1588 | /// swap |
1589 | template<typename _Res, typename... _ArgTypes> |
1590 | inline void |
1591 | swap(packaged_task<_Res(_ArgTypes...)>& __x, |
1592 | packaged_task<_Res(_ArgTypes...)>& __y) noexcept |
1593 | { __x.swap(__y); } |
1594 | |
1595 | #if __cplusplus201703L < 201703L |
1596 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1597 | // 2976. Dangling uses_allocator specialization for packaged_task |
1598 | template<typename _Res, typename _Alloc> |
1599 | struct uses_allocator<packaged_task<_Res>, _Alloc> |
1600 | : public true_type { }; |
1601 | #endif |
1602 | |
1603 | // Shared state created by std::async(). |
1604 | // Holds a deferred function and storage for its result. |
1605 | template<typename _BoundFn, typename _Res> |
1606 | class __future_base::_Deferred_state final |
1607 | : public __future_base::_State_base |
1608 | { |
1609 | public: |
1610 | explicit |
1611 | _Deferred_state(_BoundFn&& __fn) |
1612 | : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn)) |
1613 | { } |
1614 | |
1615 | private: |
1616 | typedef __future_base::_Ptr<_Result<_Res>> _Ptr_type; |
1617 | _Ptr_type _M_result; |
1618 | _BoundFn _M_fn; |
1619 | |
1620 | // Run the deferred function. |
1621 | virtual void |
1622 | _M_complete_async() |
1623 | { |
1624 | // Multiple threads can call a waiting function on the future and |
1625 | // reach this point at the same time. The call_once in _M_set_result |
1626 | // ensures only the first one run the deferred function, stores the |
1627 | // result in _M_result, swaps that with the base _M_result and makes |
1628 | // the state ready. Tell _M_set_result to ignore failure so all later |
1629 | // calls do nothing. |
1630 | _M_set_result(_S_task_setter(_M_result, _M_fn), true); |
1631 | } |
1632 | |
1633 | // Caller should check whether the state is ready first, because this |
1634 | // function will return true even after the deferred function has run. |
1635 | virtual bool _M_is_deferred_future() const { return true; } |
1636 | }; |
1637 | |
1638 | // Common functionality hoisted out of the _Async_state_impl template. |
1639 | class __future_base::_Async_state_commonV2 |
1640 | : public __future_base::_State_base |
1641 | { |
1642 | protected: |
1643 | ~_Async_state_commonV2() = default; |
1644 | |
1645 | // Make waiting functions block until the thread completes, as if joined. |
1646 | // |
1647 | // This function is used by wait() to satisfy the first requirement below |
1648 | // and by wait_for() / wait_until() to satisfy the second. |
1649 | // |
1650 | // [futures.async]: |
1651 | // |
1652 | // - a call to a waiting function on an asynchronous return object that |
1653 | // shares the shared state created by this async call shall block until |
1654 | // the associated thread has completed, as if joined, or else time out. |
1655 | // |
1656 | // - the associated thread completion synchronizes with the return from |
1657 | // the first function that successfully detects the ready status of the |
1658 | // shared state or with the return from the last function that releases |
1659 | // the shared state, whichever happens first. |
1660 | virtual void _M_complete_async() { _M_join(); } |
1661 | |
1662 | void _M_join() { std::call_once(_M_once, &thread::join, &_M_thread); } |
1663 | |
1664 | thread _M_thread; |
1665 | once_flag _M_once; |
1666 | }; |
1667 | |
1668 | // Shared state created by std::async(). |
1669 | // Starts a new thread that runs a function and makes the shared state ready. |
1670 | template<typename _BoundFn, typename _Res> |
1671 | class __future_base::_Async_state_impl final |
1672 | : public __future_base::_Async_state_commonV2 |
1673 | { |
1674 | public: |
1675 | explicit |
1676 | _Async_state_impl(_BoundFn&& __fn) |
1677 | : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn)) |
1678 | { |
1679 | _M_thread = std::thread{ [this] { |
1680 | __tryif (true) |
1681 | { |
1682 | _M_set_result(_S_task_setter(_M_result, _M_fn)); |
1683 | } |
1684 | __catch (const __cxxabiv1::__forced_unwind&)if (false) |
1685 | { |
1686 | // make the shared state ready on thread cancellation |
1687 | if (static_cast<bool>(_M_result)) |
1688 | this->_M_break_promise(std::move(_M_result)); |
1689 | __throw_exception_again; |
1690 | } |
1691 | } }; |
1692 | } |
1693 | |
1694 | // Must not destroy _M_result and _M_fn until the thread finishes. |
1695 | // Call join() directly rather than through _M_join() because no other |
1696 | // thread can be referring to this state if it is being destroyed. |
1697 | ~_Async_state_impl() { if (_M_thread.joinable()) _M_thread.join(); } |
1698 | |
1699 | private: |
1700 | typedef __future_base::_Ptr<_Result<_Res>> _Ptr_type; |
1701 | _Ptr_type _M_result; |
1702 | _BoundFn _M_fn; |
1703 | }; |
1704 | |
1705 | template<typename _BoundFn> |
1706 | inline std::shared_ptr<__future_base::_State_base> |
1707 | __future_base::_S_make_deferred_state(_BoundFn&& __fn) |
1708 | { |
1709 | typedef typename remove_reference<_BoundFn>::type __fn_type; |
1710 | typedef _Deferred_state<__fn_type> __state_type; |
1711 | return std::make_shared<__state_type>(std::move(__fn)); |
1712 | } |
1713 | |
1714 | template<typename _BoundFn> |
1715 | inline std::shared_ptr<__future_base::_State_base> |
1716 | __future_base::_S_make_async_state(_BoundFn&& __fn) |
1717 | { |
1718 | typedef typename remove_reference<_BoundFn>::type __fn_type; |
1719 | typedef _Async_state_impl<__fn_type> __state_type; |
1720 | return std::make_shared<__state_type>(std::move(__fn)); |
1721 | } |
1722 | |
1723 | |
1724 | /// async |
1725 | template<typename _Fn, typename... _Args> |
1726 | _GLIBCXX_NODISCARD[[__nodiscard__]] future<__async_result_of<_Fn, _Args...>> |
1727 | async(launch __policy, _Fn&& __fn, _Args&&... __args) |
1728 | { |
1729 | std::shared_ptr<__future_base::_State_base> __state; |
1730 | if ((__policy & launch::async) == launch::async) |
1731 | { |
1732 | __tryif (true) |
1733 | { |
1734 | __state = __future_base::_S_make_async_state( |
1735 | std::thread::__make_invoker(std::forward<_Fn>(__fn), |
1736 | std::forward<_Args>(__args)...) |
1737 | ); |
1738 | } |
1739 | #if __cpp_exceptions |
1740 | catch(const system_error& __e) |
1741 | { |
1742 | if (__e.code() != errc::resource_unavailable_try_again |
1743 | || (__policy & launch::deferred) != launch::deferred) |
1744 | throw; |
1745 | } |
1746 | #endif |
1747 | } |
1748 | if (!__state) |
1749 | { |
1750 | __state = __future_base::_S_make_deferred_state( |
1751 | std::thread::__make_invoker(std::forward<_Fn>(__fn), |
1752 | std::forward<_Args>(__args)...)); |
1753 | } |
1754 | return future<__async_result_of<_Fn, _Args...>>(__state); |
1755 | } |
1756 | |
1757 | /// async, potential overload |
1758 | template<typename _Fn, typename... _Args> |
1759 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline future<__async_result_of<_Fn, _Args...>> |
1760 | async(_Fn&& __fn, _Args&&... __args) |
1761 | { |
1762 | return std::async(launch::async|launch::deferred, |
1763 | std::forward<_Fn>(__fn), |
1764 | std::forward<_Args>(__args)...); |
1765 | } |
1766 | |
1767 | #endif // _GLIBCXX_ASYNC_ABI_COMPAT |
1768 | #endif // _GLIBCXX_HAS_GTHREADS |
1769 | |
1770 | // @} group futures |
1771 | _GLIBCXX_END_NAMESPACE_VERSION |
1772 | } // namespace |
1773 | |
1774 | #endif // C++11 |
1775 | |
1776 | #endif // _GLIBCXX_FUTURE |