@@ -187,6 +187,25 @@ struct _State_deleter : _Deleter_base<_Ty> { // manage allocator and deletion st
187187 _Alloc _My_alloc;
188188};
189189
190+ template <class _Ty>
191+ struct __declspec(novtable) _Clonable_deleter_base : _Deleter_base<_Ty> {
192+ // TRANSITION, ABI, should be fused into _Deleter_base
193+ virtual _Associated_state<_Ty>* _Move_clone(_Associated_state<_Ty>&&) = 0;
194+ };
195+
196+ template <class _Ty, class _Derived, class _Alloc>
197+ struct _State_deleter_v2 : _Clonable_deleter_base<_Ty> { // manage allocator and deletion state objects
198+ _State_deleter_v2(const _Alloc& _Al) : _My_alloc(_Al) {}
199+
200+ _State_deleter_v2(const _State_deleter_v2&) = delete;
201+ _State_deleter_v2& operator=(const _State_deleter_v2&) = delete;
202+
203+ void _Delete(_Associated_state<_Ty>* _State) noexcept override;
204+ _Associated_state<_Ty>* _Move_clone(_Associated_state<_Ty>&& _Src) override;
205+
206+ _Alloc _My_alloc;
207+ };
208+
190209template <class _Ty>
191210union _Result_holder {
192211 _Result_holder() noexcept {}
@@ -389,6 +408,10 @@ public:
389408 }
390409 }
391410
411+ _Mydel* _Get_deleter() const noexcept { // get deleter for cloning
412+ return _Deleter;
413+ }
414+
392415protected:
393416 void _Maybe_run_deferred_function(unique_lock<mutex>& _Lock) { // run a deferred function if not already done
394417 if (!_Running) { // run the function
@@ -495,19 +518,13 @@ public:
495518 template <class _Fty2, enable_if_t<!is_same_v<_Remove_cvref_t<_Fty2>, _Function_type>, int> = 0>
496519 explicit _Packaged_state(_Fty2&& _Fnarg) : _Fn(_Secret_copyability_ignoring_tag{}, _STD forward<_Fty2>(_Fnarg)) {}
497520
498- #if _HAS_FUNCTION_ALLOCATOR_SUPPORT
499- template <class _Alloc>
500- _Packaged_state(const _Function_type& _Fnarg, const _Alloc& _Al, _Mydel* _Dp)
501- : _Mybase(_Dp), _Fn(allocator_arg, _Al, _Fnarg) {}
502-
503521 template <class _Alloc>
504522 _Packaged_state(_Function_type&& _Fnarg, const _Alloc& _Al, _Mydel* _Dp)
505- : _Mybase(_Dp), _Fn(allocator_arg, _Al, _STD move(_Fnarg)) {}
523+ : _Mybase(_Dp), _Fn(_Secret_copyability_ignoring_tag{}, allocator_arg, _Al, _STD move(_Fnarg)) {}
506524
507525 template <class _Fty2, class _Alloc, enable_if_t<!is_same_v<_Remove_cvref_t<_Fty2>, _Function_type>, int> = 0>
508526 _Packaged_state(_Fty2&& _Fnarg, const _Alloc& _Al, _Mydel* _Dp)
509527 : _Mybase(_Dp), _Fn(_Secret_copyability_ignoring_tag{}, allocator_arg, _Al, _STD forward<_Fty2>(_Fnarg)) {}
510- #endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
511528
512529 void _Call_deferred(_ArgTypes... _Args) { // set deferred call
513530 _TRY_BEGIN
@@ -543,10 +560,7 @@ public:
543560 _CATCH_END
544561 }
545562
546- const auto& _Get_fn() const& {
547- return _Fn;
548- }
549- auto&& _Get_fn() && noexcept {
563+ _Function_type&& _Get_fn() && noexcept {
550564 return _STD move(_Fn);
551565 }
552566
@@ -569,11 +583,14 @@ _Associated_state<_Ty>* _Make_associated_state(const _Alloc& _Al) {
569583 return _STD _Unfancy(_Res.release()); // ownership transferred to caller
570584}
571585
572- #if _HAS_FUNCTION_ALLOCATOR_SUPPORT
573586template <class _Pack_state, class _Fty2, class _Alloc>
574587_Pack_state* _Make_packaged_state(_Fty2&& _Fnarg, const _Alloc& _Al) {
575588 // construct a _Packaged_state object with an allocator from an rvalue function object
576- using _Delty = _State_deleter<typename _Pack_state::_Mybase::_State_type, _Pack_state, _Alloc>;
589+ #ifdef _CPPRTTI // TRANSITION, ABI, should not rely on RTTI
590+ using _Delty = _State_deleter_v2<typename _Pack_state::_Mybase::_State_type, _Pack_state, _Alloc>;
591+ #else // ^^^ defined(_CPPRTTI) / !defined(_CPPRTTI) vvv
592+ using _Delty = _State_deleter<typename _Pack_state::_Mybase::_State_type, _Pack_state, _Alloc>;
593+ #endif // ^^^ !defined(_CPPRTTI) ^^^
577594 using _Aldelty = _Rebind_alloc_t<_Alloc, _Delty>;
578595 using _Alstate = _Rebind_alloc_t<_Alloc, _Pack_state>;
579596
@@ -584,7 +601,26 @@ _Pack_state* _Make_packaged_state(_Fty2&& _Fnarg, const _Alloc& _Al) {
584601 (void) _Del.release(); // ownership of _Del.get() now transferred to _Res
585602 return _STD _Unfancy(_Res.release()); // ownership transferred to caller
586603}
587- #endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
604+
605+ template <class _Ty, class _Derived, class _Alloc>
606+ void _State_deleter_v2<_Ty, _Derived, _Alloc>::_Delete(_Associated_state<_Ty>* _State) noexcept {
607+ // delete _State and this using stored allocator
608+ using _State_allocator = _Rebind_alloc_t<_Alloc, _Derived>;
609+ _State_allocator _St_alloc(_My_alloc);
610+
611+ using _Deleter_allocator = _Rebind_alloc_t<_Alloc, _State_deleter_v2>;
612+ _Deleter_allocator _Del_alloc(_My_alloc);
613+
614+ _Derived* _Ptr = static_cast<_Derived*>(_State);
615+
616+ _STD _Delete_plain_internal(_St_alloc, _Ptr);
617+ _STD _Delete_plain_internal(_Del_alloc, this);
618+ }
619+
620+ template <class _Ty, class _Derived, class _Alloc>
621+ _Associated_state<_Ty>* _State_deleter_v2<_Ty, _Derived, _Alloc>::_Move_clone(_Associated_state<_Ty>&& _Src) {
622+ return _STD _Make_packaged_state<_Derived>(static_cast<_Derived&&>(_Src)._Get_fn(), _My_alloc);
623+ }
588624
589625template <class _Rx>
590626class _Deferred_async_state : public _Packaged_state<_Rx()> {
@@ -1185,9 +1221,6 @@ private:
11851221 _Promise<int> _MyPromise;
11861222};
11871223
1188- template <class _Ty, class _Alloc>
1189- struct uses_allocator<promise<_Ty>, _Alloc> : true_type {};
1190-
11911224_EXPORT_STD template <class _Ty>
11921225void swap(promise<_Ty>& _Left, promise<_Ty>& _Right) noexcept {
11931226 _Left.swap(_Right);
@@ -1211,21 +1244,19 @@ public:
12111244 template <class _Fty2, enable_if_t<!is_same_v<_Remove_cvref_t<_Fty2>, packaged_task>, int> = 0>
12121245 explicit packaged_task(_Fty2&& _Fnarg) : _MyPromise(new _MyStateType(_STD forward<_Fty2>(_Fnarg))) {
12131246 static_assert(_Is_invocable_r<_Ret, decay_t<_Fty2>&, _ArgTypes...>::value,
1214- "The function object must be callable with _ArgTypes... and return _Ret (N4988 [futures.task.members]/3 ).");
1247+ "The function object must be callable with _ArgTypes... and return _Ret (N5014 [futures.task.members]/4 ).");
12151248 }
12161249
12171250 packaged_task(packaged_task&&) noexcept = default;
12181251
12191252 packaged_task& operator=(packaged_task&&) noexcept = default;
12201253
1221- #if _HAS_FUNCTION_ALLOCATOR_SUPPORT
12221254 template <class _Fty2, class _Alloc, enable_if_t<!is_same_v<_Remove_cvref_t<_Fty2>, packaged_task>, int> = 0>
1223- packaged_task(allocator_arg_t, const _Alloc& _Al, _Fty2&& _Fnarg)
1255+ explicit packaged_task(allocator_arg_t, const _Alloc& _Al, _Fty2&& _Fnarg)
12241256 : _MyPromise(_STD _Make_packaged_state<_MyStateType>(_STD forward<_Fty2>(_Fnarg), _Al)) {
12251257 static_assert(_Is_invocable_r<_Ret, decay_t<_Fty2>&, _ArgTypes...>::value,
1226- "The function object must be callable with _ArgTypes... and return _Ret (N4140 [futures.task.members]/2 ).");
1258+ "The function object must be callable with _ArgTypes... and return _Ret (N5014 [futures.task.members]/4 ).");
12271259 }
1228- #endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
12291260
12301261 ~packaged_task() noexcept {
12311262 _MyPromise._Get_state()._Abandon();
@@ -1270,7 +1301,20 @@ public:
12701301 void reset() { // reset to newly constructed state
12711302 _MyStateManagerType& _State_mgr = _MyPromise._Get_state_for_set();
12721303 _MyStateType& _MyState = *static_cast<_MyStateType*>(_State_mgr._Ptr());
1273- _MyPromiseType _New_promise(new _MyStateType(_STD move(_MyState)._Get_fn()));
1304+
1305+ const auto _New_state_ptr = [&_MyState]() -> _Associated_state<_P_arg_type_t<_Ret>>* {
1306+ #ifdef _CPPRTTI // TRANSITION, ABI, should not rely on RTTI
1307+ using _Clonable_deleter_t = _Clonable_deleter_base<_P_arg_type_t<_Ret>>;
1308+ if (const auto _Clonable_deleter = dynamic_cast<_Clonable_deleter_t*>(_MyState._Get_deleter())) {
1309+ return _Clonable_deleter->_Move_clone(_STD move(_MyState));
1310+ } else {
1311+ return new _MyStateType(_STD move(_MyState)._Get_fn());
1312+ }
1313+ #else // ^^^ defined(_CPPRTTI) / !defined(_CPPRTTI) vvv
1314+ return new _MyStateType(_STD move(_MyState)._Get_fn());
1315+ #endif // ^^^ !defined(_CPPRTTI) ^^^
1316+ }();
1317+ _MyPromiseType _New_promise{_New_state_ptr};
12741318 _MyPromise._Get_state()._Abandon();
12751319 _MyPromise._Swap(_New_promise);
12761320 }
@@ -1294,11 +1338,6 @@ template <class _Fx>
12941338packaged_task(_Fx) -> packaged_task<typename _Deduce_signature<_Fx>::type>;
12951339#endif // _HAS_CXX17
12961340
1297- #if _HAS_FUNCTION_ALLOCATOR_SUPPORT
1298- template <class _Ty, class _Alloc>
1299- struct uses_allocator<packaged_task<_Ty>, _Alloc> : true_type {};
1300- #endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
1301-
13021341_EXPORT_STD template <class _Ty>
13031342void swap(packaged_task<_Ty>& _Left, packaged_task<_Ty>& _Right) noexcept {
13041343 _Left.swap(_Right);
0 commit comments